您好,我是码农飞哥(wei158556),感谢您阅读本文,欢迎一键三连哦。
💪🏻 1. Python基础专栏,基础知识一网打尽,9.9元买不了吃亏,买不了上当。 Python从入门到精通
😁 2. 毕业设计专栏,毕业季咱们不慌忙,几百款毕业设计等你选。
❤️ 3. Python爬虫专栏,系统性的学习爬虫的知识点。9.9元买不了吃亏,买不了上当 。python爬虫入门进阶
❤️ 4. Ceph实战,从原理到实战应有尽有。 Ceph实战
❤️ 5. Java高并发编程入门,打卡学习Java高并发。 Java高并发编程入门
文章目录
- 1. Stream流是什么?
- 2. Stream流的执行机制
- 生成Stream流
- 执行中间操作
- 执行终止操作
- 3.使用示例(中间操作)
- 使用filter方法过滤所有红色苹果
- 使用map方法,将所有苹果重量+10,并且输出对应的苹果的产地
- sorted 排序方法
- flatMap的使用
- 去重,合并,跳过,截取(concat,distinct,skip,limit)
- 终止操作
- 聚合(max、min、count)
- 统计(counting、averaging)
- 遍历/匹配(foreach、find、match)
- 归集collect(toList、toSet、toMap)
- 分区、分组(partitioningBy、groupingBy)
- 拼接(joining)
1. Stream流是什么?
JDK1.8 中增加了Stream流,Stream流是一种流式的处理数据的风格,也就是将要处理的数据当作流,在管道中进行传输,并在管道的每个节点对数据进行处理,如过滤、排序、转换等。
先来看一个Stream API的使用示例
List<String> sourceList = Arrays.asList("1", "2", "", "12", "5");
int sum = sourceList.stream()
.filter(StringUtils::isNotBlank)
.mapToInt(Integer::valueOf)
.sum();
System.out.println(sum);
这是个很简单的一个Stream使用例子,我们过滤掉空字符串后,转成int类型并对各个元素进行求和,这里有个三个操作:filter,mapToInt,sum。后面会详细介绍。
2. Stream流的执行机制
Stream内部通过流水线(Pipline)的方式来实现的,基本思路就是顺着流水线尽可能执行更多的操作,从而避免多次迭代。
Steam流操作有三个特性:
- Stream流不存储数据:而是按照特定的规则对数据进行计算,一般会输出结果。
- Stream流不改变源数据:通常情况下会产生一个新的集合或一个值。
- Stream流具有延迟执行特性:只有调用终端操作时,中间操作才会执行。
一个Stream流的使用主要包括三步:
-
生成stream流:这就就是将输入的数据源转成Stream流,数据源主要是Collection
、
Array等集合数据。 -
执行中间操作:对数据进行处理
-
执行终止操作:返回最终的结果
生成Stream流
生成Stream流的方式有三种,分别是
List<String> sourceList = Arrays.asList("1", "2", "", "12", "5");
//1.创建stream串行流对象
sourceList.stream();
//2.创建可并行执行的stream流对象
sourceList.parallelStream();
//3.通过给定的一系列元素创建一个新的Stream串行流对象
Stream.of("12", "123", "14", "15");
执行中间操作
执行中间操作只是一种标记,只有结束操作才会触发实际计算。调用中间操作会返回一个新的流。 过滤,排序类的操作都是中间操作,中间操作可以有多个,中间操作分为无状态和有状态。
无状态:指元素的处理不受前面元素的影响。下面的方法均是无状态操作
方法 | 说明 |
---|---|
map() | 将已有元素转换为另一个对象类型,一对一逻辑 |
filter() | 按照条件过滤符号要求的元素 |
peek() | 对Stream流中的每个元素进行逐个遍历处理 |
unodered() | 返回一个无序的流,对于不关心顺序的数据处理和并行配合使用更佳。 |
mapToInt() | 将已有元素转成Int类型 |
mapToLong() | 将已有元素转成Long类型 |
mapToDouble() | 将已有元素转成Double类型 |
flatMap() | 将已有元素转换为另外对象类型,一对多逻辑 |
flatMapToInt() | 将已有元素转成Int类型 |
有状态:有状态的中间操作必须等所有元素处理之后才知道最终结果。比如排序是有状态的操作,在读取所有元素之前并不能确定排序结果。下面方法是有状态操作
方法 | 说明 |
---|---|
distinct() | 对stream中所有元素进行去重 |
sorted() | 结果排序 |
limit(n) | 仅保留集合前面指定个数的元素 |
skip(n) | 跳过集合前面指定个数的元素 |
concat() | 将两个流合并起来为1个新的流 |
执行终止操作
终止操作就是指定stream流的输出结果。
方法 | 说明 |
---|---|
count() | 元素个数 |
max() | 最大值 |
min() | 最小值 |
findFirst() | 第一个符合条件 |
findAny() | 任意一个符合条件 |
anyMatch() | 判断是否有符合条件元素 |
allMatch() | 是否所有元素都符合条件 |
noneMatch() | 是否所有元素都不符合 |
collect(Collectors进行指定) | 将流转换成指定类型 |
toArray() | 转换成数组 |
iterator() | 转换成iterator()对象 |
foreach() | 逐个遍历 |
3.使用示例(中间操作)
现在定义一个Apple类,此类有价格price,颜色color,重量weight,产地distinct 四个属性。
private static List<Apple> appleList = new ArrayList<>();
static {
appleList.add(new Apple(10, "red", 12, "安徽"));
appleList.add(new Apple(5, "red", 13, "江西"));
appleList.add(new Apple(5, "blue", 10, "江西"));
appleList.add(new Apple(40, "blue", 9, "河南"));
appleList.add(new Apple(15, "blue", 11, "浙江"));
}
}
public class Apple {
private Integer price;
private String color;
private Integer weight;
private String district;
public Apple(Integer price, String color, Integer weight, String district) {
this.price = price;
this.color = color;
this.weight = weight;
this.district = district;
}
省略getter和setter方法
}
-
使用filter方法过滤所有红色苹果
//1.filter(过滤)筛选出所有颜色是红色的苹果 List<Apple> red = appleList.stream().filter(apple -> apple.getColor().equals("red")).collect(Collectors.toList());
-
使用map方法,将所有苹果重量+10,并且输出对应的苹果的产地
//2.map的使用,将所有苹果重量+10,并且输出对应的苹果的产地 appleList.stream() .map(apple -> { apple.setWeight(apple.getWeight() + 10); return apple; }).map(Apple::getDistrict) .collect(Collectors.toList());
-
sorted 排序方法
- sorted():自然排序,流中元素需实现Comparable接口
- sorted(Comparator com):Comparator排序器自定义排序
//3.sorted() 排序
//按价格升序排序 自然排序
System.out.println("按价格升序排序 自然排序");
appleList.stream().sorted(Comparator.comparing(Apple::getPrice))
.peek(System.out::println).collect(Collectors.toList());
//按价格倒序排序 reversed()
System.out.println("按价格倒序排序 reversed()");
appleList.stream().sorted(Comparator.comparing(Apple::getPrice).reversed())
.peek(System.out::println).collect(Collectors.toList());
System.out.println("先按价格再按重量升序排序 thenComparing");
//先按价格再按重量升序排序 thenComparing
appleList.stream().sorted(Comparator.comparing(Apple::getPrice)
.thenComparing(Apple::getWeight))
.peek(System.out::println)
.collect(Collectors.toList());
//自定义排序,先按价格再按重量(降序)
System.out.println("自定义排序,先按价格再按年龄(降序)");
appleList.stream().sorted((p1, p2) -> {
if (p1.getPrice() == p2.getPrice()) {
return p2.getWeight() - p1.getWeight();
} else {
return p2.getPrice() - p1.getPrice();
}
}).peek(System.out::println).collect(Collectors.toList());
-
flatMap的使用
- 当使用map()操作时,不是返回一个值,而是返回一个集合或者一个数组的时候,这时候就可以使用flatMap解决这个问题。就是扁平化将每个元素映射成另一个Stream对象。
,将两个字符数组合并成一个新的字符数组
List<List<Integer>> lists = new ArrayList<>(); List<Integer> list = new ArrayList<>(); list.add(4444); list.add(33333); list.add(444444); lists.add(list); lists.stream().flatMap(Collection::stream).forEach(System.out::println); List<String> strings = Arrays.asList("m,k,l,a", "1,3,4,5"); List<String> listNew = strings.stream().flatMap(s -> { //将每个元素转成一个新的stream String[] split = s.split(","); Stream<String> s2 = Arrays.stream(split); return s2; }).collect(Collectors.toList()); System.out.println(listNew);
-
去重,合并,跳过,截取(concat,distinct,skip,limit)
//创建两个流 Stream<String> stream1 = Stream.of("1", "2", "", "12", "5"); Stream<String> stream2 = Stream.of("3", "4", "5", "6"); //concat:合并两个流 //distinct:去重 List<String> lists1 = Stream.concat(stream1, stream2) .distinct().collect(Collectors.toList()); //limit:限制从流中获取前n个数据 List<String> collect = stream1.limit(3).collect(Collectors.toList()); //skip:跳过前n个数据 List<String> collect1 = stream1.skip(2).collect(Collectors.toList());
终止操作
-
聚合(max、min、count)
//取出价格最高的苹果 appleList.stream().max(Comparator.comparing(Apple::getPrice)).get(); //取出价格最低的苹果 appleList.stream().min(Comparator.comparing(Apple::getPrice)).get(); //统计元素个数 appleList.stream().count();
-
统计(counting、averaging)
Collectors提供了一系列用于数据统计的静态方法:
-
计数:counting
-
平均值:averagingInt、averagingLong、averagingDouble
-
最值:maxBy、minBy
-
求和:summingInt、summingLong、summingDouble
//求平均重量 Double avg = appleList.stream().collect(Collectors.averagingDouble(Apple::getWeight)); //求和 Integer sum = appleList.stream().collect(Collectors.summingInt(Apple::getWeight)); //统计 List<Integer> orgNums = Arrays.asList(3, 2, 2, 3, 7, 3, 5); IntSummaryStatistics statistics = orgNums.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("列表中最大的数:" + statistics.getMax()); System.out.println("列表中最小的数:" + statistics.getMin()); System.out.println("所有数之和:" + statistics.getSum()); System.out.println("平均数:" + statistics.getAverage());
-
-
遍历/匹配(foreach、find、match)
//foreach appleList.stream().filter(apple -> apple.getColor().equals("blue")) .forEach(System.out::println); //匹配第一个颜色是blue的苹果 appleList.stream().filter(apple -> apple.getColor().equals("blue")) .findFirst(); //匹配任意一个颜色是blue的苹果 appleList.stream().filter(apple -> apple.getColor().equals("blue")) .findAny(); //是否包含符合特定条件的元素 appleList.stream().anyMatch(apple -> apple.getColor().equals("blue"));
-
归集collect(toList、toSet、toMap)
appleList.stream().map(Apple::getDistrict).collect(Collectors.toList()); //调用toMap方法时,如果key重复可以如下处理 Map<String, Apple> collect = appleList.stream().collect(Collectors.toMap(Apple::getDistrict, a->a,(a1,a2)->a1)); //集合去重 Set<Apple> collect1 = appleList.stream().collect(Collectors.toSet());
-
分区、分组(partitioningBy、groupingBy)
-
分区:将stream按条件分为两个Map,比如水果按照价格是否高于12分出两部分。
-
分组:将集合分为多个Map,比如水果按产地分组。有单级分组和多级分组。
//- 分区:将stream按条件分为两个Map,比如水果按照价格是否高于12分出两部分。 Map<Boolean, List<Apple>> collect = appleList.stream().collect(Collectors.partitioningBy(apple -> apple.getPrice() > 12)); //- 分组:将集合分为多个Map,比如水果按产地分组。有单级分组和多级分组。 Map<String, List<Apple>> collect1 = appleList.stream().collect(Collectors.groupingBy(apple -> apple.getDistrict()));
-
-
拼接(joining)
List<String> list = Arrays.asList("1","2","3","4"); //以空字符拼接,输出 1234 String result= list.stream().collect(Collectors.joining()); //以“-”符号拼接,输出1-2-3-4 String result1= list.stream().collect(Collectors.joining("-")); System.out.println(result1);
-
多个参数
joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) 方法接受一个字符串序列作为拼接符,并在拼接完成后添加传递的前缀和后缀。假如我们传递的分隔符为 “-”,前缀为 “[” , 后缀为 “]” 。那么输出结果为 [1-2-3-4]
List<String> arrayList = Arrays.asList("1","2","3","4");
String collect = arrayList.stream().collect(Collectors.joining(",", "[", "]"));