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
*
*/
}
}