jdk1.8、数据类型、面向对象、注解、常用类库
参考资料
1.1 jdk1.8特性
- 接口:提供默认方法和静态方法
- Lambda 表达式:把函数作为一个方法的参数
- 函数式接口
- 方法引用 类名::方法名
- Stream
- 中间操作:sorted、filter、map、flatMap、limit、peel、distinct、substream
- 终止操作:collect、forEach、toArray、reduce、min、max、count、anyMatch、allMatch、noneMatch、findFirst、findAny
- Collectors: Collectors.toList()、Collectors.groupingBy
- Optional
- 容器对象,保存类型T的值,或仅保存null
- ofNullable
- orElse
- map
- Date/Time API:LocalDate/LocalTime
- 重复注解
- 扩展注解的支持
- Base64
- JavaFX
- 其它
1.2 数据类型
JVM启动时会创建9个对象池,用来存储8个基本数据类型的包装类对象和String对象
1.2.1.基本数据类型
boolean:布尔只能用true、false表示真假
Byte 数据范围表示
浮点类型
char(2字节)
int、float(4字节 byte=4*8位bite)
Long、double(8字节 =64bite)
float f=(float)3.4 或float f = 3.4f 在java里面,没小数点的默认是int,有小数点的默认是 double;
1B=1字节(byte)=8位(bit);
1KB=1024B=1024*8bit
1.2.基本数据类型及包装类
int(基本数据类型,栈内存)->Interger(类对象,堆内存) 等…….
1.3.自动拆箱和装箱(编译阶段)
自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对 象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱
1.2.2.String(final修饰的类)、StringBuilder 、 StringBuffer
- 运行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String
- 在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的
- StringBuffer中很多方法可以带有synchronized(同步)关键字,所以可以保证线程是安全的
- StringBuilder对象内容可以修改,不生成新的对象,在内存使用上要优于String类,在实际使用时,如果经常需要对一个字符串进行修改,例如插入、删除等操作,使用StringBuilder要更加适合一些。
- String对象一旦产生后不可以被修改,重新赋值是两个对象了。
示例:
- 1).String str1 = “abc” //创建对象,返回引用
- String str2 = “abc” //String对象池中搜索到abc,不再创建,直接返回引用
- String str3 = new String (”abc” ) //直接创建新对象,并返回引用
- 2).StringBuffer和StringBuilder: 大量拼接字符串时用,提高效率,并且StringBuffer线程安全
- 3).StringBuilder和String是一个变量和常量的关系。 StringBuilder效率高
1.2.3.Date
1.2.4.数组:长度固定
- int[][] intArr = new int[5][10];
- int intArray[ ][ ] = { {1,2}, {2,3}, {4,5} };
- String[] cArray = new String[]{“a”,”b”,”c”,”d”,”e”};
- new a[5],创建一个数组示例,长度为5,并未创建5个对象
1.2.5.枚举
- 1.所有枚举类都是继承java.lang.Enum类,枚举enum是同class,interface同一级别的特性,
- 2.它们都可以定义一些属性和方法,不过,因为java是单继承,所以枚举不能再继承其它类,但枚举可以实现接口。
- 3.枚举的定义
- 1).枚举常量没有任何修饰符
- 2).每个常量以“,”分隔,以“;”结束枚举常量的描述。
- 3).枚举常量必须定义在所有方法或者构造器之前。
1.2.6.类、对象
“==”和equal()区别
Hashcode()和equals()
- hashCode()方法和equal()方法的作用一样,都用来对比两个对象是否相等
- equal()相等的两个对象hashCode()肯定相等,用equal()绝对可靠,但复杂
- hashCode()相等的两个对象equal()不一定相等
- 先比较hashcode再比较equal,效率高且可靠
1.4 面向对象
https://course.tianmaying.com/java-basic+abstract-class-and-interface#2
如果我们要定义的一个类没有足够的信息来描述一个具体的对象,还需要其他的具体类来支持,这个时候我们可以考虑使用抽象类(abstract)
1.4.1 抽象类、抽象方法、接口类、继承的概念
1.1).抽象类:类定义的前面增加 abstract 关键字,就表明一个类是抽象类
- 类中至少包含了一个抽象(abstract)方法
- 抽象类不能实例化对象,即无法通过new Graph()来创建对象, 也无法直接;
- 抽象类必须被继承(extends),才能被实例化使用,由于抽象类不能实例化对象;
- 类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样
- 在抽象类中可以为部分方法提供默认的实现,避免在子类中重复实现;但java抽象类不支持多继承
1.2).抽象方法:abstract声明抽象方法,
- 抽象方法只包含方法名,没有方法体,没有定义,方法名后直接跟一个分号,而不是花括号
- 如果一个类包含抽象方法,那么该类必须是抽象类
- 任何子类必须重写父类的抽象方法,否则就必须声明自身为抽象类
1.3).接口(可实现多个接口):类定义的前面增加 Interface 关键字,就表明一个类是接口类
- 接口是一组抽象方法的集合,类中方法都是抽象方法
- jdk1.8后可以有default默认实现方法、static静态方法
- 接口在某种意义上是特殊的抽象类,所有的东西都是抽象的
- 接口也和抽象类一样,无法被实例化,但是可以被实现(implements)
- 接口的实现类,必须实现接口内所有方法,否则就必须声明为抽象类
- jdk1.8后,因为接口可以有default默认方法实现,所以可以不必须实现所有接口中的抽象方法
- 接口支持多重实现,即一个类可以同时实现多个接口
- 接口中的方法是不能为静态static的
- jdk1.8后可以有default默认实现方法、static静态方法
- 接口中可声明变量,一般是final和static类型,要以常量初始化,实现类不能改变接口中的变量
- 接口访问权限有:接口类可以是public权限和默认权限,若接口的访问权限是public,其方法和变量都是public
- 接口类型变量,可以引用到一个该接口的实现类的对象, 例如:
Map<String,object> map = new HashMap<String,Object>();
List<String> list = new ArrayList<String> ();
2).继承: extends(java 只能单继承)
- 1).Java中的继承是单继承的,也就是说一个子类只能继承一个父类。
- 2).子类会继承父类中的除构造函数以外的所有非private成员方法,以及所有非private成员变量。
- 3).生成子类实例时,Java默认先调用父类的无参构造方法,再调用子类构造方法,生成子类对象。
- 4).this表示对当前对象的引用,而super表示对父类对象的引用。
- 5).在子类的构造函数中,一般第一条语句是super();,表示调用父类构造函数。也可以调用父类有参数的构造函数,比如super(name);。
- 6).若一个类的构造函数的第一语句既不是this()也不是super()时,就会隐含的调用super()。
作用:(1)代码复用;(2)建立抽象层次,更容易扩展
3).多态
父类的引用指向子类对象:父类类型 引用名称 = new 子类类型
多态成员变量
当子类中出现同名的成员变量时,多态调用该变量时: 编译时期:参考的是引用型变量所属的类中是否有被调用的成员变量。没有,编译失败。 运行时期:也是调用引用型变量所属的类中的成员变量。 也就是编译和运行都参考等号的左边
多态成员方法
- 编译时期:参考引用变量所属的类,如果类中没有调用的方法。编译失败。
- 运行时期:参考引用变量所指的对象所属的类,并运行对象所属类中的成员方法。
- 也就是编译看左边(父类是否拥有该方法),运行看右边(静态都看左边)
执行 new Sub();
在创造子类的过程中首先创建父类对象,然后才能创建子类。
创建父类即默认调用Base()方法,在方法中调用callName()方法,由于子类中存在此方法,则被调用的callName()方法是子类中的方法,此时子类还未构造,所以变量baseName的值为null
先成员变量再构造方法,先父类再子类
多态表现:有同名方法执行子类的
执行 Base b = new Sub();时,由于多态编译时表现为Base类特性,运行时表现为Sub类特性,不管是哪种状态都会调用Base构造器执行 callName()方法;
执行方法时,由于多态表现为子类特性,所以会先在子类是否有 callName();而此时子类尚未初始化(执行完父类构造器后才会开始执行子类),如果有 就 执行(此时, 因为还没有调用子类构造函数, 所以子类的 baseName 输出为 null),没有再去父类寻找。
4).封装
其核心思想就是隐藏不需要对外公开的属性和方法,以减少对外耦合,包证数据的安全和程序的稳定。
Java访问权限关键字:
本类内部 | 本包 | 子类 | 外部包 | |
---|---|---|---|---|
public | ✓ | ✓ | ✓ | ✓ |
protected | ✓ | ✓ | ✓ | × |
default | ✓ | ✓ | × | × |
private | ✓ | × | × | × |
说明:Java访问权限控制是在编译层,不会再类文件中留下痕迹。通过反射机制,还是可以访问类的私有成员。
1.4.2 抽象类和接口类的异同点
相同点:
都不能被实例化
- 1.都包含抽象方法,用于描述系统能提供哪些服务,而这些服务是由子类来提供实现的
- 2.设计上,两者都代表系统的抽象层,当使用一棵继承树上的类时,应尽量把引用变量声明为继承树的上层抽象类型,
这样可以提高两个系统之间的松耦合
不同点:
- 抽象类可以为部分方法提供默认实现,避免在子类中重复实现;接口不能提供任何方法的实现
- 抽象类不支持多继承,但是接口支持多继承(实现多个接口)。
- 接口代表了接口定义者和接口实现者的一种契约;而抽象类和具体类一般而言是一种继承关系;
1.4.3 类继承(单继承)和接口继承(可多继承)
- java类是单继承的。classB Extends classA
- java接口可以多继承。Interface3 Extends Interface0, Interface1, interface……
不允许类多重继承的主要原因是,如果A同时继承B和C,而B和C同时有一个D方法,A如何决定该继承那一个呢?
但接口不存在这样的问题,接口全都是抽象方法继承谁都无所谓,所以接口可以继承多个接口。
1.4.4 static、final
1.static :
成员变量前加static修饰符外,我们还可以在成员方法前加修饰符,表明该方法与某个具体实例无关,仅仅是该类的一个公共方法。
声明成static的方法有几条限制:
- 仅能调用其他的static方法。
- 只能访问static数据。
- 不能以任何方式引用this或super
- 静态方法可以直接通过类名调用,任何的该类的实例也都可以调用它的静态方法,因此静态方法中不能用this和super关键字。
JAVA中STATIC{}语句块详解:
static{}(即static块),会在类被加载的时候执行且仅会被执行一次,
一般用来初始化静态变量和调用静态方法
2.final
变量声明为final,目的是阻止它的内容被修改。这意味着在声明final变量的时候,必须初始化它
- 被final修饰的方法可以被子类继承,不能被子类的方法覆盖
- final定义的类不能继承,而abstract抽象类,需要继承 ,不可共存
- final不能修饰构造方法。
- 父类中的private成员方法是不能被子类覆盖的,所有有private限制的成员方法默认也是final的
使用final修饰方法除了不想让子类覆盖之外,还有一个原因就是高效,Java编译器在遇到final关键字修饰的方法时会使用内联机制,省去函数调用的开销,大大提高执行效率。
final变量的所有字符选择大写是一个普遍的编码约定,用final修饰的变量在实例中不占用内存,它实质上是一个常数
1.4.5 类加载、类实例化过程
类加载:
Java命令的作用是启动虚拟机,虚拟机通过输入流,从磁盘上将字节码文件(.class文件)中的内容读入虚拟机,并保存起来的过程就是类加载。
类加载特性 :
*在虚拟机的生命周期中一个类只被加载一次。 *类加载的原则:延迟加载,能少加载就少加载,因为虚拟机的空间是有限的。 *类加载的时机: 1)第一次创建对象要加载类. 2)调用静态方法时要加载类,访问静态属性时会加载类。 3)加载子类时必定会先加载父类。 4)创建对象引用不加载类. 5) 子类调用父类的静态方法时 (1)当子类没有覆盖父类的静态方法时,只加载父类,不加载子类 (2)当子类有覆盖父类的静态方法时,既加载父类,又加载子类 6)访问静态常量,如果编译器可以计算出常量的值,则不会加载类, 例如:public static final int a =123;否则会加载类,例如:public static final int a = math.PI。
类的实例化过程:
JVM读取指定classpath路径下的class文件,加载到内存,如果有直接父类,也会加载父类;
堆内存分配空间;
执行父类、子类静态代码块;
对象属性进行默认初始化;
调用构造方法;
在构造方法中,先调用父类构造方法初始化父类数据;
初始化父类数据后,显示初始化,执行子类的构造代码块;
再进行子类构造方法的特定初始化;
初始化完毕后,将地址赋值给引用。
1.5 注解
1.5.1.注解定义:
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。
它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
1.5.2.作用分类:
- 编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】
- 代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
- 编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】
1.5.3.常见注解:
- @Override
它的作用是对覆盖超类中方法的方法进行标记,如果被标记的方法并没有实际覆盖超类中的方法,则编译器会发出错误警告。 - @SuppressWarnings
deprecation,使用了过时的类或方法时的警告unchecked,执行了未检查的转换时的警告
fallthrough,当 Switch 程序块直接通往下一种情况而没有 Break 时的警告
path,在类路径、源文件路径等中有不存在的路径时的警告
serial,当在可序列化的类上缺少 serialVersionUID 定义时的警告
finally ,任何 finally 子句不能正常完成时的警告 all,关于以上所有情况的警告 - @Deprecated
@Deprecated的作用是对不应该在使用的方法添加注释,当编程人员使用这些方法时,将会在编译时显示提示信息,它与javadoc里的 @deprecated标记有相同的功能,准确的说,它还不如javadoc@deprecated,因为它不支持参数
1.5.4.@PostConstruct与@PreDestroy详解
Java EE5 引入了@PostConstruct和@PreDestroy这两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作
API使用说明
以下为@PostConstruct的API使用说明:
PostConstruct 注释用于在依赖关系注入完成之后需要执行的方法上,以执行任何初始化。
此方法必须在将类放入服务之前调用。支持依赖关系注入的所有类都必须支持此注释。即使类没有请求注入任何资源,用 PostConstruct 注释的方法也必须被调用。只有一个方法可以用此注释进行注释。
应用 PostConstruct 注释的方法必须遵守以下所有标准:
- 该方法不得有任何参数,除非是在 EJB 拦截器 (interceptor) 的情况下,根据 EJB规范的定义,在这种情况下它将带有一个 InvocationContext 对象 ;
- 该方法的返回类型必须为 void;该方法不得抛出已检查异常;
- 应用 PostConstruct 的方法可以是 public、protected、package private 或 private ;
- 除了应用程序客户端之外,该方法不能是 static;该方法可以是 final;
- 如果该方法抛出未检查异常,那么不得将类放入服务中,除非是能够处理异常并可从中恢复的 EJB。
总结为一下几点:
- 只有一个方法可以使用此注释进行注解;
- 被注解方法不得有任何参数;
- 被注解方法返回值为void;
- 被注解方法不得抛出已检查异常;
- 被注解方法需是非静态方法;
- 此方法只会被执行一次;
Servlet执行流程图
两个注解加入只会,Servlet执行流程图:
在具体Bean的实例化过程中,@PostConstruct注释的方法,会在构造方法之后,init方法之前进行调用。
实例
基于Spring boot编写的可执行方法见github:https://github.com/HappySecondBrother/example UserService方法(提供缓存数据):
@Service
public class UserService {
public List<String> getUser(){
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
return list;
}
}
// BusinessService方法,通过@PostConstruct调用UserService:
@Service
public class BusinessService {
@Autowired
private UserService userService;
private List<String> list = null;
/**
* 构造方法执行之后,调用此方法
*/
@PostConstruct
public void init(){
System.out.println("@PostConstruct方法被调用");
// 实例化类之前缓存获得用户信息
List<String> list = userService.getUser();
this.list = list;
if(list != null && !list.isEmpty()){
for(String user : list){
System.out.println("用户:" + user);
}
}
}
public BusinessService(){
System.out.println("构造方法被调用");
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
执行结果:
构造方法被调用
@PostConstruct方法被调用
用户:张三
用户:李四
项目应用
在项目中@PostConstruct主要应用场景是在初始化Servlet时加载一些缓存数据等。
注意事项
使用此注解时会影响到服务的启动时间。服务器在启动时会扫描WEB-INF/classes的所有文件和WEB-INF/lib下的所有jar包。
1.5.5 @JsonFormat和@JSONField、@Transient 注解
- @JSONField
- @JSONField(ordinal =0) 序列化字段的顺序,默认是0
- @JSONField(name = “”) 用于解决属性名和key不一致的情况,当前端传过来的字段名不一样的时候,我们可以在字段名上加上这个注解
- @JSONField(format = “yyyy-MM-dd HH:mm:ss”) 用在Date属性上,自动格式化日期
- @JSONField(serialize = false) 是否要把这个字段序列化成JSON字符串,默认是true
- @JSONField(deserialize = false) 字段是否需要进行反序列化,默认是true
- @JsonFormat
- @Transient
- 实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中,该变量内容在序列化后无法获得访问
- 被transient修饰,变量将不再是对象持久化的一部分,不做库表的orm 映射处理
1.6 常用类库-工具包
- Apache-commons
- Betwixt: XML与Java对象之间相互转换。
- Launcher: 可以跨平台独立启动的java应用程序。
- Exec: 提供常用方法用来执行外部进程,如执行exe文件或命令行
- Validator: 提供了在一个XML文件中定义校验器(校验方法)和校验规则
- CLI:CLI 提供针对命令行参数,选项,选项组,强制选项等的简单API
- Compress: 压缩、解压缩,可操作ar、cpio、Unix dump、tar、zip、gzip、XZ、Pack200和bzip2
- Codec: 提供常用的编码和解码方法,如DES、SHA1、MD5、Base64、URL和Soundx等。
- Configuration :java应用程序的配置管理类库,可以从properties或者xml文件中加载配置信息。
- DBCP :提供数据库连接池服务。
- DbUtils: 提供对jdbc 的操作封装来简化数据查询和记录读取操作。
- Email: 邮件操作组件,对java Mail api进行封装,提供了常用的邮件发送和接收类
- FileUpload: 为Web应用程序或Servlet提供文件上传功能,Struts2和SpringMVC的文件上传组件。
- IO: io工具类包,对java.io扩展,提供更加方便的IO操作。
- Lang:Java基本对象方法的工具类包,提供对字符、数组等基本对象的操作,StringUtils,ArrayUtils
- Collections:扩展java标准Collections API.对常用的集合操作进行封装、抽象和补充
- BeanUtils: 提供了对于JavaBean进行各种操作,克隆对象,属性等。
- Net: 封装了各种网络协议的客户端,支持FTP、NNTP、SMTP、POP3、Telnet等协议。
- Math :轻量级自容器的数学和统计计算方法类包,包含大多数常用的数值算法。
- Logging: 提供统一的日志接口,同时兼顾轻量级和不依赖具体的实现。
- Apache HttpClient: 曾是 Apache Commons的子项目,后独立 。HttpClient简化HTTP客户端与服务器的各种通讯,实现HTTP客户端程序(也就是浏览器程序)的功能
- JDK:包位置 D:/java/jre/lib/rt.jar/java
- java.lang:提供Java编程的基础类,如 Object、Math、String、StringBuffer、System、Thread等
- java.util:提供了包含集合框架、遗留的集合类、事件模型、日期和时间实施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组)。
- java.io:该包通过文件系统、数据流和序列化提供系统的输入与输出。
- java.Math:数学运算相关
- java.net:该包提供实现网络应用与开发的类。
- Java.nio :为输入输出提供缓冲区的类
- java.sql:提供了使用Java语言访问并处理存储在数据源(数据库)中的数据API。
- java.awt: 提供了创建界面和绘制图形图像的所有类,提供了GUI设计与开发的类
- javax.swing:提供了GUI设计与开发的类。而javax.swing包提供了一组“轻量级”的组件
- java.text: 提供了与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。
- Java.applet:提供创建applet小程序所需要的类
- Java.beans:包含与开发javaBeans相关的类
使用总结
equals()和hashCode()
首先equals()和hashCode()方法、包括toString()方法=都可以由IDEA工具生成,属于模板代码
- https://blog.csdn.net/u012133048/article/details/87878586
- https://blog.csdn.net/javazejian/article/details/51348320
- https://blog.csdn.net/qq_28051453/article/details/52701171
数据转换
#### byte-String
1.String转byte数组:
String str = "abcd";
byte[] bs = str.getBytes();
2.byte数组转String:
String s = new String(bs,"utf-8");
#### Array-List
1.如果你的List只是用来遍历,就用Arrays.asList()吧!
例:String转数组,再转list
Arrays.asList(StringUtils.split(stringObj, ","))
这个ArrayList不是java.util包下的,而是java.util.Arrays.ArrayList,显然它是Arrays类自己定义的一个内部类!这个内部类没有实现add()、remove()方法,而是直接使用它的父类AbstractList的相应方法。而AbstractList中的add()和remove()是直接抛出java.lang.UnsupportedOperationException异常的!
2.如果你的List还要添加或删除元素,还是乖乖地new一个java.util.ArrayList,然后一个一个的添加元素吧!
//Collections.addAll()
String[] array = {“aa”,”bb”,”cc”};
List List = new ArrayList();
Collections.addAll(List, array);
//循环遍历数组,add到list中
for(int i = 0; i < array.length; i++){
List.add(array[i]);
}
#### String-int
1.String 转 int
int a = Integer.parseInt(str);
int b = Integer.valueOf(str).intValue()
2. int转 String
//注: Double, Float, Long 的方法大同小异.
String str = String.valueOf(int i);
String str = Integer.toString(int i);
String str = “” + i ;
#### map-obj
1.map转obj
2.obj转map
#### Date
1.date转String
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//日期格式
string date = sdf.format(new Date());
2.String转date
String string = "2014-3-17";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
date = sdf .parse(string);
#### JsonObject & JSONArray
1.jsonString转jsonObject,遍历键值对
JSONObject data = JSONObject.parseObject(param);//com.alibaba.fastjson.JSON
JSONObject jsonParams = JSONObject.fromObject(queryParams);//net.sf.json.JSONObject
Iterator<String> paramKeys = jsonParams.keys();
while(paramKeys.hasNext()){
String paramName = paramKeys.next();
String value = jsonParams.getString(paramName)
)
2.Map转jsonObject
Map<String, Object> rtn = new HashMap<String, Object>();
JSONObject json = JSONObject.fromObject(rtn); //net.sf.json.JSONObject
3.Object转jsonObject
JSONObject data = JSONObject.parseObject(param);//com.alibaba.fastjson.JSON
JSONObject jsonParams = JSONObject.fromObject(queryParams);//net.sf.json.JSONObject
4.JSONObject 转 Map/object
JSONObject.parseObject(result.toString(), Map.class);
6.JSONArray 转 List<T>
//net.sf.json.JSONArray
List<TJzglWj> wj = (List<TJzglWj>)JSONArray.toCollection(jsonArray2,TJzglWj.class);
7.jsonString 转 List<T>
//com.alibaba.fastjson.JSON
List<TJzglWj> parseArray = JSON.parseArray(listStr, TJzglWj.class);
#### Spring BeanUtils 的对象复制 copyProperties
BeanUtils.copyproperties(source,target)
#### 求商-保留两位小数
private String divideBy2Decimal(double numA, double numB){
if(numB == 0.00){
return "0";
}
BigDecimal bigDecimalNumA = BigDecimal.valueOf(numA);
BigDecimal bigDecimalNumB = BigDecimal.valueOf(numB);
BigDecimal result = bigDecimalNumA.divide(bigDecimalNumB, 2, BigDecimal.ROUND_HALF_UP);
return result.toString();
}
stream示例
https://blog.csdn.net/lu930124/article/details/77595585
1.stream优雅的去重
字符串集合去重
List<String> distinctElements = list.stream().distinct().collect(Collectors.toList());
// 根据属性id去重
List<Person> unique = appleList.stream().collect(
collectingAndThen(
toCollection( () -> new TreeSet<>(comparingLong(Apple::getId)) ),
ArrayList::new
)
);
根据对象属性去重
public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Map<Object, Boolean> map = new ConcurrentHashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
//使用举例
persons.stream().filter(distinctByKey(Person::getName))
2.groupingBy():list 分组转 Map<String, List<Student>>
Map<String, List<Student>> stuentMap = studentList.stream().collect(Collectors.groupingBy(Student::getName()));
Map<String, List<Map<String, Object>>> AttendanceLeaveRegisterMap = AttendanceLeaveRegisterMapList.stream().collect(Collectors.groupingBy(e -> e.get("user_id").toString()));
3.sorted()排序
List<StudentInfo> studentsSortName = studentList.stream().sorted(Comparator.comparing(StudentInfo::getAge)).collect(Collectors.toList());
4.filter() 过滤
List<StaffWithDept> deptStaffs = staffWithDepts.stream().filter(s -> deptId.equals(s.getDeptId())).collect(Collectors.toList());
5.map() 使用
List<Integer> deptIds = staffWithDepts.stream().map(StaffWithDept::getDeptId).distinct().collect(Collectors.toList());//选出去重后的部门id
6.List转Map
//需要注意的是: toMap 如果集合对象有重复的key,会报错Duplicate key .... apple1,apple12的id都为1。可以用 (k1,k2)->k1 来设置,如果有重复的key,则保留key1,舍弃key2
Map<Integer, Apple> appleMap = appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1));
7.求和:将集合中的数据按照某个属性求和
//计算 总金额
BigDecimal totalMoney = appleList.stream().map(Apple::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
8.查找流中最大 最小值 Collectors.maxBy 和 Collectors.minBy
Optional<Dish> maxDish = Dish.menu.stream().collect(Collectors.maxBy(Comparator.comparing(Dish::getCalories)));
Optional<Dish> minDish = Dish.menu.stream().collect(Collectors.minBy(Comparator.comparing(Dish::getCalories)));