1. package com.zy.stream.collect;
    2. import com.zy.stream.model.Apple;
    3. import com.zy.stream.model.Person;
    4. import org.junit.Test;
    5. import java.util.*;
    6. import java.util.stream.Collectors;
    7. import java.util.stream.Stream;
    8. /**
    9. * Stream流中关于Collectors集合类中的相关方法,详解
    10. **/
    11. public class StreamCollectTest {
    12. //实体类
    13. @Data
    14. @AllArgsConstructor
    15. @NoArgsConstructor
    16. @Builder
    17. class Apple {
    18. private String color;
    19. private Integer weight;
    20. }
    21. @Data
    22. @Builder(toBuilder = true)
    23. @AllArgsConstructor
    24. @NoArgsConstructor
    25. class Person {
    26. private String firstName, lastName, job, gender;
    27. private int salary,age;
    28. }
    29. List<Person> listPerson1= new ArrayList<Person>() {
    30. {
    31. add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 2000, 18));
    32. add(new Person("Tamsen", "Brittany", "Java programmer", "female", 2371, 55));
    33. add(new Person("Floyd", "Donny", "Java programmer", "male", 3322, 25));
    34. add(new Person("Sindy", "Jonie", "Java programmer", "female", 35020, 15));
    35. add(new Person("Vere", "Hervey", "Java programmer", "male", 2272, 25));
    36. add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 870));
    37. add(new Person("testMaude", null, "Java programmer", "female", 2057, 870));
    38. add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 87));
    39. add(new Person("Shawn", "Randall", "Java programmer", "male", 3120, 99));
    40. add(new Person("Jayden", "Corrina", "Java programmer", "female", 345, 25));
    41. add(new Person("Palmer", "Dene", "Java programmer", "male", 3375, 14));
    42. add(new Person("Addison", "Pam", "Java programmer", "female", 3426, 20));
    43. }
    44. };
    45. List<Person> listPerson2= new ArrayList<Person>() {
    46. {
    47. add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 2000, 18));
    48. add(new Person("Tamsen", "Brittany", "Java programmer", "female", 2371, 55));
    49. add(new Person("testFloyd", "Donny", "Java programmer", "male", 3322, 25));
    50. add(new Person("Sindy", "Jonie", "Java programmer", "female", 35020, 15));
    51. add(new Person("testVere", "Hervey", "Java programmer", "male", 2272, 25));
    52. add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 87));
    53. add(new Person("testShawn", "Randall", "Java programmer", "male", 3120, 99));
    54. add(new Person("Jayden", "Corrina", "Java programmer", "female", 345, 25));
    55. add(new Person("testPalmer", "Dene", "Java programmer", "male", 3375, 14));
    56. add(new Person("Addison", "Pam", "Java programmer", "female", 3426, 20));
    57. }
    58. };
    59. @Test
    60. public void testAll(){
    61. List<Integer> collect = listPerson1.stream().map(Person::getSalary).collect(Collectors.toList());
    62. //交集 (list1 + list2)
    63. System.out.println("test=======交集[firstName中不含有test] ========>:");
    64. listPerson1.stream()
    65. .filter(listPerson2::contains)
    66. .collect(Collectors.toList())
    67. .forEach(System.out::println);
    68. //差集 取差集是注意以那个集合为主
    69. System.out.println("test=======listPerson2差集[firstName中含有test] ========>:");
    70. listPerson2.stream()
    71. .filter(e-> !listPerson1.contains(e))
    72. .collect(Collectors.toList())
    73. .forEach(System.out::println);
    74. //并集
    75. System.out.println("test=======并集[两个集合的所有元素] ========>:");
    76. List<Person> collect1 = listPerson1.parallelStream().collect(Collectors.toList());
    77. collect1.addAll(listPerson2.parallelStream().collect(Collectors.toList()));
    78. collect1.stream().forEach(System.out::println);
    79. System.out.println("test=======并集[两个集合的所有元素] 去重========>:");
    80. collect1.stream().distinct().forEach(System.out::println);
    81. HashMap<String, Integer> map = new HashMap<>();
    82. map.put("Apple1",30);
    83. map.put("Apple2",20);
    84. map.put("Apple3",10);
    85. map.put("Apple6",51);
    86. map.put("Apple4",99);
    87. System.out.println("test=======Map集合转 List[注意数据类型]按照key值排序========>:");
    88. //Map集合转 List
    89. map.entrySet().stream().sorted(Comparator.comparing(e -> e.getKey()))
    90. .map(e -> new Apple(e.getKey(), e.getValue())).collect(Collectors.toList())
    91. .forEach(System.out::println);
    92. System.out.println("test=======Map集合转 List[注意数据类型]按照value值排序========>:");
    93. map.entrySet()
    94. .stream()
    95. .sorted(Comparator.comparing(Map.Entry::getValue)).map(e -> new Apple(e.getKey(), e.getValue()))
    96. .collect(Collectors.toList())
    97. .forEach(System.out::println);
    98. System.out.println("test=======Map集合转 List[注意数据类型]按照key值排序Entry.comparingByKey()========>:");
    99. map.entrySet()
    100. .stream()
    101. .sorted(Map.Entry.comparingByKey())
    102. .map(e -> new Apple(e.getKey(), e.getValue()))
    103. .collect(Collectors.toList())
    104. .forEach(System.out::println);
    105. //toList()方法
    106. List<Integer> collectList = Stream.of(1, 2, 3, 4)
    107. .collect(Collectors.toList());
    108. System.out.println("test=======Collectors.toList()========》: " + collectList);
    109. HashMap<String, Object> objMap = new HashMap<>();
    110. //List转map集合 Collectors.toMap方法的第三个参数为键值重复处理策略,如果不传入第三个参数,当有相同的键时,会抛出一个IlleageStateException。
    111. System.out.println("test=======List元素对象转map集合[方式一]========>:");
    112. /* toMap()参数一:key值,参数二:value值 参数三:当两个key值相同时,决定保留前一个value值还是后一个value值
    113. key为null 可以为null
    114. 字典查询和数据转换 toMap时,如果value为null,会报空指针异常,需要校验
    115. */
    116. listPerson1.stream()
    117. .collect(Collectors.toMap(p -> p.getFirstName(), p -> Optional.ofNullable(p.getLastName()).orElse("value为null加非空检验"), (k1, k2) -> k1))
    118. .forEach(
    119. (key, value) -> {
    120. //map集合forEach()循环时传两个参数,key,value值,
    121. System.out.println("key: " + key + " value: " + value);
    122. }
    123. );
    124. /*下面这种形式,通过方法的引用也可以去取重复的key,保证不抛出异常,但是只能保证出现的第一个key的数据(Map::putAll)
    125. key为null 可以为null
    126. value为null,不会报空指针异常
    127. */
    128. System.out.println("test=======List元素对象转map集合[方式二]========>:");
    129. listPerson1.stream()
    130. .collect(HashMap::new,(maps,p)->maps.put(p.getFirstName(),p.getLastName()),Map::putAll)
    131. .forEach(
    132. (key, value) -> {
    133. //map集合forEach()循环时传两个参数,key,value值,
    134. //如果value为null 打印:key: testMaude value: null
    135. System.out.println("++key: " + key + " ++value: " + value);
    136. }
    137. );
    138. System.out.println("test=======List元素对象转map集合[方式三]========>:");
    139. Stream<Apple> appleStream = Stream.of(new Apple("白色", 18),
    140. new Apple("红色", 180),
    141. new Apple("绿色", 187),
    142. new Apple("银色", 19));
    143. Map<String , Apple> appleMap = appleStream.collect(Collectors.toMap(Apple::getColor, i -> i));
    144. appleMap.forEach(
    145. (key, value) -> {
    146. System.out.println("appleKey: " + key + " appleValue: " + value);
    147. }
    148. );
    149. System.out.println("test========假设要得到按年龄分组的Map<Integer,List>:=======>:");
    150. Map<Integer, List<Person>> ageMap = listPerson1.stream().collect(Collectors.toMap(Person::getAge, Collections::singletonList, (a, b) -> {
    151. List<Person> resultList = new ArrayList<>(a);
    152. resultList.addAll(b);
    153. return resultList;
    154. }));
    155. ageMap.forEach(
    156. (key, value) -> {
    157. System.out.println("ageKey: " + key + " personValue: " + value);
    158. }
    159. );
    160. //List<String> 转String
    161. System.out.println("test========List<String> 转String使用Collectors.joining():=======>:");
    162. String str = Arrays.asList("voidcc.com", "voidmvn.com", "voidtool.com").stream().collect(Collectors.joining(","));
    163. System.out.println(str);
    164. //排序
    165. System.out.println("test=======排序sorted()========>:");
    166. //按照自然顺序进行排序 如果要自定义排序sorted 传入自定义的 Comparator
    167. listPerson1.stream().map(Person::getAge).sorted((x,y)->x.compareTo(y)).forEach(System.out::println);
    168. //比较
    169. System.out.println("test=======比较sorted()========>:");
    170. Comparator<Person> comparator = (p1, p2) -> p1.getFirstName().compareTo(p2.getFirstName());
    171. Person p1 = new Person("Addison", "Pam", "Java programmer", "female", 3426, 20);
    172. Person p2 = new Person("Addison", "Pam", "Java programmer", "female", 3426, 20);
    173. comparator.compare(p1, p2); // > 0
    174. comparator.reversed().compare(p1, p2); // < 0
    175. //分组
    176. System.out.println("test=======按照薪资分组Collectors.groupingBy()=====返回map===>:");
    177. listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary)).forEach(
    178. (key, value) -> {System.out.println("key: " + key + " value: " + value);}
    179. );
    180. /*
    181. * groupingBy 分组后操作
    182. //Collectors中还提供了一些对分组后的元素进行downStream处理的方法:
    183. //counting方法返回所收集元素的总数;
    184. //summing方法会对元素求和;
    185. //maxBy和minBy会接受一个比较器,求最大值,最小值;
    186. //mapping函数会应用到downstream结果上,并需要和其他函数配合使用;
    187. */
    188. Map<Integer, Long> count = listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.counting()));
    189. count.forEach((key, value) -> {System.out.println("counting方法返回所收集元素的总数:--->key: " + key + " value: " + value);});
    190. Map<Integer, Integer> ageCount = listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.summingInt(Person::getAge)));
    191. ageCount.forEach((key, value) -> {System.out.println("summing方法会对元素求和:--->key: " + key + " value: " + value);});
    192. Map<Integer, Optional<Person>> ageMax = listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.maxBy(Comparator.comparing(Person::getAge))));
    193. ageMax.forEach((key, value) -> {System.out.println("maxBy和minBy会接受一个比较器,求最大值,最小值:--->key: " + key + " value: " + value);});
    194. Map<Integer, List<String>> nameMap = listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.mapping(Person::getFirstName,Collectors.toList())));
    195. nameMap.forEach((key, value) -> {System.out.println("mapping函数会应用到downstream结果上,并需要和其他函数配合使用: " + key + " value: " + value);});
    196. /*
    197. *1. Collectors partitioningBy
    198. * Collectors中还提供了partitioningBy方法,接受一个Predicate函数,该函数返回boolean值,用于将内容分为两组。
    199. *
    200. *2. Collectors joining
    201. * Collectors.joining 收集Stream中的值,该方法可以方便地将Stream得到一个字符串。joining函数接受三个参数,分别表示允(用以分隔元素)、前缀和后缀
    202. *
    203. * Collectors分别提供了求平均值averaging、总数couting、最小值minBy、最大值maxBy、求和suming等操作。
    204. * 但是假如你希望将流中结果聚合为一个总和、平均值、最大值、最小值,
    205. * 那么Collectors.summarizing(Int/Long/Double)就是为你准备的,
    206. * 它可以一次行获取前面的所有结果,其返回值为(Int/Long/Double)SummaryStatistics。
    207. *
    208. *
    209. * 使用collect可以将Stream转换成值。maxBy和minBy允许用户按照某个特定的顺序生成一个值。
    210. averagingDouble:求平均值,Stream的元素类型为double
    211. averagingInt:求平均值,Stream的元素类型为int
    212. averagingLong:求平均值,Stream的元素类型为long
    213. counting:Stream的元素个数
    214. maxBy:在指定条件下的,Stream的最大元素
    215. minBy:在指定条件下的,Stream的最小元素
    216. reducing: reduce操作
    217. summarizingDouble:统计Stream的数据(double)状态,其中包括count,min,max,sum和平均。
    218. summarizingInt:统计Stream的数据(int)状态,其中包括count,min,max,sum和平均。
    219. summarizingLong:统计Stream的数据(long)状态,其中包括count,min,max,sum和平均。
    220. summingDouble:求和,Stream的元素类型为double
    221. summingInt:求和,Stream的元素类型为int
    222. summingLong:求和,Stream的元素类型为long
    223. *
    224. */
    225. }
    226. }