Skip to main content
 首页 » 编程设计

Java Stream API 新增功能

2022年07月19日117softidea

Java 9 Stream API 新增功能

本文聚焦Java 9 Stream API 新增功能。

1. Stream Takewhile/Dropwhile

假如我们需要生成字符串流,增加一个字符至前一个流的值,直到流当前值的长度小于10.
在java8中如何实现?需要使用短路的中间操作如,limit,allMatch(实际上用于其他目的)。或者基于Spliterator实现自己的takeWhile。总之,把简单问题复杂化。

Java9的实现非常简单:

Stream<String> stream = Stream.iterate("", s -> s + "s") 
  .takeWhile(s -> s.length() < 10); 

takeWhile操作带一个Predicate参数,其应用于元素决定在所有元素中取最长的前缀(如果流是有序的),或者流所有元素的子集(流是无序的)。

继续学习之前最好理解“最长的前缀”和“流的子集”是什么意思:

  • 最长的前缀:匹配条件的流中连续元素序列. 序列的第一个元素是流的第一个元素, 紧接在序列最后一个元素后面的元素与给定的谓词不匹配。

  • “流的子集:流中匹配条件的部分元素集合。

介绍完这些关键术语后,我们可以较容易地理解另一个新的dropWhile操作。

它恰好是takeWhile的相反操作,如果流是有序的,dropWhile返回的流,是删除了最长前缀后留下元素集合。如果流是无序的,dropWhile返回的流包括删除匹配条件的子集后留下元素的集合。

使用前缀获得流实现丢弃前五个元素:

stream.dropWhile(s -> !s.contains("sssss")); 

简言之,dropWhile操作删除对于给定条件返回true的元素,并第一次遇到条件返回false停止删除。

2. Stream Iterate

接着介绍新特性是重载iterate方法实现有限流生成。不要与另一个重载static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)方法混淆,其返回有函数生成的无限顺序序列流。

新的iterate增加了一个predicate决定生成流什么条件必须终止,其使用很方便、简洁:

Stream.iterate(0, i -> i < 10, i -> i + 1) 
  .forEach(System.out::println); 

其对应的for语句为:

for (int i = 0; i < 10; ++i) { 
    System.out.println(i); 
} 

3. Stream Ofnullable

有时添加至流中的元素可能为null,我们并不希望这样值存在流中。因此需要些if条件语句或三元运算符检查元素是否为null。

假如我们有collection 和 map 变量,内容如下:

List<String> collection = Arrays.asList("A", "B", "C"); 
Map<String, Integer> map = new HashMap<>() { 
    { 
        put("A", 10); 
        put("C", 30); 
    } 
}; 

请看下面示例:

collection.stream() 
  .flatMap(s -> { 
      Integer temp = map.get(s); 
      return temp != null ? Stream.of(temp) : Stream.empty(); 
    }) 
  .collect(Collectors.toList()); 

这里需要判断temp是否为null,导致flatMap方法过于冗长。为了避免使用Stream类的ofNullable方法,相同功能代码非常简洁:

collection.stream() 
  .flatMap(s -> Stream.ofNullable(map.get(s))) 
  .collect(Collectors.toList()); 

4. 总结

本文介绍了Java 9 Stream Api中新增的方法,这些增强功能会帮助使用更少的代码实现强大功能。


本文参考链接:https://blog.csdn.net/neweastsun/article/details/103650977
阅读延展