Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
Stream(流)是一个来自数据源的元素队列并支持聚合操作
元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
数据源流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
聚合操作类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
在 Java 8 中, 集合接口有两个方法来生成流:
stream()− 为集合创建串行流。
parallelStream()− 为集合创建并行流。
List<String> strings = Arrays.asList("AAA", "BBB", "CCC", "DDD");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
复制代码
筛选Boolean为true的数据
//筛选查询ID=20 的数据
List<CustomerVO> customerVOList = getArrayList();
List<CustomerVO> idList= customerVOList.stream().filter(customerVO -> customerVO.getId().equals(20)).collect(Collectors.toList());
复制代码
去除重复元素,根据类的equals判断是否相同
//筛选ID大于0并且去重的数据
List<CustomerVO> customerDistinctList =customerVOList.stream().filter(t->t.getId().compareTo(0)==1).distinct().collect(Collectors.toList());
复制代码
将流中的每一个元素 T 映射为一个流,再把每一个流连接成为一个流
//1.获取到customerVOList中的收货方
List<String> receiveNoList = customerVOList.stream().map(CustomerVO::getReceiveNo).collect(Collectors.toList());
//filter和map函数结合
List<String> receiveNoList2=customerVOList.stream().filter(customerVO -> customerVO.getId().equals(20)).map(CustomerVO::getReceiveNo).collect(Collectors.toList());
复制代码
流中是否有一个元素匹配给定的 T -> boolean
条件
//customerVOList是否存在一个 CustomerVO 对象的 id 等于 20:
boolean resultBool= customerVOList.stream().allMatch(person -> person.getId() == 20);
复制代码
//customerVOList是否 CustomerVO 对象的 id 都等于 20:
boolean resultBool= customerVOList.stream().allMatch(person -> person.getId() == 20);
复制代码
//customerVOList是否不存在 CustomerVO 对象的 id 等于 20:
boolean resultBool= customerVOList.stream().noneMatch(person -> person.getId() == 20);
复制代码
findAny():找到其中一个元素 (使用 stream() 时找到的是第一个元素;使用 parallelStream() 并行时找到的是其中一个元素)
findFirst():找到第一个元素
这两个方法返回的是一个 Optional 对象,它是一个容器类,能代表一个值存在或不存在
limit,findFirst, 因为这两个方法会考虑元素的顺序性,而并行本身就是违背顺序性的,也是因为如此 findAny 一般比 findFirst 的效率要高
//findFirst
Optional<CustomerVO> voOptional= customerVOList.stream().filter(cp->cp.getId().compareTo(0)==0).findFirst();
if (voOptional.isPresent()){
System.out.println(voOptional.get());
}
//findAny
Optional<CustomerVO> voOptional= customerVOList.stream().filter(cp->cp.getId().compareTo(0)==0).findAny();
if (voOptional.isPresent()){
System.out.println(voOptional.get());
}
复制代码
将流中的每一个元素 T 映射为一个流,再把每一个流连接成为一个流
eg:1
//查询收货方
List<String> receiveNoList = customerVOList.stream().map(CustomerVO::getReceiveNo).collect(Collectors.toList());
//eg:2
List<String> list = new ArrayList<>();
list.add("aaa bbb ccc");
list.add("ddd eee fff");
list.add("ggg hhh iii");
list = list.stream().map(s -> s.split(" ")).flatMap(Arrays::stream).collect(toList());
复制代码
上面例子中,我们的目的是把 List 中每个字符串元素以" "分割开,变成一个新的 List。 首先 map 方法分割每个字符串元素,但此时流的类型为 Stream<String[ ]>,因为 split 方法返回的是 String[ ] 类型;所以我们需要使用 flatMap 方法,先使用Arrays::stream将每个 String[ ] 元素变成一个 Stream 流,然后 flatMap 会将每一个流连接成为一个流,最终返回我们需要的 Stream
返回前n个元素
//返回前2个元素
list = customerVOList.stream()
.limit(2)
.collect(toList());
复制代码
去除前n和元素
list = customerVOList.stream()
.skip(2)
.collect(toList());
复制代码
用在 limit(n) 前面时,先去除前 m 个元素再返回剩余元素的前 n 个元素
limit(n) 用在 skip(m) 前面时,先返回前 n 个元素再在剩余的 n 个元素中去除 m 个元素
//skip/limit 获取List中低n->m的数据 [获取id 2到10之间的数据]
customerVOList.stream().sorted(Comparator.comparing(CustomerVO::getId).reversed()).skip(2).limit(10).collect(Collectors.toList());
复制代码
如果流中的元素的类实现了 Comparable 接口,即有自己的排序规则,那么可以直接调用 sorted() 方法对元素进行排序,如 Stream
反之, 需要调用 sorted((T, T) -> int)
实现 Comparator 接口
//根据ID大小进行比较
list = customerVOList.stream()
.sorted((p1, p2) -> p1.getId() - p2.getId())
.collect(toList())
//还以可以写成
customerVOList.stream().filter(cp->cp.getId().compareTo(0)==1). sorted(Comparator.comparing(CustomerVO::getId).reversed().thenComparing(CustomerVO::getId)).collect(Collectors.toList());
//可以简化为
list = customerVOList.stream()
.sorted(Comparator.comparingInt(CustomerVO::getId))
.collect(toList());
复制代码
//使用forEash调用方法
customerVOList.stream().forEach(cp->getSendNOLambda(cp.getSendNo(),cp.getReceiveNo()));
//当ID大于0循环输出
customerVOList.stream().filter(cp->cp.getId()>0).forEach(System.out::println);
private void getSendNOLambda(String sendNo,String receiveNo){
System.out.println(sendNo+','+receiveNo);
}
复制代码
//转换为Map[获取ID大于0的发货方和收货方转换为Map]
Map<String,String> stringMap=customerVOList.stream().filter(customerVO -> customerVO.getId()>0).collect(Collectors.toMap(CustomerVO::getSendNo,CustomerVO::getReceiveNo));
复制代码
//1.不带参数返回的是Object数组
Object[] receiveNoArray= customerVOList.stream().filter(cp->cp.getId()>0).map(CustomerVO::getReceiveNo).toArray();
String[] receiveArray= customerVOList.stream().filter(cp->cp.getId()>0).map(CustomerVO::getReceiveNo).toArray(String[]::new);
CustomerVO[] customerVOArray= customerVOList.stream().filter(cp->cp.getId()>0).toArray(CustomerVO[]::new);
复制代码
groupingBy 用于将数据分组,最终返回一个 Map 类型
//其中返回的 Map 键为 Integer 类型,值为 Map<T, List> 类型,即参数中 groupBy(...) 返回的类型
Map<Integer, List<CustomerVO>> map = list.stream().collect(groupingBy(CustomerVO::getId));
复制代码
// groupingBy(CustomerVO::getId) 等同于 groupingBy(CustomerVO::getId, toList())
复制代码
maxBy,minBy 两个方法,需要一个 Comparator 接口作为参数
//1.最大值
Optional<CustomerVO> optional = customerVOList.stream().collect(maxBy(comparing(CustomerVO::getId)));
//2.最小值
Optional<CustomerVO> optiona2 = customerVOList.stream().collect(minBy(comparing(CustomerVO::getId)));
//优化
Optional<CustomerVO> optional = customerVOList.stream().max(comparing(CustomerVO::getId));
复制代码
//1.计算总数
long listCount = customerVOList.stream().collect(counting());
long listCount2 = customerVOList.stream().count();//推荐
//2.summingInt ,summingLong ,summingDouble
Integer sum = customerVOList.stream().collect(summingInt(CustomerVO::getMoney));
Integer sum2 = customerVOList.stream().mapToInt(CustomerVO::getMoney).sum();
//3.averagingInt,averagingLong,averagingDouble
Double average = customerVOList.stream().collect(averagingInt(CustomerVO::getMoney));
OptionalDouble average2 = customerVOList.stream().mapToInt(CustomerVO::getAge).getMoney();
复制代码
**推荐阅读 **
Java 8系列之Stream的基本语法详解
Java集合Stream类filter的使用
如果你觉得我的文章对你有帮助话,欢迎点赞:+1: 关注:heart: 分享:busts_in_silhouette:! 如果本篇博客有任何错误,请批评指教,不胜感激! 点个在看,分享到朋友圈,对我真的很重要!!!