Java8InAction_Chapter06

  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

 

posted @ 2017-10-23 00:55  咸_鱼  Views(254)  Comments(0Edit  收藏  举报