1 import static java.util.Comparator.comparingInt;
2 import static java.util.stream.Collector.Characteristics.CONCURRENT;
3 import static java.util.stream.Collector.Characteristics.IDENTITY_FINISH;
4 import static java.util.stream.Collectors.collectingAndThen;
5 import static java.util.stream.Collectors.counting;
6 import static java.util.stream.Collectors.groupingBy;
7 import static java.util.stream.Collectors.mapping;
8 import static java.util.stream.Collectors.maxBy;
9 import static java.util.stream.Collectors.partitioningBy;
10 import static java.util.stream.Collectors.reducing;
11 import static java.util.stream.Collectors.summingInt;
12 import static java.util.stream.Collectors.toSet;
13 import static lambdasinaction.chap6.Dish.menu;
14
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.EnumSet;
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Optional;
22 import java.util.Set;
23 import java.util.function.BiConsumer;
24 import java.util.function.BinaryOperator;
25 import java.util.function.Function;
26 import java.util.function.Predicate;
27 import java.util.function.Supplier;
28 import java.util.stream.Collector;
29 import java.util.stream.IntStream;
30 import java.util.stream.Stream;
31
32 /**
33 * 在这里编写类的功能描述
34 *
35 * @author shangjinyu
36 * @created 2017/10/5
37 */
38 public class Notes {
39
40 /**
41 * Collectors类的静态工厂方法
42 * 工厂方法 返回类型 用于
43 * toList List<T> 把流中所有项目收集到一个List
44 * 使用示例: List<Dish> dishes = menuStream.collect(toList());
45 * toSet Set<T> 把流中所有项目收集到一个Set,删除重复项
46 * 使用示例: Set<Dish> dishes = menuStream.collect(toSet());
47 * toCollection Collection<T> 把流中所有项目收集到给定的供应源创建的集合
48 * 使用示例: Collection<Dish> dishes = menuStream.collect(toCollection(), ArrayList::new);
49 * counting Long 计算流中元素的个数
50 * 使用示例: long howManyDishes = menuStream.collect(counting());
51 * summingInt Integer 对流中项目的一个整数属性求和
52 * 使用示例: int totalCalories = menuStream.collect(summingInt(Dish::getCalories));
53 * averagingInt Double 计算流中项目Integer属性的平均值
54 * 使用示例: double avgCalories = menuStream.collect(averagingInt(Dish::getCalories));
55 * summarizingInt IntSummaryStatistics 收集关于流中项目Integer属性的统计值,例如最大,最小,总和与平均值
56 * 使用示例: IntSummaryStatistics menuStatistics = menuStream.collect(summarizingInt(Dish::getCalories));
57 * joing String 连接对流中每个项目调用toString方法所生成的字符串
58 * 使用示例: String shortMenu = menuStream.map(Dish::getName).collect(joining(", "));
59 * maxBy Optional<T> 一个包裹了流中按照给定比较器选出的最大元素的Optional,或如果流为空则为Optional.empty()
60 * 使用示例: Optional<Dish> fattest = menuStream.collect(maxBy(comparingInt(Dish::getCalories)));
61 * minBy Optional<T> 一个包裹了流中按照给定比较器选出的最小元素的Optional,或如果流为空则为Optional.empty()
62 * 使用示例: Optional<Dish> fattest = menuStream.collect(minBy(comparingInt(Dish::getCalories)));
63 * reducing 规约操作产生的类型 从一个作为累加器的初始值开始,利用BinaryOperator与流中的元素逐个结合,从而将流规约为单个值
64 * 使用示例: int totalCalories = menuStream.collect(reducing(0, Dish::getCalories, Integer::sum));
65 * collectionAndThen 转换函数返回的类型 包裹另一个收集器,对其结果应用转换函数
66 * 使用示例: int howManyDishes = menuStream.collect(collectingAndThen(toList(), List::size));
67 * groupingBy Map<K,List<T> 根据项目的一个属性的值对流中的项目分组,并将属性值作为结果Map的键
68 * 使用示例: Map<Dish.Type,List<Dish>> dishesByType = menuStream.collect(groupingBy(Dish::getType));
69 * partitioningBy Map<Boolean,List<T> 根据对流中每个项目应用谓词的结果来对项目进行分区
70 * 使用 :Map<Boolean,List<Dish>> vegetarianDishes = menuStream.collect(partitioningBy(Dish::isVegetarian));
71 */
72 //返回Colletcors接口
73 //counting(), maxBy(), summingInt(), averagingInt(), summarizingInt(), joining(), groupingBy
74
75 //reducing()
76 int totalCalories = menu.stream().collect(reducing(
77 0, Dish::getCalories, (i, j) -> i + j));
78
79 Optional<Dish> mostCalorieDish =
80 menu.stream().collect(reducing(
81 (d1, d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2));
82
83 public enum CaloricLevel {DIET, NORMAL, FAT};
84
85 Map<CaloricLevel, List<Dish>> dishesByCaloricLevel = menu.stream().collect(groupingBy(dish -> {
86 if (dish.getCalories() <= 400) return CaloricLevel.DIET;
87 else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
88 else return CaloricLevel.FAT;
89 }));
90
91 //groupingBy()
92 Map<Dish.Type, Map<CaloricLevel, List<Dish>>> dishesByTypeCaloricLevel = menu.stream().collect(
93 groupingBy(Dish::getType,
94 groupingBy(dish -> {
95 if (dish.getCalories() <= 400) return CaloricLevel.DIET;
96 else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
97 else return CaloricLevel.FAT;
98 })
99 )
100 );
101 /**
102 * {MEAT={DIET=[chicken], NORMAL=[beef], FAT=[pork]},
103 * FISH={DIET=[prawns], NORMAL=[salmon]},
104 * OTHER={DIET=[rice, seasonal fruit], NORMAL=[french fries, pizza]}}
105 */
106
107 Map<Dish.Type, Long> typesCount = menu.stream().collect(
108 groupingBy(Dish::getType, counting()));
109 //{MEAT=3, FISH=2, OTHER=4}
110 //单参数groupingBy(f) 其中f是分类函数,实际是groupingBy(f, toList())的简写法
111
112 Map<Dish.Type, Optional<Dish>> mostCaloricByType1 =
113 menu.stream()
114 .collect(groupingBy(Dish::getType,
115 maxBy(comparingInt(Dish::getCalories))));
116 //{FISH=Optional[salmon], OTHER=Optional[pizza], MEAT=Optional[pork]}
117
118 Map<Dish.Type, Dish> mostCaloricByType2 =
119 menu.stream().collect(groupingBy(Dish::getType,
120 collectingAndThen(maxBy(comparingInt(Dish::getCalories)), Optional::get)));
121 //{FISH=salmon, OTHER=pizza, MEAT=pork}
122
123 Map<Dish.Type, Integer> totalCaloriesByType =
124 menu.stream().collect(groupingBy(Dish::getType,
125 summingInt(Dish::getCalories)));
126
127 Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType =
128 menu.stream().collect(
129 groupingBy(Dish::getType, mapping(
130 dish -> {
131 if (dish.getCalories() <= 400) return CaloricLevel.DIET;
132 else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
133 else return CaloricLevel.FAT;
134 },
135 toSet()))); // toCollection(HashSet::new) )));
136 //{OTHER=[DIET, NORMAL], MEAT=[DIET, NORMAL, FAT], FISH=[DIET, NORMAL]}
137
138 //partitioningBy()
139 Map<Boolean, List<Dish>> partitionedMenu = menu.stream().collect(partitioningBy(Dish::isVegetarian));
140 /**
141 * {false=[pork, beef, chicken, prawns, salmon],
142 * true=[french fries, rice, season fruit, pizza]}
143 * <p>
144 * = List<Dish> vegetarianDishes = menu.stream().filter(Dish::isVegetarian).collect(toList());
145 */
146
147 Map<Boolean, Map<Dish.Type, List<Dish>>> vegetarianDishesByType = menu.stream().collect(
148 partitioningBy(Dish::isVegetarian, groupingBy(Dish::getType)));
149 /**
150 * {false={FISH=[prawns, salmon], MEAT=[pork, beef, chicken]},
151 * true={OTHER=[french fries, rice, season fruit, pizza]}}
152 */
153
154 Map<Boolean, Dish> mostCaloricPartitionedByVegetarian =
155 menu.stream().collect(partitioningBy(Dish::isVegetarian,
156 collectingAndThen(maxBy(comparingInt(Dish::getCalories)), Optional::get)));
157 //{false=pork, true=pizza}
158
159 //假设你要写个方法,它接受参数int n,并将前n个自数分为质数和非质数
160 public boolean isPrime(int candidate) {
161 int candidateRoot = (int) Math.sqrt((double) candidate);
162 return IntStream.rangeClosed(2, candidateRoot)
163 .noneMatch(i -> candidate % i == 0);
164 }
165
166 public Map<Boolean, List<Integer>> partitionPrimes(int n) {
167 return IntStream.rangeClosed(2, n).boxed()
168 .collect(
169 partitioningBy(candidate -> isPrime(candidate)));
170 }
171 //自定义收集器
172 public class ToListCollector<T> implements Collector<T, List<T>, List<T>> {
173 @Override
174 public Supplier<List<T>> supplier(){
175 return ArrayList::new;
176 }
177
178 @Override
179 public BiConsumer<List<T>, T> accumulator() {
180 return List::add;
181 }
182
183 @Override
184 public BinaryOperator<List<T>> combiner() {
185 return (list1, list2) -> {
186 list1.addAll(list2);
187 return list1;
188 };
189 }
190
191 @Override
192 public Function<List<T>, List<T>> finisher() {
193 return Function.identity();
194 }
195
196 @Override
197 public Set<Characteristics> characteristics() {
198 return Collections.unmodifiableSet(EnumSet.of(IDENTITY_FINISH, CONCURRENT));
199 }
200
201 }
202
203 List<Dish> dishes = menu.stream().collect(ArrayList::new, List::add, List::addAll);
204
205 }
1 public static class PrimeNumbersCollector
2 implements Collector<Integer, Map<Boolean, List<Integer>>, Map<Boolean, List<Integer>>> {
3
4 @Override
5 public Supplier<Map<Boolean, List<Integer>>> supplier() {
6 return () -> new HashMap<Boolean, List<Integer>>() {{
7 put(true, new ArrayList<Integer>());
8 put(false, new ArrayList<Integer>());
9 }};
10 }
11
12 @Override
13 public BiConsumer<Map<Boolean, List<Integer>>, Integer> accumulator() {
14 return (Map<Boolean, List<Integer>> acc, Integer candidate) -> {
15 acc.get( isPrime( acc.get(true),
16 candidate) )
17 .add(candidate);
18 };
19 }
20
21 @Override
22 public BinaryOperator<Map<Boolean, List<Integer>>> combiner() {
23 return (Map<Boolean, List<Integer>> map1, Map<Boolean, List<Integer>> map2) -> {
24 map1.get(true).addAll(map2.get(true));
25 map1.get(false).addAll(map2.get(false));
26 return map1;
27 };
28 }
29
30 @Override
31 public Function<Map<Boolean, List<Integer>>, Map<Boolean, List<Integer>>> finisher() {
32 return i -> i;
33 }
34
35 @Override
36 public Set<Characteristics> characteristics() {
37 return Collections.unmodifiableSet(EnumSet.of(IDENTITY_FINISH));
38 }
39 }
40
41 public Map<Boolean, List<Integer>> partitionPrimesWithInlineCollector(int n) {
42 return Stream.iterate(2, i -> i + 1).limit(n)
43 .collect(
44 () -> new HashMap<Boolean, List<Integer>>() {{
45 put(true, new ArrayList<Integer>());
46 put(false, new ArrayList<Integer>());
47 }},
48 (acc, candidate) -> {
49 acc.get( isPrime(acc.get(true), candidate) )
50 .add(candidate);
51 },
52 (map1, map2) -> {
53 map1.get(true).addAll(map2.get(true));
54 map1.get(false).addAll(map2.get(false));
55 });
56 }
57 public static boolean isPrime(List<Integer> primes, Integer candidate) {
58 double candidateRoot = Math.sqrt((double) candidate);
59 //return primes.stream().filter(p -> p < candidateRoot).noneMatch(p -> candidate % p == 0);
60 return takeWhile(primes, i -> i <= candidateRoot).stream().noneMatch(i -> candidate % i == 0);
61 }
62
63 public static <A> List<A> takeWhile(List<A> list, Predicate<A> p) {
64 int i = 0;
65 for (A item : list) {
66 if (!p.test(item)) {
67 return list.subList(0, i);
68 }
69 i++;
70 }
71 return list;
72 }
View Code