jdk 8 Stream的简单运用
概述
- Stream api的介绍网上不少,这里不多说了,本文主要总结一下可能对你有帮助的stream的简单操作,你可以在这些小例子中举一反三得到更多有用的能够简化你代码的写法。文末贴上一些本文的参考资料,它们介绍得比较全面。
- 废话不多说立刻上例子。
创建Stream
-
列举常用的创建方法
-
Stream.of(T... values)
-
Arrays.stream(T[] array)
-
Collection.stream()
List<String> list = Arrays.asList(strArray); stream = list.stream();
-
循环输出forEach
Arrays.asList(11,12,13,14,15,16).stream().forEach(System.out::print);
,串行保持顺序Arrays.asList(1,2,3,4,5,6,7,8).parallelStream().forEach(System.out::print)
,并行不会按照顺序输出Arrays.asList(11,12,13,14,15,16).stream().forEach(x -> System.outprint(x))
,这种迭代你也在lambda表达式中做其它事,当然不能修改元素。
filter
- 过滤掉空字符串:
List<String> filtered = Stream.of("abc", "", "bc", "efg", "abcd","", "jkl").filter(string -> !string.isEmpty()).collect(Collectors.toList())
map
- 每一个列表元素平方组成的列表:
List<Integer> list = Stream.of(1, 2, 3, 4, 5).map(x -> x * x).collect(Collectors.toList());
- 用户列表中只选取用户的id并组成新的列表:
List<Integer> integerList = userList.stream().map(User::getId).collect(Collectors.toList());
,这种User::getId
实际上为方法引用,后面会多出用到,当然这里也可以写成lambda表达式。 - 统计用户列表中所有用户的年龄总和:
Integer age = userList.stream().mapToInt(User::getAge).sum();
reduce
- 求和
- 不指定累加初始值:
Arrays.asList(11,12,13,14,15,16).stream().reduce((a,b) -> a+b).get()
或者Arrays.asList(11,12,13,14,15,16).stream().reduce( Integer::sum).get()
- 指定累加初始值为0:
Arrays.asList(11,12,13,14,15,16).stream().reduce(0, (a,b) -> a+b)
或者Arrays.asList(11,12,13,14,15,16).stream().reduce(0, Integer::sum)
。上面两个例子可以看出reduce可以指定初始值,如果不指定会得到一个Optional对象。下面为了省略代码就只使用其中一种方法。 - 注意:只有IntStream、DoubleStream、LongStream才有average、sum等方法,其它需要自己使用reduce来定义自己的规约方法。后面也会使用collect实现类似功能。
- 不指定累加初始值:
- 拼接字符串:
String message = Arrays.asList("hello ", "world", "!").stream().reduce("", String::concat);
最大值、最小值、平均值
- 基本类型
- 最大值:
Arrays.asList(3, 2, 2, 3, 7, 3, 5).stream().max((a, b) -> a - b).get()
或者Arrays.asList(3, 2, 2, 3, 7, 7, 5).stream().max(Comparator.comparingInt(Integer::intValue)).get()
- 最小值:同上理,调用min
- 平均值:
Arrays.asList(3, 2, 2, 3, 7, 7, 5).stream().collect(Collectors.averagingInt(Integer::intValue))
- 最大值:
- 引用类型
- 得到年龄最大的用户:
userList.stream().max(Comparator.comparingInt(User::getAge))
,当然也可以像上面一样写lambda - 得到年龄最小的用户:同理
- 用户的平均年龄:
userList.stream().collect(Collectors.averagingInt(User::getAge))
- 得到年龄最大的用户:
排序
- 调用sort(),传一个Comparator,像上面一样,不再多说
列表匹配条件
- 返回都是boolean值
- anyMatch:只要一个元素满足就为true
- nonMatch:都不满足为true
- allMatch:都满足为true
- 例子:
Arrays.asList(3, 2, 2, 3, 7, 3, 5).stream().anyMatch(a -> a >= 7)
其他简单的api
- distinct : 去掉多余的元素(比如原本有多个1最后只剩下一个1)
- limit : 流取前k个元素
- skip : 流跳过前k个元素
- findFirst : 拿到第一个元素
- 生成随机数列表 : 调用Random类的ints、doubles、longs(传入长度,下界,上界),再次调用boxed()就可以得到List了
分组
- 同一学校学生分一组:
Map<String, List<Student>> groups = students.stream().collect(Collectors.groupingBy(Student::getSchool));
- 统计出现数字次数:
Map<Integer, Long> map = Stream.of(1, 2, 3, 4, 2, 1, 5).collect(Collectors.groupingBy(Integer::intValue, Collectors.counting()));
,也从而可以得到出现频率最高的数字(只有一个):Integer max = map.entrySet().stream().max((x, y) -> (int) (x.getValue() - y.getValue())).get().getKey()
分区
- 类似二分,满足某个条件的一边,否则另一边
- 合格不合格学生分两边:
Map<Boolean, List<Student>> passingFailing = students.stream() .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
- 合格不合格学生分两边:
参考资料
- https://www.baeldung.com/java-8-streams
- http://www.runoob.com/java/java8-streams.html
- https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/
- http://www.cnblogs.com/CarpenterLee/p/6550212.html