java流
1,函数式编程
(1)定义:是一种构建程序结构的编程范式,是一种与面向对对象程序设计完全不同的设计思想
(2)性质:函数的输出应且仅应依赖函数本身
(函数的执行,不应依赖于函数外部数据的状态[闭包])
(3)选择:函数式编程与面向对象编程有各自的优势,所以两者没有优劣之分
(4)例子:
//面向对象的程序设计
//不仅仅依赖于方法本身还依赖于方法外部的属性
int x;
public int multiply(){
return x * x;
}
//函数式设计方法
//仅仅依赖于方法参数及方法本身的函数式的设计
public int multiply(int x){
return x * x;
}
2,lambda表达式
(1)函数介绍
[1]通过函数式接口,设计一个函数(约束函数的参数/返回类型的抽象方法)
[2]通过lambda表达式,定义一个已经设计好的函数(函数式接口的实现)
[3]函数,可以像对象一样传递,在需要的时候执行
[4]特点
<1>匿名:无修饰符/返回类型/名称(Think more , Write less)
<2>函数:不属于任何类,有参数列表/函数体/返回值
<3>传递:可以作为参数传递给方法,或者作为变量的值
(2)Lambda表达式语法
[1]写法1:(arg1,arg2) -> expression
[2]写法2:(arg1,arg2) -> {body}
[3]参数列表解释:
<1>箭头,函数参数列表与表达式/函数主体的分隔符
<2>Lambda表达式可包含0或多个参数
<3>参数列表,当参数为空时,需要声明空括号,当只有一个的时候可以忽略
<4>参数类型可以省略,编译器会自动完成类型推导
[4]函数体解释:
<1>Lambda表达式的函数体,可包含0或多条语句
<2>函数体,只有一条语句的表达式,可以省略{}
<3>函数体,包含一条以上的语句必须包含在括号中
<4>函数体,返回类型必须匹配,没有可不声明返回值
<5>函数体,无参数有返回值,函数体必须有{}
<6>函数体,无参数无返回值,只有一条语句可以忽略{}
3,java集合流(鉴于java对集合操作的复杂性,java8之后引入Stream API,用于操作处理集合中的元素)
(1)接口:java.util.stream.Stream
(2)集合流介绍
[1]集合是存储元素对象的容器
[2]Stream(集合流),并不是存储元素的数据结构,而是操作集合元素的管道
[3]集合流相当于是一个生产线,通过不同操作进行处理。
[4]集合流操作的主题是集合内的元素,不是集合本身
(操作后:将创建新集合聚合Stream操作的结果,不影响原集合结构)
4,java集合流特点
(1)Stream仅会对流动的元素操作一次(溜走了)[与Iteration的游标相似]
(2)想要进行心的操作就必须重新生成一个新Stream才能继续操作
(3)Stream上的操作会被延迟处理,对于一个流,系统会被优化后再执行[提高执行效率]
(4)Stream提供了一系列操作集合元素的函数
(5)Collection接口中,通过stream()方法获取当前集合的Stream对象
(6)操作类型[中间操作,终止操作]
5,Terminal Operations终止操作
(1)作用:终止stream操作处理,消费stream操作产生的结果
(2)collect():聚合在stream中间操作的结果
(3)forEach():迭代stream的每个元素
(4)Collectors(java.util.stream.Collectors)类,用于操作聚合结果的工具类
[1]groupingBy()/mapping()
[2]toList()/toSet()/toMap()
(5)forEach()方法,不是for-each-loop循环
(6)forEach()方法和foreach循环的区别
private static void forEach() {
//通过foreach循环进行循环输出
for (Apple a : APPLES) {
System.out.println(a.getWeight());
}
//通过foreach()方法循环输出
//这个方法的参数是一个函数,这个函数是以Lambda表达式的形式
APPLES.forEach(a -> System.out.println(a.getWeight()));
}
6,Intermediate Operations中间操作
(1)Stream filter(): 基于参数选择stream中的元素,过滤
//介绍:Stream<T> filter() 过滤stream中的元素,表达式的结果必须是boolean值,为真就置于新的stream中,为假就过滤掉
//只过滤指定颜色的苹果
//写法一
private static List<Apple> filter(Apple.Color c) {
Stream<Apple> appleStream = APPLES.stream();
Stream<Apple> appleStream1 = appleStream.filter(apple -> apple.getColor() == c);
List<Apple> apples = appleStream1.collect(Collectors.toList());
//聚合成一个集合
return apples
}
//写法二
private static List<Apple> filter(Apple.Color c) {
return APPLES.stream()
.filter(a -> a.getColor() == c)
.collect(Collectors.toList()); //聚合成一个集合
}
//过滤指定颜色和重量的苹果
private static void filter(Apple.Color c, int weight) {
APPLES.stream()
//下面这两个过滤实际上可以写在一起用&&连接
//下面这种写法更加清晰,而且鉴于流延迟处理的特性,分开写并不会影响效率
.filter(a -> a.getColor() == c)
.filter(a -> a.getWeight() >= weight)
.collect(Collectors.toList())
.forEach(a -> System.out.println(a.getId()));
}
(2)Stream map(): 基于stream操作映射为新的类型,映射(将原有元素类型转换成新的类型)
//Stream<T> map() 映射Stream中的元素,基于条件将元素映射为新类型的元素
//例子:将苹果重量收集为新集合,并进行打印输出
//写法一
private static void map() {
APPLES.stream()
.map(a ->a.getWeight())
.collect(Collectors.toList())
.forEach(a -> System.out.println(a));
}
//写法二(流中的Lambda表达式,当只有一层实例级方法的时候可以直接用元素类型的这种写法)
//注意:后面的方法一定不要就加括号,中间是双冒号(只能是一级的实例级方法)
private static void map(){
APPLES.stream()
.map(Apple::getWeight)
.collect(Collectors.toList())
.forEach(System.out::println);
}
(3)Stream sorted(): 排序stream中的元素,排序
//Stream<T>Sorted() 对于stream中的元素进行排序
//Comparator类,比较器,控制顺序
//comparing(),基于指定值排序
//reversed() ,倒序
//案例1(按重量进行排序)
private static void sorted() {
APPLES.stream()
.sorted(Comparator.comparing(Apple::getWeight))
.collect(Collectors.toList())
.forEach(a -> System.out.println(a.getWeight()));
}
//案例2(按照id进行倒叙排序)
private static void sortedReversed() {
APPLES.stream()
.sorted(Comparator.comparing(Apple::getId).reversed())
.collect(Collectors.toList())
.forEach(a -> System.out.println(a.getId()));
}
(4)Long count(): 获取Stream中元素的个数,计数
[上面除了计数的返回值是Long其余全是Stream,所以可以多次操作,形成流的操作链]
(5)Stream的其他方法
takeWhile() //从头遍历置于流,到结果为true停止
dropWhile() //从头遍历,到结果为true开始置于流
flatMap() //将多层映射合并
findFirst() //从流中读取第一个符合条件的元素,封装到Optional
findAny() //从流中取任意一个符合条件的元素
anyMatch() //任意一个元素符合条件就返回true
allMatch() //全部元素符合条件,返回true