Lombok
基于jsr269规范,从JDK6开始提供的特性,在Java类编译期间能够利用合适的注解对该类生成字节码文件的过程中添加源文件没有的内容 Lombok基于字节码增强,编译期处理,可以配置在开发工具 IDE 或 项目建造工具 Mave Lombok的注解大都在源码级别生效@Retension(RetentionPolicy.SOURCE)
如图所示Lombok对字节码文件在编译期修改的时间
Lombok安装使用
对于使用指令进行Java对象的编译,可以参考javac -cp lombok.jar xxx.java
,使用的前提是需要将Lombok的jar包放到类路径下(关于javac ) 对于在Maven中使用Lombok,可以直接在pom文件中引入Lombok依赖 对于开发工具如IDEA,可以直接下载安装Lombok插件
Lombok常用注解
@Getter/@Setter
可以作用在类上或者是成员属性上 可以指定生成的set()
、get()
方法的访问级别,例如生成protected访问级别的set方法@Setter(AccessLevel.PROTECTED)
可以指定某个成员属性不生成set()
、get()
方法,可以在该成员属性上加上@Setter(AccessLevel.NONE)
,则不生成该成员属性的set()
方法,get()
同理 当@Getter/@Setter
加在类上时,对于final
修饰的成员属性不会生成set方法
@ToString
在该注解所有属性均为default
时,作用在类上可以为该类生成除了静态属性变量以外的,打印其他所有成员变量的toString()
方法 @ToString
有两个比较常用属性 1.例如@ToString(exclude={"xxx","yyy"})
,则成员变量xxx
、yyy
均不会在toString()
方法中被打印 2.例如@ToString(of={"xxx","yyy"})
,此时就算xxx
或yyy
是静态属性也会在toString()
方法中被打印,但是其他没有出现在 of
中的成员属性则不会被toString()
方法打印
@EqualsAndHashCode
在该注解所有属性均为default时,会生成包含所有成员属性作为判断条件的equals()
、所有成员属性作为计算hash的输入的hashCode()
方法、判断比较对象是否与被比较对象属于同一个类型的canEqual()
方法 @EqualsAndHashCode
有两个比较常用属性 1.例如@EqualsAndHashCode(exclude={"xxx","yyy"})
,则成员变量xxx
、yyy
均不会在equals()
、hashCode()
方法中使用到 2.例如@EqualsAndHashCode(of={"xxx","yyy"})
,此时仅有xxx
和yyy
两个成员属性会在equals()
、hashCode()
方法中使用到
@NonNull
该注解可以作用在成员属性或者是方法的入参上 1.加在成员属性上时,则构造器或set方法对该成员属性赋值时,就会自动判断非空,如果为空则报空指针异常 2.加在方法签名的入参上时,如果在调用该方法时不传入参,则会报空指针异常
@NoArgsConstructor
、@RequiredArgsConstructor
、@AllArgsConstructor
这三个注解作用在类上,作用分别为生成无参构造器、有入参的构造器、包含所有成员属性作为入参的构造器 @RequiredArgsConstructor
能生成有入参的构造器,这些入参只包含 final修饰的且没有初始化赋值 以及加了@NonNull
注解的这两类成员属性
@Data
这个注解作用在类上,同时包含了@Getter/@Setter
、@ToString
、@EqualsAndHashCode
、@RequiredArgsConstructor
几个注解的作用
@Builder
这个注解作用在类上,会使得该类满足建造者模式,同时如果这个类有@Data
或 @RequiredArgsConstructor
同样作用在类上,那么对于自动生成的有入参的构造器会变成包含所有成员属性作为入参的构造器
@Log
这个注解作用在类上,会为该类自动生成一个log
常量
val
val
是Lombok提供的关键字,类似于js中的val
,但是其修饰的变量一旦初始化就不可以再次改变,查看编译后的class文件可以发现,关键字的作用仅仅只是节省代码量,class文件中又会回到遵从Java语法的写法
@Cleanup
这个注解用在流或者其他一些打开系统资源的成员或局部变量上,作用和try with resource相同,都是会在流或者这些系统资源使用借宿后自动关闭
Lambda
public class Main {
public Main ( ) {
Function < String , String > func1 = x -> { System . out. println ( this ) ; return x ; } ;
System . out. println ( func1. apply ( "" ) ) ;
}
public String toString ( ) {
return "Main" ;
}
public static void main ( String [ ] argv) {
new Main ( ) ;
}
}
函数式接口
函数式接口:只有一个抽象方法的接口 常见的函数式接口
方法引用
方法引用:Lambda所表达的逻辑已经有某个类的方法实现了,就可以通过类名::方法名
替代Lambda表达式
import java. util. function. Function ;
public class Main {
public static void main ( String [ ] argv) {
Function < Integer , String > func1 = x -> Integer . toBinaryString ( x) ;
System . out. println ( func1. apply ( 10 ) ) ;
Function < Integer , String > func2 = Integer :: toBinaryString ;
System . out. println ( func2. apply ( 10 ) ) ;
Supplier < Integer > supplier1 = "icbc" :: length ;
System . out. println ( supplier1. get ( ) ) ;
}
}
Stream流
Stream(流)是一个来自数据源的元素队列并支持聚合操作 数据源:流的来源,可以是集合,数组,I/O channel,产生器 generator 等 元素队列:特定类型的对象形成的一个队列如ArrayList<String>
、String[]
等,Java 中的 Stream 并不会存储元素 聚合操作:类似 SQL 语句一样的操作,比如 filter, map, reduce, find, match, sorted 等
Stream特征
Pipelining:中间操作都会返回流对象本身。这样多个操作可以串联成一个管道,如同流式风格(fluent style)。这样做可以对操作进行优化,比如延迟执行(laziness)和短路(short-circuiting) 内部迭代:以前对集合遍历都是通过 Iterator 或者 For-Each 的方式,显式的在集合外部进行迭代,这叫做外部迭代。Stream 提供了内部迭代的方式,通过访问者模式(Visitor)实现
创建Stream流
Collection.stream ()
,这种方式是直接通过实现集合接口的集合实例中的stream ()
方法实现将集合实例转变成流Arrays.asStream()
,这种方式是将需要转变成Stream流的数组作为Arrays
工具类中的asStream()
方法入参,实现数组到Stream流的转变
Stream的操作方法
中间操作
中间操作:返回一个新的流并且可以在新流的基础上继续对流进行操作,旧的流不能再使用
选择与过滤
常用的选择与过滤方法 1.filter(Predicate p)
入参为 Lambda表达式 ,从流中排除某些元素 2.distinct()
筛选,通过流中元素的 hashCode()
和 equals()
去除重复元素 3.limit(long maxSize)
截断流,使其元素不超过给定数量 4.skip(long n)
跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流
映射
常用的映射方法 1.map(Function f)
入参为 Lambda表达式,将元素转换成其他形式或提取信息;接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素 2.mapToDouble(ToDoubleFunction f)
入参为 Lambda表达式,接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream 3.mapToInt(ToIntFunction f)
接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的IntStream
4.mapToLong(ToLongFunction f)
接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream
5.flatMap(Function f)
接收一个函数作为参数,将流中的每个元素都换成另一个流,然后把所有流连接成一个流(比如流中元素是集合,那么集合中的元素会被取出来放到总的流中)
排序
常用的排序方法 1.sorted()
产生一个新流,其中按自然顺序排序 2.sorted(Comparator comp)
产生一个新流,其中按比较器顺序排序
终止操作
终止操作:经过终止操作的流不能再次使用且返回操作结果
查找与匹配
常用的查找与匹配方法 1.noneMatch()
检查是否没有匹配的元素 2.findFirst()
返回第一个元素 3.count()
返回流中元素的总个数 4.findAny()
返回当前流中的任意元素 5.max()
返回流中最大值
归约 reduce
收集collect
迭代forEach
list. stream ( ) . forEach ( System . out:: println ) ;
并行Stream流
与传统的Stream流有相同的操作,不过区别在于JVM可以使用多线程去执行这些操作
创建并行流
Stream.parallel()
已经存在的Stream流实例,调用自身的parallel()
方法,将该Stream流转变成并行Stream流Collection.parallelStream()
直接通过实现集合接口的集合实例中的parallelStream()
方法实现将集合实例直接转变成并行Stream流
Guava
Guava 是一种基于JDK做增强的开源 Java 工具类库,其中包含很多谷歌他们自己项目正在使用的很多核心库 Guava 类库是为了方便编码,并减少编码错误。这个库提供用于集合,缓存,支持原语,并发性,常见注解,字符串处理,I/O 和验证的实用方法 Guava 对 JDK 集合的扩展 1.不可变集合:用不变的集合进行防御性编程和性能提升 2.新集合类型:multisets, multimaps, tables, bidirectional maps 等 3.强大的集合工具类:提供 java.util.Collections 中没有的集合工具 4.扩展工具类:让实现和扩展集合类变得更容易,比如创建 Collection 的装饰器 ,或实现迭代器 Guava 对本地缓存[Caches]实现,支持多种缓存过期策略 Guava 对并发[Concurrency]的增强:ListenableFuture:完成后触发回调的 Future Guava 对字符串处理[Strings]的增强:增添非常有用的字符串工具,包括分割、连接、填充等操作 Guava 对事件总线[EventBus]的实现:发布-订阅模式的组件通信,进程内模块间解耦 Guava 对反射[Reflection]的增强:Guava 的 Java 反射机制工具类