Stream (四)之Collectors集合類常用方法
阿新 • • 發佈:2020-12-02
Stream (四)之Collectors集合類常用方法
package com.zy.stream.collect; import com.zy.stream.model.Apple; import com.zy.stream.model.Person; import org.junit.Test; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; /** * Stream流中關於Collectors集合類中的相關方法,詳解 **/ public class StreamCollectTest { //實體類 @Data @AllArgsConstructor @NoArgsConstructor @Builder class Apple { private String color; private Integer weight; } @Data @Builder(toBuilder = true) @AllArgsConstructor @NoArgsConstructor class Person { private String firstName, lastName, job, gender; private int salary,age; } List<Person> listPerson1= new ArrayList<Person>() { { add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 2000, 18)); add(new Person("Tamsen", "Brittany", "Java programmer", "female", 2371, 55)); add(new Person("Floyd", "Donny", "Java programmer", "male", 3322, 25)); add(new Person("Sindy", "Jonie", "Java programmer", "female", 35020, 15)); add(new Person("Vere", "Hervey", "Java programmer", "male", 2272, 25)); add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 870)); add(new Person("testMaude", null, "Java programmer", "female", 2057, 870)); add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 87)); add(new Person("Shawn", "Randall", "Java programmer", "male", 3120, 99)); add(new Person("Jayden", "Corrina", "Java programmer", "female", 345, 25)); add(new Person("Palmer", "Dene", "Java programmer", "male", 3375, 14)); add(new Person("Addison", "Pam", "Java programmer", "female", 3426, 20)); } }; List<Person> listPerson2= new ArrayList<Person>() { { add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 2000, 18)); add(new Person("Tamsen", "Brittany", "Java programmer", "female", 2371, 55)); add(new Person("testFloyd", "Donny", "Java programmer", "male", 3322, 25)); add(new Person("Sindy", "Jonie", "Java programmer", "female", 35020, 15)); add(new Person("testVere", "Hervey", "Java programmer", "male", 2272, 25)); add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 87)); add(new Person("testShawn", "Randall", "Java programmer", "male", 3120, 99)); add(new Person("Jayden", "Corrina", "Java programmer", "female", 345, 25)); add(new Person("testPalmer", "Dene", "Java programmer", "male", 3375, 14)); add(new Person("Addison", "Pam", "Java programmer", "female", 3426, 20)); } }; @Test public void testAll(){ List<Integer> collect = listPerson1.stream().map(Person::getSalary).collect(Collectors.toList()); //交集 (list1 + list2) System.out.println("test=======交集[firstName中不含有test] ========>:"); listPerson1.stream() .filter(listPerson2::contains) .collect(Collectors.toList()) .forEach(System.out::println); //差集 取差集是注意以那個集合為主 System.out.println("test=======listPerson2差集[firstName中含有test] ========>:"); listPerson2.stream() .filter(e-> !listPerson1.contains(e)) .collect(Collectors.toList()) .forEach(System.out::println); //並集 System.out.println("test=======並集[兩個集合的所有元素] ========>:"); List<Person> collect1 = listPerson1.parallelStream().collect(Collectors.toList()); collect1.addAll(listPerson2.parallelStream().collect(Collectors.toList())); collect1.stream().forEach(System.out::println); System.out.println("test=======並集[兩個集合的所有元素] 去重========>:"); collect1.stream().distinct().forEach(System.out::println); HashMap<String, Integer> map = new HashMap<>(); map.put("Apple1",30); map.put("Apple2",20); map.put("Apple3",10); map.put("Apple6",51); map.put("Apple4",99); System.out.println("test=======Map集合轉 List[注意資料型別]按照key值排序========>:"); //Map集合轉 List map.entrySet().stream().sorted(Comparator.comparing(e -> e.getKey())) .map(e -> new Apple(e.getKey(), e.getValue())).collect(Collectors.toList()) .forEach(System.out::println); System.out.println("test=======Map集合轉 List[注意資料型別]按照value值排序========>:"); map.entrySet() .stream() .sorted(Comparator.comparing(Map.Entry::getValue)).map(e -> new Apple(e.getKey(), e.getValue())) .collect(Collectors.toList()) .forEach(System.out::println); System.out.println("test=======Map集合轉 List[注意資料型別]按照key值排序Entry.comparingByKey()========>:"); map.entrySet() .stream() .sorted(Map.Entry.comparingByKey()) .map(e -> new Apple(e.getKey(), e.getValue())) .collect(Collectors.toList()) .forEach(System.out::println); //toList()方法 List<Integer> collectList = Stream.of(1, 2, 3, 4) .collect(Collectors.toList()); System.out.println("test=======Collectors.toList()========》: " + collectList); HashMap<String, Object> objMap = new HashMap<>(); //List轉map集合 Collectors.toMap方法的第三個引數為鍵值重複處理策略,如果不傳入第三個引數,當有相同的鍵時,會丟擲一個IlleageStateException。 System.out.println("test=======List元素物件轉map集合[方式一]========>:"); /* toMap()引數一:key值,引數二:value值 引數三:當兩個key值相同時,決定保留前一個value值還是後一個value值 key為null 可以為null 字典查詢和資料轉換 toMap時,如果value為null,會報空指標異常,需要校驗 */ listPerson1.stream() .collect(Collectors.toMap(p -> p.getFirstName(), p -> Optional.ofNullable(p.getLastName()).orElse("value為null加非空檢驗"), (k1, k2) -> k1)) .forEach( (key, value) -> { //map集合forEach()迴圈時傳兩個引數,key,value值, System.out.println("key: " + key + " value: " + value); } ); /*下面這種形式,通過方法的引用也可以去取重複的key,保證不丟擲異常,但是隻能保證出現的第一個key的資料(Map::putAll) key為null 可以為null value為null,不會報空指標異常 */ System.out.println("test=======List元素物件轉map集合[方式二]========>:"); listPerson1.stream() .collect(HashMap::new,(maps,p)->maps.put(p.getFirstName(),p.getLastName()),Map::putAll) .forEach( (key, value) -> { //map集合forEach()迴圈時傳兩個引數,key,value值, //如果value為null 列印:key: testMaude value: null System.out.println("++key: " + key + " ++value: " + value); } ); System.out.println("test=======List元素物件轉map集合[方式三]========>:"); Stream<Apple> appleStream = Stream.of(new Apple("白色", 18), new Apple("紅色", 180), new Apple("綠色", 187), new Apple("銀色", 19)); Map<String , Apple> appleMap = appleStream.collect(Collectors.toMap(Apple::getColor, i -> i)); appleMap.forEach( (key, value) -> { System.out.println("appleKey: " + key + " appleValue: " + value); } ); System.out.println("test========假設要得到按年齡分組的Map<Integer,List>:=======>:"); Map<Integer, List<Person>> ageMap = listPerson1.stream().collect(Collectors.toMap(Person::getAge, Collections::singletonList, (a, b) -> { List<Person> resultList = new ArrayList<>(a); resultList.addAll(b); return resultList; })); ageMap.forEach( (key, value) -> { System.out.println("ageKey: " + key + " personValue: " + value); } ); //List<String> 轉String System.out.println("test========List<String> 轉String使用Collectors.joining():=======>:"); String str = Arrays.asList("voidcc.com", "voidmvn.com", "voidtool.com").stream().collect(Collectors.joining(",")); System.out.println(str); //排序 System.out.println("test=======排序sorted()========>:"); //按照自然順序進行排序 如果要自定義排序sorted 傳入自定義的 Comparator listPerson1.stream().map(Person::getAge).sorted((x,y)->x.compareTo(y)).forEach(System.out::println); //比較 System.out.println("test=======比較sorted()========>:"); Comparator<Person> comparator = (p1, p2) -> p1.getFirstName().compareTo(p2.getFirstName()); Person p1 = new Person("Addison", "Pam", "Java programmer", "female", 3426, 20); Person p2 = new Person("Addison", "Pam", "Java programmer", "female", 3426, 20); comparator.compare(p1, p2); // > 0 comparator.reversed().compare(p1, p2); // < 0 //分組 System.out.println("test=======按照薪資分組Collectors.groupingBy()=====返回map===>:"); listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary)).forEach( (key, value) -> {System.out.println("key: " + key + " value: " + value);} ); /* * groupingBy 分組後操作 //Collectors中還提供了一些對分組後的元素進行downStream處理的方法: //counting方法返回所收集元素的總數; //summing方法會對元素求和; //maxBy和minBy會接受一個比較器,求最大值,最小值; //mapping函式會應用到downstream結果上,並需要和其他函式配合使用; */ Map<Integer, Long> count = listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.counting())); count.forEach((key, value) -> {System.out.println("counting方法返回所收集元素的總數:--->key: " + key + " value: " + value);}); Map<Integer, Integer> ageCount = listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.summingInt(Person::getAge))); ageCount.forEach((key, value) -> {System.out.println("summing方法會對元素求和:--->key: " + key + " value: " + value);}); Map<Integer, Optional<Person>> ageMax = listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.maxBy(Comparator.comparing(Person::getAge)))); ageMax.forEach((key, value) -> {System.out.println("maxBy和minBy會接受一個比較器,求最大值,最小值:--->key: " + key + " value: " + value);}); Map<Integer, List<String>> nameMap = listPerson1.stream().collect(Collectors.groupingBy(Person::getSalary,Collectors.mapping(Person::getFirstName,Collectors.toList()))); nameMap.forEach((key, value) -> {System.out.println("mapping函式會應用到downstream結果上,並需要和其他函式配合使用: " + key + " value: " + value);}); /* *1. Collectors partitioningBy * Collectors中還提供了partitioningBy方法,接受一個Predicate函式,該函式返回boolean值,用於將內容分為兩組。 * *2. Collectors joining * Collectors.joining 收集Stream中的值,該方法可以方便地將Stream得到一個字串。joining函式接受三個引數,分別表示允(用以分隔元素)、字首和字尾 * * Collectors分別提供了求平均值averaging、總數couting、最小值minBy、最大值maxBy、求和suming等操作。 * 但是假如你希望將流中結果聚合為一個總和、平均值、最大值、最小值, * 那麼Collectors.summarizing(Int/Long/Double)就是為你準備的, * 它可以一次行獲取前面的所有結果,其返回值為(Int/Long/Double)SummaryStatistics。 * * * 使用collect可以將Stream轉換成值。maxBy和minBy允許使用者按照某個特定的順序生成一個值。 averagingDouble:求平均值,Stream的元素型別為double averagingInt:求平均值,Stream的元素型別為int averagingLong:求平均值,Stream的元素型別為long counting:Stream的元素個數 maxBy:在指定條件下的,Stream的最大元素 minBy:在指定條件下的,Stream的最小元素 reducing: reduce操作 summarizingDouble:統計Stream的資料(double)狀態,其中包括count,min,max,sum和平均。 summarizingInt:統計Stream的資料(int)狀態,其中包括count,min,max,sum和平均。 summarizingLong:統計Stream的資料(long)狀態,其中包括count,min,max,sum和平均。 summingDouble:求和,Stream的元素型別為double summingInt:求和,Stream的元素型別為int summingLong:求和,Stream的元素型別為long * */ } }