当前位置:   article > 正文

记:复习java 8 stream 流式写法_flatmap(collection::stream)

flatmap(collection::stream)

今天花了几个小时复习了下 java 8的stream,许久不用,怕忘记,整理下常用知识。

stream lambda 结合真是有如猛虎添翼,大大提升了开发效率,可读性也提高,效率也有提升,所以还是推荐用lambda和stream,真的是优胜于传统for循环太多了。

  1. import java.util.*;
  2. import java.util.function.Function;
  3. import java.util.stream.Collectors;
  4. import java.util.stream.Stream;
  5. /**
  6. * @author luwt
  7. * @date 2019/12/5.
  8. */
  9. public class TestStream {
  10. /**
  11. * 流共分为三大部分:
  12. * 1、打开流
  13. * 2、对流的具体操作
  14. * 3、终止操作
  15. * 流是惰性操作,只有在遇到终止操作才会计算出结果,否则都只是一个过程状态。
  16. * 所以想要获取结果,必须要有终止操作;对流的中间操作都会的到一个过程状态,
  17. * 这个过程状态是可以继续传递给下个流进行操作的。
  18. * 需要注意的是,流是不可逆的操作,一次消费结束后(终止操作后),本次的流就结束了。
  19. * 不可以在终止操作之后再对流进行任何操作。
  20. */
  21. /**
  22. * 需要注意的是打开流之前最好能确定集合或数组非空,如果是空会抛空指针异常
  23. * @param type
  24. * @return
  25. */
  26. private static Stream openStream(String type){
  27. // 数组打开方式
  28. Integer[] array = new Integer[]{1, 3, 1, 2, 5, 2, 6, 4};
  29. Stream<Integer> arrayStream = Arrays.stream(array);
  30. // 集合打开方式,即:Collection.stream()
  31. List<String> list = new ArrayList<String>(){{add("a"); add("b"); add("c");}};
  32. Stream<String> listStream = list.stream();
  33. return type.equals("array") ? arrayStream : listStream;
  34. }
  35. /**
  36. * 对流的操作(常用的):
  37. * filter:过滤,从流中筛选出符合条件(断言)的元素;
  38. * map:映射,将流中的每一个元素都执行一个操作,即将某个操作映射到每个元素上;
  39. * flatmap:扁平化操作,可以将二维数组合并为一个一维数组;
  40. * distinct:对流中元素去重;
  41. * limit:取前多少元素;
  42. * skip:跳过多少元素;
  43. * sorted:排序,可以自定义。
  44. * 其他的像 mapToInt等,都是对上面操作的一个增进。
  45. * @param stream
  46. * @return
  47. */
  48. private static Stream operateStream(Stream<Integer> stream, String type){
  49. if (type.equals("filter")) {
  50. // filter,传入一个断言,或者一个条件,符合的元素将被筛出来
  51. // out -> [5 6 4]
  52. stream = stream.filter(a -> a > 3);
  53. } else if (type.equals("map")) {
  54. // map,对每个元素都执行指定操作
  55. // out -> [1 9 1 4 25 4 36 16]
  56. stream = stream.map(a -> a * a);
  57. } else if (type.equals("flatmap")){
  58. // flatmap,将多个小的流合并为一个大的流,即扁平化,创建一个二维数组,扁平化将会把其变为一个一维数组。
  59. // out -> [10 11 12 13 14 15]
  60. Integer[] a = new Integer[]{10, 11, 12};
  61. Integer[] b = new Integer[]{13, 14, 15};
  62. // 下面两种写法是一样的,c1 与 listStream相同
  63. List<Integer[]> c = new ArrayList<Integer[]>(){{add(a); add(b);}};
  64. Stream<List<Integer[]>> c1 = Stream.of(c);
  65. Stream<List<Integer>> listStream = Stream.of(Arrays.asList(a), Arrays.asList(b));
  66. return listStream.flatMap(Collection::stream);
  67. } else if (type.equals("distinct")){
  68. // distinct 去重操作
  69. // out -> [1 3 2 5 6 4]
  70. stream = stream.distinct();
  71. } else if (type.equals("limit")){
  72. // limit 取前多少个元素
  73. // out -> [1 3 1]
  74. stream = stream.limit(3);
  75. } else if (type.equals("skip")){
  76. // skip 跳过前多少个元素
  77. // out -> [1 2 5 2 6 4]
  78. stream = stream.skip(2);
  79. } else if (type.equals("sorted")) {
  80. // sorted 排序
  81. // out -> [1 1 2 2 3 4 5 6]
  82. stream = stream.sorted();
  83. // 自定义排序,将小于5的值都放到前面
  84. // out -> [4 2 2 1 3 1 5 6],顺序是按-1, 0, 1来排的
  85. stream = stream.sorted((x, y) -> {
  86. if (x < 5) {
  87. return -1;
  88. } else if (x.equals(y)){
  89. return 0;
  90. } else {
  91. return 1;
  92. }
  93. });
  94. // 也可以这样写,与第一种写法类似,接收一个comparator
  95. // out -> [1 1 2 2 3 4 5 6]
  96. stream = stream.sorted(Comparator.comparing(Integer::intValue));
  97. }
  98. return stream;
  99. }
  100. /**
  101. * 终止流的操作(消费):
  102. * reduce:将流内的元素进行聚合操作,譬如做算术运算,其结果为一个Optional容器;
  103. * foreach:将流内的元素消费掉,接收一个函数用以消费流;
  104. * collect:将流内的元素收集起来;
  105. * count:统计流内元素个数;
  106. * findAny: 从流内元素随机返回一个值,放入Optional容器;
  107. * findFirst:将流内元素的第一个值取出,放入Optional容器;
  108. * max、min:求流内元素的最大或最小值,放入Optional容器;
  109. * toArray:将流内元素转为一个数组;
  110. * allMatch:接收一个断言(一个匹配条件),判断元素是否全部匹配,返回布尔值;
  111. * anyMatch:接收一个断言(一个匹配条件),判断是否存在匹配的元素,返回布尔值;
  112. * noneMatch:接收一个断言(一个匹配条件),判断是否全部不匹配,返回布尔值。
  113. * !!!需要注意的是,终止操作只能执行一次,消费一次流就没有了,就不能再消费了!!!
  114. * @param stream
  115. * @return
  116. */
  117. private static void terminalStream(Stream<Integer> stream, String operation){
  118. if (operation.equals("reduce")){
  119. Optional<Integer> reduce;
  120. // reduce = stream.reduce((x, y) -> x + y);
  121. // 等同于下面的写法,reduce将会产生一个Optional容器对象,
  122. // 该容器只能存一个值,或者没有。
  123. // Optional容器取值用get方法,判断是否有值用isPresent方法
  124. // out -> [24]
  125. reduce = stream.reduce(Integer::sum);
  126. if (reduce.isPresent())
  127. System.out.println(reduce.get());
  128. } else if (operation.equals("foreach")){
  129. // 消费流,接收一个函数,没有返回值
  130. // out -> [1 3 1 2 5 2 6 4]
  131. stream.forEach(System.out::println);
  132. } else if (operation.equals("collect")){
  133. // 将流中的元素收集起来:
  134. // 收集为 list
  135. // out -> [1, 3, 1, 2, 5, 2, 6, 4]
  136. // List<Integer> list = stream.collect(Collectors.toList());
  137. // System.out.println(list);
  138. // 收集为 set
  139. // out -> [1, 2, 3, 4, 5, 6]
  140. // Set<Integer> set = stream.collect(Collectors.toSet());
  141. // System.out.println(set);
  142. // 收集为 map,由于我这里举例的是一个纯数字的数组,所以收集为map的时候没有办法指定元素的某个属性,
  143. // 就直接将该元素设为key和value,Function.identity()指向元素本身,也可以用lambda表达式 x-> x,
  144. // 如果是实际业务,流中的元素为一个实体类,那么久可以用 x -> x.getProperty(),指定属性了。
  145. // 尤其需要注意的是:map是不允许键重复的,,所以在键如果会重复的情况下,需要指定一个合并冲突的方法,
  146. // 这里用第二个键覆盖第一个。
  147. // out -> {1=1, 2=2, 3=3, 4=4, 5=5, 6=6}
  148. // Map<Integer, Integer> map = stream.collect(Collectors.toMap(Function.identity(), x -> x, (v1, v2) -> v2));
  149. // System.out.println(map);
  150. // 分组,结果也是map,与上面的直接放入map不同的是,这里的键就是指定的键,值是符合条件的元素,将会被放入一个list
  151. // out -> {1=[1, 1], 2=[2, 2], 3=[3], 4=[4], 5=[5], 6=[6]}
  152. Map<Integer, List<Integer>> groupMap = stream.collect(Collectors.groupingBy(Function.identity()));
  153. System.out.println(groupMap);
  154. } else if (operation.equals("count")) {
  155. // 统计元素个数
  156. // out -> [8]
  157. long count = stream.count();
  158. System.out.println(count);
  159. } else if (operation.equals("findAny")){
  160. // 随机返回一个值
  161. // out -> [1]
  162. Optional<Integer> any = stream.findAny();
  163. any.ifPresent(System.out::println);
  164. } else if (operation.equals("findFirst")){
  165. // 返回第一个值
  166. // out -> [1]
  167. Optional<Integer> first = stream.findFirst();
  168. first.ifPresent(System.out::println);
  169. } else if (operation.equals("max|min")){
  170. // 返回最大值
  171. // out -> [6]
  172. // Optional<Integer> max = stream.max(Integer::compareTo);
  173. // max.ifPresent(System.out::println);
  174. // 返回最小值
  175. // out -> [1]
  176. Optional<Integer> min = stream.min(Integer::compareTo);
  177. min.ifPresent(System.out::println);
  178. } else if (operation.equals("toArray")){
  179. // 转为数组
  180. // out -> [1, 3, 1, 2, 5, 2, 6, 4]
  181. Object[] array = stream.toArray();
  182. System.out.println(Arrays.toString(array));
  183. } else if (operation.equals("allMatch")){
  184. // 全匹配
  185. // out -> true
  186. boolean allMatch = stream.allMatch(x -> x.compareTo(0) > 0);
  187. System.out.println(allMatch);
  188. } else if (operation.equals("anyMatch")){
  189. // 只要匹配一个即可
  190. // out -> true
  191. boolean anyMatch = stream.anyMatch(x -> x.compareTo(5) > 0);
  192. System.out.println(anyMatch);
  193. } else if (operation.equals("noneMatch")){
  194. // 都不匹配的情况
  195. // out -> true
  196. boolean noneMatch = stream.noneMatch(x -> x.compareTo(0) < 0);
  197. System.out.println(noneMatch);
  198. }
  199. }
  200. public static void main(String[] args) {
  201. Stream stream = openStream("array");
  202. // operateStream(stream, "sorted").forEach(s -> System.out.printf("%d ", s));
  203. terminalStream(stream, "collect");
  204. }
  205. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/537119
推荐阅读
相关标签
  

闽ICP备14008679号