流的操作过程
流的创建->流的中间操作->终止操作
一、流的创建
1.通过collection系列集合提供的stream()方法或parallelStream()方法创建流
示例代码:
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
2.通过Arrays的静态方法stream()方法产生数组流。
示例代码:
SysDeptEntity[] deptEntities = new SysDeptEntity[10];
Stream<SysDeptEntity> stream1 = Arrays.stream(deptEntities);
3.通过Stream类中的静态方法of()生成
示例代码:
Stream<String> stream2 = Stream.of("aa","bb","cc");
4.无限流的创建
1)通过迭代的方式创建
示例:
//迭代方式
Stream stream3 = Stream.iterate(0,(x)-> x+2);
stream3.limit(8).forEach(System.out::println);
2)通过生成的方式创建
//生成
Stream.generate(()-> {
return new Random().nextLong();
}).limit(10).forEach(System.out::println);
二、流的中间操作
1.筛选与切片
filter (接收Lambda ,从中排除某些元素)
示例:
List<EntityTest> deptList = Arrays.asList(new EntityTest("123",23),
new EntityTest("111",22),
new EntityTest("111",21),
new EntityTest("111",25),
new EntityTest("111",24));
deptList.stream().filter((EntityTest)-> EntityTest.getName().equals("111"))
.forEach(System.out::println);
distinct()、limit(long MaxSize)、skip(long n)方法比较简单此处不做详细解释,见下图。
2.映射
所谓映射是指将元素转换成其他形式或提取信息。接受一个函数作为参数,改函数会被应用到每个flatMap-接受一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连接成一个流。
1).map映射
map方法接收一个函数作为函数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
下面实例,把每个字符串转换成大写字母,把所有的序列组成一个流
@Test
public void test4(){
List<String> list = Arrays.asList("aaa", "bbb", "ccc");
/*map方法中接收一个Function类型的对象,该对象用Lambda表达式实现,输入一个字符串类型,返回一个字符串类型,并把返回的字符串放到流中*/
Stream<String> stream = list.stream()
.map((x) -> {
String s = x.toUpperCase();
return s;
});
stream.forEach(System.out::println);
}
2)flatMap映射
上面一个实例,把每个子流放入一个流中,相当于流中嵌套了一个流,如果用flatMap方法的话,会把每个子流中的元素组成一个流,然后遍历一个流就可以了,而不是遍历一个流中的每个流。
public static Stream<Character> filterString(String str){
List<Character> list = new ArrayList<Character>();
for(Character ch : str.toCharArray()){ //char[]
list.add(Character.toUpperCase(ch));
}
return list.stream();
}
@Test
public void test6(){
List<String> list = Arrays.asList("aaa", "bbb", "ccc");
Stream<Character> stream = list.stream()
.flatMap(TestStream::filterString);
stream.forEach(System.out::println);
}
注意:map与flatMap的区别类似于集合中的add方法与addAll方法的区别,map方法映射时会将流对象一并映射过来,flatMap映射时不会映射流对象,只映射流对象中的元素。
3.排序
1).sorted()自然排序(Comparable)
List<EntityTest> deptList = Arrays.asList(new EntityTest("123",23),
new EntityTest("111",22),
new EntityTest("111",21),
new EntityTest("111",25),
new EntityTest("111",24));
deptList.stream().sorted()
.forEach(System.out::println);
2).sorted(Comparator com)定制排序(Comparator)
定制化排序的入参为函数式接口Comparator对象,关于函数式接口的介绍可参考https://blog.csdn.net/qq_41471057/article/details/102094614
默认按年龄大小排序当年龄一样时按姓名排序
List<EntityTest> deptList = Arrays.asList(new EntityTest("123",23),
new EntityTest("2352",22),
new EntityTest("168",21),
new EntityTest("7654",25),
new EntityTest("234",24));
deptList.stream().sorted((e1,e2)->{
if(e1.getAge()==e2.getAge()) {
return e1.getName().compareTo(e2.getName());
}else{
return e1.getAge().compareTo(e2.getAge());
}
}).forEach(System.out::println);
4.查找与匹配(终止操作)
count()返回流中元素的总个数
max()返回流中最大值
min()返回流中最小值
还有最常用的foreach()流内部遍历
5.规约与收集
1)规约
方法名 | 描述 |
---|---|
reduce(T iden, BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回T |
reduce(BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回Optional |
代码示例:
@Test
public void test11() {
List<Integer> llist = Arrays.asList( 1,2,3,4,5,6,7,8 );
//这种不可能为空
Integer sun = llist.stream()
//首先把0作为x 然后0+1得到1 然后把1作为x 然后1+2 逐渐结合
.reduce( 0,(x,y) -> x+y );
System.out.println(sun);
//这种可能为空,因为没有起始值
Optional<Integer> ss = list.stream()
.map((x) -> x.getId() )
.reduce((x,y) -> x+y);
System.out.println(ss.get());
}
2)收集
对流中元素执行一个可变汇聚操作。是一个终止操作。比如:将流中的元素放入到一个List集合当中,将流中的元素进行分组、分区,求和等等操作。接受一个收集器Collector对象。
收集器Collector概述
Collector是一接口。通过上面的介绍我们知道Stream的collect方法会接受一个Collector类型的参数,用来进行汇聚操作。那么是怎样实现汇聚操作的呢?Collector这个接口又有什么用呢?下面讲逐一介绍。
通过读Jdk的文档可以知道,Collector接口是用来定义一个可变的汇聚操作:讲输入元素累加到一个可变结果容器,当所有的输入元素都被处理过后,选择性的将累加结果转换为一个最终会的表示。汇聚操作可以被串行和并行的执行。
代码示例:
/**
* 收集
* collect - 将流转化为其他形式,接受一个Collector接口的实现,用于给Stream中元素做汇总的方法
*/
@Test
public void test12() {
/**
* Collector接口中方法的实现决定了如何对流执行收集操作,(如收集到List,Set,Map)
* 但是Collectors实用类提供了很多静态方法,可以方便的创建常见收集器实例
*/
List l = list.stream()
.map( (x) -> x.getName() )
/**将得到的name放在list*/
.collect( Collectors.toList() );
l.forEach( System.out::println );
list.stream()
.map( (x) -> x.getName() )
/**将得到的name放在set*/
.collect( Collectors.toSet() );
list.stream()
.map( (x) -> x.getName() )
/**将得到的name放在HashSet*/
.collect( Collectors.toCollection( HashSet::new ) );
Long l1 = list.stream()
/***得到集合的总数*/
.collect( Collectors.counting() );
System.out.println(l1);
Double d = list.stream()
/**id的平均值*/
.collect( Collectors.averagingDouble( Use::getId) );
Double d1 = list.stream()
/**id的总和*/
.collect( Collectors.summingDouble( Use::getId ) );
Optional optional = list.stream()
/**id的最大值*/
.collect( Collectors.maxBy((x,y) -> Double.compare( x.getId(),y.getId() ) ) );
System.out.println( optional.get() );
/**id的最小值*/
Optional<Integer> oo = list.stream( )
.map( Use::getSaler ).min( Double::compare );
System.out.println(oo.get());
/**
* 分组
*
* 按照id分组
*/
Map <Integer, List <Use>> m = list.stream()
.collect( Collectors.groupingBy( Use::getId ) );
//遍历map
for (Map.Entry map:m.entrySet()) {
System.out.println(map.getKey());
System.out.println(map.getValue());
}
System.out.println(m);
/**
* 组合分组
* 满足条件一个区(true),不满足条件一个区(false)
*/
Map<String, Map<Integer, List<Use>>> mapMap = list.stream()
.collect( Collectors.groupingBy( Use::getName,Collectors.groupingBy( (e) -> e.getId() ) ) );
/**
* 分区
*/
Map<Boolean, List<Use>> map = list.stream()
.collect( Collectors.partitioningBy( (e) -> e.getId()>3 ) );
System.out.println(map);
DoubleSummaryStatistics dd = list.stream()
.collect( Collectors.summarizingDouble( (x) -> x.getId() ) );
/**
* 连接字符串
*/
list.stream()
.map( (x) -> x.getName() )
.collect( Collectors.joining("z") );
}