java 8 流(Stream)操作两个集合求并集,交集,补集
一、基础的数据类型 如 String 两个集合 1 2 3 4 5 6 7 8 9 10 11 12 List<String> A = new ArrayList<>(); A.add("1"); A.add("2"); A.add("3"); A.add("4"); List<String> B = new ArrayList<>(); B.add("3"); B.add("4"); B.add("5"); B.add("6"); B.add("7");
1. 求并集 1 2 3 4 A.addAll(B); List<String> AuB = A.stream().distinct().collect(Collectors.toList()); System.out.println("并集:" + AuB);
输出结果:
并集:[1, 2, 3, 4, 5, 6, 7]
2. 求交集 1 2 3 List<String> AnB = A.stream().filter(B::contains).collect(Collectors.toList()); System.out.println("交集:" + AnB);
注:B::contains = s -> B.contains(s) 高版本IDEA会提示转换
输出结果
交集:[3, 4]
3. 求差集 1 2 3 List<String> difference = A.stream().filter(s -> !B.contains(s)).collect(Collectors.toList()); System.out.println("A中B的补集:" + difference);
注:差集:A - B;学名就叫做 A中B的补集
输出结果
A 中 B 的补集:[1, 2]
二、自定义的类型(以单条属性为标准) 求交集并集是以 username 为标准
1 2 3 4 5 6 7 8 9 10 import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class UserInfo { private String username; private Integer age; }
两个集合 1 2 3 4 5 6 7 8 List<UserInfo> A = new ArrayList<>(); A.add(new UserInfo("赵", 1)); A.add(new UserInfo("杜", 2)); List<UserInfo> B = new ArrayList<>(); B.add(new UserInfo("杜", 2)); B.add(new UserInfo("周", 3));
1. 求并集 1 2 3 4 5 6 7 8 9 10 11 12 13 // 求并集 A.addAll(B); // 获取两集合相加并根据username去重后的集合,并按照number进行排序 List<UserInfo> AuB = A.stream().collect(Collectors.collectingAndThen( Collectors.toCollection( () -> new TreeSet<>( Comparator.comparing(UserInfo::getUsername) ) ), ArrayList::new )).stream().sorted(Comparator.comparing(UserInfo::getNumber)).collect(Collectors.toList()); System.out.println("并集:"); AuB.forEach(System.out::println);
输出结果:
并集: UserInfo(username = 赵, number=1) UserInfo(username = 杜, number=2) UserInfo(username = 周, number=3)
2. 求交集 1 2 3 4 5 6 7 // 求交集 List<UserInfo> AnB = A.stream().filter(userInfo -> B.stream().map(UserInfo::getUsername).collect(Collectors.toList()).contains(userInfo.getUsername()) ).collect(Collectors.toList()); System.out.println("交集:"); AnB.forEach(System.out::println);
输出结果
交集: UserInfo(username = 杜, number=2)
3. 求差集 1 2 3 4 5 6 7 // 求差集 List<UserInfo> difference = A.stream().filter(userInfo -> !B.stream().map(UserInfo::getUsername).collect(Collectors.toList()).contains(userInfo.getUsername()) ).collect(Collectors.toList()); System.out.println("A中B的补集:"); difference.forEach(System.out::println);
注:差集:A - B;学名就叫做 A中B的补集
输出结果
A 中 B 的补集: UserInfo(username = 赵, number=1)
二、自定义的类型(以多条属性为标准) 求差集 1 2 3 4 5 6 7 8 9 10 11 12 // 大集合 List<PmRuleConfigParams> prpallParams = new ArrayList<>(); // 小集合 List<PmRuleConfigParams> pmParams = new ArrayList<>(); // 求差集 List<PmRuleConfigParams> dif = prpallParams.stream.filter( //把集合转成以ruleCode-paramCode为key的map ruleParams -> !pmParams.stream().collect(Collectors.toMap(params -> params.getRuleCode() + "-" + params.getParamCode(), value -> value)) //判断该key是否存在 .containsKey(ruleParams.getRuleCode() + "-" + ruleParams.getParamCode()) ).collect(Collectors.toList())
单属性的原理是把一个集合转化成一个完全由该属性组成的 List,从而判断该属性是否存在,多条属性则是转成一个 map,标准属性作为 key,判断 key 存不存在