Lambda表达式也称为箭头函数,匿名函数,闭包
Lambda表达式体现的是轻量级函数式编程思想
->符号是Lambda表达式核心操作符号,符号左侧是参数,
右侧是操作表达式
jdk8的新特性
使用Lambda创建线程
new Thread(() -> {
// 需要执行的代码
}).start();
为什么使用Lanbda
- 它不是解决未知问题的新技术
- 对现有解决方案的语义优化
- 需要根据实际需求考虑性能问题
函数式接口
-
函数式接口就是java类型系统中的接口
-
函数式接口是只包含一个接口方法的特色接口
-
语义化检测注解:@FuncionalInterface
-
default方法,static方法不算其中
-
从Object中继承的方法也不算其中,例如toString()
-
Lambda表达式只能操作一个方法
-
java中Lambda表达式核心就是一个函数式接口的实现
Lambda针对函数式接口的实现: A a = (方法的参数) -> { // 方法的实现 };
java中内建的函数式接口
- java.lang.Runable
- java.lang.Comparable
- java.lang.Comparator
- java.io.FileFilter
- 等等…
jdk8中提供了java.util.function包提供了常用的函数式功能接口
-
java.util.function.Predicate 接受参数T,返回一个Boolean
Predicate<String> pre = (string name) -> { return "a".equals(name); }; pre.test("a");
-
java.util.function.Comsumer 接受参数对象T,没有返回值
Comsumer<String> cs = (string message) -> { print("接受参数:" + message); };
-
java.util.function.Function<T, R> 接受对象T,返回对象R
Function<String, Boolean> funct = (String name) { return "a".equals(name) ? 1 : 0; }
-
java.util.function.Supplier 不接受参数,提供T对象的创建工厂
Supplier<String> sp = () -> { return UUID.rendomUUID().toString(); }
-
java.util.function.UnaryOperator 接受参数对象T,返回结果对象T
UnaryOperator<String> uo = (String img) { return img += "..."; }
-
java.util.function.BinaryOperator 接受两个Td对象,返回一个T 对象结果
BinaryOperator<Integer> b=(Integer i1,Integer i2) { return i1 > i2 ? li : l2; }
Lambda表达式的基本语法
-
声明:就是和Lambda表达式绑定的接口类型
-
参数:包含在一对圆括号中,和绑定的接口中的抽象方法中的参数
-
个数及顺序一致
-
操作符:->
-
执行代码快:包含在一对大括号中,出现在操作符号右侧
-
[接口声明] = (参数) -> {执行代码块}
A a = (参数) -> {} a.方法名();
Lambda表达式必须和接口绑定
Lambda表达式的参数可以附带0个到n个参数,括号中的参数类型
可以不用指定,JVM运行是会自动绑定接口中参数的数据类型当有返
回值时,当只有一行代码,可以省略{}和return关键字
匿名内部类中的变量捕获
new Thread(() -> {
this.成员变量
局部变量直接访问
}).start();
Lambda的类型检查
test(函数式接口<String, List>)
test((x, y) -> {
y.add(x)
});
JVM会自动将(x, y) -> { y.add(x)} 绑定为函数式接口类型,
x,y会绑定String, List类型
方法重载两个相同的方法名会使JVN产生混淆,JVM无法判断该调用
那个方法,就会给出编译错误
使用Lambda表达式底层实现是先创建一个静态的方法,方法中实现
逻辑处 理,再创建一个final类型的内部类实现了函数式接口,实现
函
数式的方法,该方法中调用了先前创建的静态方法
Lambda表达式的方法引用
-
静态方法引用的使用
类型名称.方法名称 -> 类型名称::方法名称 对象排序:Collections.Sort(对象,(t1, t2)-> t1.getAge() - t2.getAge()); 使用Lambda表达式Collections.Sort(对象,对象::静态方法)
-
实例方法引用
A a = new A(); a::方法名();
-
构造方法引用
A a = A::new;
-
Stream是用户处理集合中较为复杂的操作
过滤 list.stream().fileter(x -> x.length() >=5).collect(Collectors.toList());
获取stream对象
-
从集合或数组中获取
串行 Collections.stream() 并行 Collections.parallelStream() Arrays.stream(数组对象)
-
从集合或数组中获取
-
从BufferReader缓冲中获取BufferReader.lines()
-
静态工厂
java.util.stream.IntStream.renge() java.nio.file.files.walk()
-
自定构建
java.util.Spliterator
-
更多的方式…
Random.ints() Pattern.spiltAsStream()...
中间操作(返回还是stream())
中间操作可以有一个或者多个连续的中间操作,中间操作只记录操作
方式,不做具体执行,直到结束操作发生时,才做最终执行,中间操作
就是逻辑处理
中间操作过程
-
无状态:数据处理时,不受前置中间操作的影响
map/filter/peek/parallel/sequential/unordered
-
有状态:数据处理时,收前置中间操作的影响
-
distinct/sorted/limit/skip
结束操作|终结操作
一个stream()只能有一个终结操作,这个操作一旦发生,就会真实处理
数据,生成对于的处理结果短路操作:当前stream对象必须处理完集合
中的所有数据,才得到结果
forEach/forEachOrdered/toArray/reduce/collect/min/max
/count/iterator
非短路操作
当前的stream对象在处理过程中,一旦满足某个条件,就可以得到结果
anyMatch/allmatch/noneMatch/findFirst/findAny等
Short-circuiting,无限大的Stream -> 有限大的Stream
转换成stream对象
- stream.of(’’,’’);
- Arrays.stream();
- Collections.stream()
- map.entrySet().stream()
- IntStream.of(int [])
- IntStream.range(1,3) 范围查找,包含起始数据不包含结束数据
- IntStream.rangeClosed(1,3) 范围查找,包含起始数据也包含结束数据
stream转换指定的对象
-
转换数组
stream.toArray(String[] ::new);
-
转换string
stream.collect(Collectors.joining()).toString();
-
转换List
stream.collect(Collectors.toList())
-
转换set
stream.collect(Collectors.toSet())
-
转换map
stream.collect(Collectors.toMap(x -> x, y -> y))
stream常见的api操作
-
列表中添加一个前缀
list.stream().map(x -> 'aa' + x).collect (Collectors.toList())
-
过滤
list.stream().fileter(x -> x.length()).collect (Collectors.toList())
-
forEach
-
list.forEach()
-
peek 中间操作
ist.stream().peek().peek()....froEach()
-
skip 中间操作,有状态的操作,跳过部分数据
list.stream().skip(3).forEach()
-
limit 中间操作,有状态,限制输出数据数量
list.stream().skip(3).limit(2).forEach
-
distinct 中间操作,有状态,剔除重复数据
list.stream.distinct().forEach
-
sorted 中间操作,有状态,排序
-
max 获取最大值
Optional option = list.stream().max((x, y) -> x-y) optional.get()
-
min 获取最小值
-
reduce 合并处理数据,求和
Optional option = list.stream().reduce((sum, x) -> sum + x) optional.get()
parallelStream并行处理原理
将一个大任务拆分成多个小的任务通过多个线程执行的过程
使用parallelStream的forEach会存在线程不安全的情况
线程安全的parallelStream.collect(Collections.toList)
总结
对于简单的数据处理可以使用常规的外部迭代进行处理,如果
对性能有要求可以使用parallelStream进行操作对于复杂对象
的处理操作,stream的迭代操作与普通的迭代操作相差无几,
甚至超过普通的迭代方式,可以使用简洁的stream语法替代
常规迭代操作
如果性能上有要求的话,可以选择parallelStream进行操作