流
筛选各异的元素
流还支持一个叫作distinct的方法,它会返回一个元素各异(根据流所生成元素的
hashCode和equals方法实现)的流。例如,以下代码会筛选出列表中所有的偶数,并确保没有
重复。图5-2直观地显示了这个过程。
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream().filter(i -> i % 2 == 0).distinct().forEach(System.out::println);
截短流
截短流
流支持limit(n)方法,该方法会返回一个不超过给定长度的流。所需的长度作为参数传递
给limit。如果流是有序的,则最多会返回前n个元素。比如,你可以建立一个List,选出热量
超过300卡路里的头三道菜:
List<Dish> dishes = menu.stream().filter(d -> d.getCalories() > 300).limit(3).collect(toList());
跳过元素
流还支持skip(n)方法,返回一个扔掉了前n个元素的流。如果流中元素不足n个,则返回一
个空流。请注意,limit(n)和skip(n)是互补的!例如,下面的代码将跳过超过300卡路里的头
两道菜,并返回剩下的。
List<Dish> dishes = menu.stream().filter(d -> d.getCalories() > 300).skip(2).collect(toList());
流的扁平化
例如, 给定单词列表[“Hello”,“World”],你想要返回列表[“H”,“e”,“l”, “o”,“W”,“r”,“d”]。
List<String> words = Arrays.asList("Hello", "World");
List<String> uniqueCharacters =
words.stream()
.map(w -> w.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList());
uniqueCharacters.stream().forEach(System.out::println);
查找和匹配
另一个常见的数据处理套路是看看数据集中的某些元素是否匹配一个给定的属性。Stream
API通过allMatch、anyMatch、noneMatch、findFirst和findAny方法提供了这样的工具。
if(menu.stream().anyMatch(Dish::isVegetarian)){
System.out.println("The menu is (somewhat) vegetarian friendly!!");
}
//anyMatch方法返回一个boolean,因此是一个终端操作。
最大值和最小值
原来,只要用归约就可以计算最大值和最小值了!让我们来看看如何利用刚刚学到的reduce
来计算流中最大或最小的元素。正如你前面看到的,reduce接受两个参数:
//最大值
List<Integer> numbers= Arrays.asList(4, 5, 3, 9);
Optional<Integer> max = numbers.stream().reduce(Integer::max);
//最小值
List<Integer> numbers= Arrays.asList(4, 5, 3, 9);
Optional<Integer> min= numbers.stream().reduce(Integer::min);