1 public static void main(String [] args) {
2 //Stream API
3 List<String> arrList1 = Arrays.asList("predicate1", "collect1", "map1", "flatmap1", "reduce1", "collect1");
4 List<String> arrList2 = Arrays.asList("predicate2", "collect2", "map2", "flatmap2", "reduce2", "collect2");
5 List<List<String>> arrAll = Arrays.asList(arrList1, arrList2);
6 System.out.println(arrList1.stream().filter(i -> i.length() > 5).collect(Collectors.toList()));
7 System.out.println(arrList1.stream().map(i -> i.toUpperCase()).collect(Collectors.toList()));
8 //flatmap 将流中数据扁平化处理,其中参数二是一个 Stream 对象。本例中将所有字符数组扁平化到一个流中
9 arrList1.stream().map(i -> i).flatMap(i -> Stream.of(i.toCharArray())).forEach(i -> System.out.println(Arrays.toString(i)));
10 //flatmap 将流中数据扁平化处理,其中参数二是一个 Stream 对象。本例针对的是 List<List<String>> 结构数据,将多个 List 中的数据扁平化到一个流中
11 System.out.println(arrAll.stream().flatMap(i -> i.stream()).collect(Collectors.toList()));
12 //流元素去重
13 System.out.println(arrList1.stream().distinct().collect(Collectors.toList()));
14 //流元素排序
15 System.out.println(arrList1.stream().sorted(String::compareTo).collect(Collectors.toList()));
16 //peek 不影响最终 collect 操作。类似数据预览效果
17 System.out.println(arrList1.stream().peek(i -> {
18 i += "suffix";
19 System.out.println(i);
20 }).collect(Collectors.toList()));
21 //类似数据库分页查询操作
22 System.out.println(arrList1.stream().skip(1).limit(3).collect(Collectors.toList()));
23 //遍历消费流中元素
24 arrList1.stream().forEach(System.out::println);
25 //流转数组
26 Object[] objects = arrList1.stream().toArray();
27 //通过 i,可以显示的创建一个大小固定的数组
28 Object[] strings = arrList1.stream().toArray(i -> {
29 System.out.println("i = " + i);
30 return new Object[i];
31 });
32 System.out.println(Arrays.toString(strings));
33 //精简写法,并且可以免去泛型强转的问题
34 String[] strings1 = arrList1.stream().toArray(String[]::new);
35 System.out.println(Arrays.toString(strings1));
36 //reduce,汇聚操作,对流中的每个元素按一定规则计算,最终输出一个值,内置的汇聚操作有求和、求平均值、最大值等
37 arrList1.stream().reduce((a, b) -> a.concat(b)).ifPresent(i -> System.out.println(i));
38 System.out.println(arrList1.stream().reduce("prefix", (a, b) -> a.concat(b)));
39 //reduce 的重载形式,计算流中字符的总个数,参数一是一个初始值
40 System.out.println(arrList1.stream().reduce(0, (a, b) -> a += b.length(), (a, b) -> a+= b));
41 //求最大值和最小值,本质上使用的就是 reduce
42 arrList1.stream().min((a, b) -> a.length() - b.length()).ifPresent(i -> System.out.println(i));
43 arrList1.stream().max((a, b) -> a.length() - b.length()).ifPresent(i -> System.out.println(i));
44 //求个数(可以使用 peek 配合 reduce,可以同时得出多个汇聚后的值,而不是一个)
45 System.out.println(arrList1.stream().count());
46 //任意匹配返回 true
47 System.out.println(arrList1.stream().anyMatch(i -> "map1".equals(i)));
48 //全部匹配返回 true
49 System.out.println(arrList1.stream().allMatch(i -> i.length() > 0));
50 //全部都不匹配返回 true
51 System.out.println(arrList1.stream().noneMatch(i -> i.length() < 0));
52 //找出流中第一个元素
53 arrList1.stream().findFirst().ifPresent(i -> System.out.println(i));
54 //找出流中任意一个元素
55 arrList1.stream().findAny().ifPresent(i -> System.out.println(i));
56 }
57
58
59 public static void main1(String[] args) {
60
61
62 //Collectors API
63 StringBuilder builder = Stream.of("supplier", "consumer", "producer")
64 .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append);
65 System.out.println(builder);
66 int[] intArr = Arrays.asList(1, 2, 3, 4, 5).stream()
67 .collect(() -> new int[1], (a, b) -> a[0] += b, (a, b) -> a[0] += b[0]);
68 System.out.println(Arrays.toString(intArr));
69 Collectors collectors;
70 Stream.<String>of().collect(Collectors.<String>toList());
71 StringJoiner joiner = new StringJoiner(";", "pre", "suf");
72 joiner.add("supplier").add("consumer").add("producer");
73 System.out.println("merge : " + joiner.toString());
74 List<String> list = Arrays.asList("supplier", "consumer", "producer");
75 //在应用一个下游收集器之前,对流中的元素做一次 map 转换
76 System.out.println(list.stream().collect(Collectors.mapping(String::toUpperCase, Collectors.toList())));
77 //先应用了一个下游收集器,然后对下游收集器的结果应用一个 Function 进行转换。理解 Charactristic 的几个枚举值
78 String collect = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), r -> StringUtils.join(r, ";")));
79 System.out.println(collect);
80 List<Integer> nums = Arrays.asList(1, 3, 5, 7, 9, 11);
81 System.out.println("couting1 : " + nums.stream().collect(Collectors.counting()));
82 Integer collect1 = nums.stream().parallel().collect(new Collector<Integer, int[], Integer>() {
83 @Override
84 public Supplier supplier() { return () -> new int[1]; }
85
86 @Override
87 public BiConsumer<int [], Integer> accumulator() { return (a, b) -> a[0] = 1; }
88
89 @Override
90 public BinaryOperator<int []> combiner() {
91 return (a, b) -> {
92 System.out.println("a = " + a + " , b = " + b);
93 System.out.println(Thread.currentThread().getName() + ":" + a[0] + ":" + b[0]);
94 a[0] = a[0] + b[0];
95 return a;
96 };
97 }
98 @Override
99 public Function<int [], Integer> finisher() { return (a) -> a[0];}
100
101 @Override
102 public Set<Characteristics> characteristics() { return Collections.emptySet();}
103 });
104 System.out.println("couting2 : " + collect1);
105 //其实本质上也是 reduce 的调用,也符合下面的规则,流中元素 -> 输出为一个值
106 nums.stream().collect(Collectors.minBy((a, b) -> a - b)).ifPresent(System.out::println);
107 nums.stream().collect(Collectors.maxBy((a, b) -> a - b)).ifPresent(System.out::println);
108 System.out.println(nums.stream().collect(Collectors.summingInt(a -> a * 2)));
109 //reduce 函数的作用是将流中的多个元素,按照某种规则,输出为一个值。比如统计 Count、求和、元素转 String 等
110 System.out.println(nums.stream().collect(Collectors.<Integer, String>reducing("", a -> "{" + a + "}", (a, b) -> a + b)));
111 Map<String, Object> m1 = new HashMap<>();
112 m1.put("a", 123);
113 m1.put("b", 456);
114 m1.put("c", 789);
115 //HashMap 中的这个方法,将新值和旧值合并;旧值就是通过 get("a") 获取,新值就是 111。合并规则由 BinaryOperator 指定
116 m1.merge("d", 111, (a, b) -> a + "-" + b);
117 System.out.println(m1);
118 m1.replaceAll((k, v) -> k + '-' + v);
119 System.out.println("after replace All : " + m1);
120 for(Map.Entry<String, Object> entry : m1.entrySet()) {
121 m1.merge(entry.getKey(), "111", (a, b) -> a + "-" + b);
122 }
123 System.out.println(m1);
124 List<String> list1 = Arrays.asList("aaSupplier11", "ccComsumer12", "ccProducer13", "ccEntry14", "aaMap15", "ccProducer16");
125 Map<String, List<String>> result1 = list1.stream().collect(Collectors.groupingBy(a -> a.startsWith("aa") ? "aa" : "bb"));
126 System.out.println(result1);
127 Map<String, List<String>> result2 = list1.stream().collect(
128 Collectors.<String, String, List<String>, List<String>>groupingBy(
129 a -> a.startsWith("aa") ? "aa" : "cc", (Collector<? super String, List<String>, List<String>>) Collectors.<String>toList()));
130 System.out.println(result2);
131 //最底层的 groupBy,需要提供的有:键的分类器、保存结果的 Map 容器、容器中值对应的类型(一般是 List)
132 Map<String, Set<String>> result3 = list1.stream().collect(Collectors.<String, String, Set<String>, Set<String>, Map<String, Set<String>>>groupingBy(
133 a -> a.startsWith("aa") ? "aa" : "ee",
134 () -> new HashMap<String, Set<String>>()
135 , (Collector<? super String, Set<String>, Set<String>>) Collectors.<String>toSet()));
136 System.out.println(result3);
137
138 //分区,里面有一个对象 Partition,Partition 本质上是一个 Map,并且它的 Key 是 Boolean 类型,该 Map 中仅有两个元素。值是泛型 T,可以是任意类型
139 Map<Boolean, List<String>> result = list1.stream().collect(Collectors.partitioningBy(i -> i.startsWith("cc"), Collectors.toList()));
140 System.out.println(result);
141
142 //toMap,将流中每个元素按照指定规则,转为 map,但要确保流中的元素不会有重复,否则异常
143 Map<String, Integer> result4 = list1.stream().collect(Collectors.toMap(i -> i.toUpperCase(), i -> i.length()));
144 System.out.println(result4);
145
146 List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9);
147 //这个例子也演示了如何通过自定义类的方式来制作一个容器
148 IntSummaryStatistics collect2 = intList.parallelStream().collect(Collectors.summarizingInt(i -> i));
149 System.out.println(collect2);
150
151 List<String> list0 = new ArrayList<>();
152 List<String> list2 = Arrays.asList("aaSupplier21", "ccComsumer22", "ccProducer23", "ccEntry24", "aaMap25", "ccProducer26");
153 List<String> list3 = Arrays.asList("aaSupplier31", "ccComsumer32", "ccProducer33", "ccEntry34", "aaMap35", "ccProducer36");
154 list0.addAll(list1);
155 list0.addAll(list2);
156 list0.addAll(list3);
157 System.out.println("-------------");
158 Thread.currentThread().setName("ForkJoinPool.commonPool-worker-M");
159 //三个枚举值的使用
160 for(int i = 0; i < 1; i++) {
161 List<String> collect3 = list0.parallelStream().collect(new Collector<String, List<String>, List<String>>() {
162 @Override
163 public Supplier<List<String>> supplier() {
164 return () -> {
165 System.out.println("do supplier " + Thread.currentThread().getName());
166 return new ArrayList<>();
167 };
168 }
169
170 @Override
171 public BiConsumer<List<String>, String> accumulator() {
172 return (a, b) -> {
173 a.add(b);
174 //在获取并行流的情况下,如果多线程处理的是一个结果容器,这里不能遍历读取容器中的内容,否则很有可能抛出异常 ConcurrentModificationException
175 //在获取并行流的情况下,除上述情况外,不会有异常出现
176 //System.out.println("do accumulator " + Thread.currentThread().getName() + " " + a);
177 };
178 }
179
180 @Override
181 public BinaryOperator<List<String>> combiner() {
182 return (a, b) -> {
183 a.addAll(b);
184 System.out.println("do combiner " + Thread.currentThread().getName() + " " + a);
185 return a;
186 };
187 }
188
189 @Override
190 public Function<List<String>, List<String>> finisher() {
191 return a -> {
192 System.out.println("do finisher " + Thread.currentThread().getName());
193 return a;
194 };
195 }
196
197 @Override
198 public Set<Characteristics> characteristics() {
199 System.out.println("do characteristics " + Thread.currentThread().getName());
200 //在获取了并行流的前提下,当且仅当同时设置了 UNORDERED 和 CONCURRENT 时,combiner 才不会执行,这是因为多线程中,多线程操作的是同一个结果容器
201 //在获取了并行流的情况下,除上述情况外,其他情况都会执行 combiner,这是因为多线程中,每个线程处理一个结果容器,最后会将多个结果容器汇总起来
202 return Collections.unmodifiableSet(EnumSet.of(Characteristics.CONCURRENT, Characteristics.UNORDERED));
203 //return Collections.emptySet();
204 }
205 });
206 System.out.println(collect3);
207 }
208 }