java两个List的交集,并集方式
java两个List的交集,并集
方法一
- 使用apache的CollectionUtils工具类(推荐)
public static void main(String[] args) {
String[] arrayA = new String[] { "1", "2", "3", "4"};
String[] arrayB = new String[] { "3", "4", "5", "6" };
List<String> listA = Arrays.asList(arrayA);
List<String> listB = Arrays.asList(arrayB);
//1、并集 union
System.out.println(CollectionUtils.union(listA, listB));
//输出: [1, 2, 3, 4, 5, 6]
//2、交集 intersection
System.out.println(CollectionUtils.intersection(listA, listB));
//输出:[3, 4]
//3、交集的补集(析取)disjunction
System.out.println(CollectionUtils.disjunction(listA, listB));
//输出:[1, 2, 5, 6]
//4、差集(扣除)
System.out.println(CollectionUtils.subtract(listA, listB));
//输出:[1, 2]
}方法二
- List自带方法
public static void main(String[] args) {
String[] arrayA = new String[] { "1", "2", "3", "4"};
String[] arrayB = new String[] { "3", "4", "5", "6" };
List<String> listA = Arrays.asList(arrayA);
List<String> listB = Arrays.asList(arrayB);
//1、交集
List<String> jiaoList = new ArrayList<>(listA);
jiaoList.retainAll(listB);
System.out.println(jiaoList);
//输出:[3, 4]
//2、差集
List<String> chaList = new ArrayList<>(listA);
chaList.removeAll(listB);
System.out.println(chaList);
//输出:[1, 2]
//3、并集 (先做差集再做添加所有)
List<String> bingList = new ArrayList<>(listA);
bingList.removeAll(listB); // bingList为 [1, 2]
bingList.addAll(listB); //添加[3,4,5,6]
System.out.println(bingList);
//输出:[1, 2, 3, 4, 5, 6]
}注意 : intersection和retainAll的差别
要注意的是它们的返回类型是不一样的,intersection返回的是一个新的List集合,而retainAll返回是Bollean类型那就说明retainAll方法是对原有集合进行处理再返回原有集合,会改变原有集合中的内容。
个人观点:
1、从性能角度来考虑的话,List自带会高点,因为它不用再创建新的集合。
2、需要注意的是:因为retainAll因为会改变原有集合,所以该集合需要多次使用就不适合用retainAll。
注意:
Arrays.asList将数组转集合不能进行add和remove操作。
原因:
调用Arrays.asList()生产的List的add、remove方法时报异常,这是由Arrays.asList() 返回的市Arrays的内部类ArrayList, 而不是java.util.ArrayList。
Arrays的内部类ArrayList和java.util.ArrayList都是继承AbstractList,remove、add等方法AbstractList中是默认throw UnsupportedOperationException而且不作任何操作。
java.util.ArrayList重新了这些方法而Arrays的内部类ArrayList没有重新,所以会抛出异常。
- 所以正确做法如下
String[] array = {"1","2","3","4","5"};
List<String> list = Arrays.asList(array);
List arrList = new ArrayList(list);
arrList.add("6");方法三
JDK1.8 stream 新特性
String[] arrayA = new String[] { "1", "2", "3", "4"};
String[] arrayB = new String[] { "3", "4", "5", "6" };
List<String> listA = Arrays.asList(arrayA);
List<String> listB = Arrays.asList(arrayB);
// 交集
List<String> intersection = listA.stream().filter(item -> listB.contains(item)).collect(toList());
System.out.println(intersection);
//输出:[3, 4]
// 差集 (list1 - list2)
List<String> reduceList = listA.stream().filter(item -> !listB.contains(item)).collect(toList());
System.out.println(reduceList);
//输出:[1, 2]
// 并集 (新建集合:1、是因为不影响原始集合。2、Arrays.asList不能add和remove操作。
List<String> listAll = listA.parallelStream().collect(toList());
List<String> listAll2 = listB.parallelStream().collect(toList());
listAll.addAll(listAll2);
System.out.println(listAll);
//输出:[1, 2, 3, 4, 3, 4, 5, 6]
// 去重并集
List<String> list =new ArrayList<>(listA);
list.addAll(listB);
List<String> listAllDistinct = list.stream().distinct().collect(toList());
System.out.println(listAllDistinct);
//输出:[1, 2, 3, 4, 5, 6]总结 : 这三种推荐第一种方式,因为第二种还需要确定该集合是否被多次调用。第三种可读性不高。
对象集合交、并、差处理
因为对象的equels比较是比较两个对象的内存地址,所以除非是同一对象,否则equel返回永远是false。
但我们实际开发中 在我们的业务系统中判断对象时有时候需要的不是一种严格意义上的相等,而是一种业务上的对象相等。在这种情况下,原生的equals方法就不能满足我们的需求了,所以这个时候我们需要重写equals方法。
说明 :String为什么可以使用equels方法为什么只要字符串相等就为true,那是因为String类重写了equal和hashCode方法,比较的是值。
public class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
/**
* 为什么重写equals方法一定要重写hashCode方法下面也会讲
*/
@Override
public int hashCode() {
String result = name + age;
return result.hashCode();
}
/**
* 重写 equals 方法 根据name和age都相同那么对象就默认相同
*/
@Override
public boolean equals(Object obj) {
Person u = (Person) obj;
return this.getName().equals(u.getName()) && (this.age.equals(u.getAge()));
}
/**
* 重写 toString 方法
*/
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}这里根据name和age都相同那么就默认相同对象。
public static void main(String[] args) {
List<Person> personList = Lists.newArrayList();
Person person1 = new Person("小小",3);
Person person2 = new Person("中中",4);
personList.add(person1);
personList.add(person2);
List<Person> person1List = Lists.newArrayList();
Person person3 = new Person("中中",4);
Person person4 = new Person("大大",5);
person1List.add(person3);
person1List.add(person4);
/**
* 1、差集
*/
System.out.println(CollectionUtils.subtract(personList, person1List));
//输出:[Person{name='小小', age=3}]
/**
* 2、并集
*/
System.out.println(CollectionUtils.union(personList, person1List));
//输出:[Person{name='小小', age=3}, Person{name='中中', age=4}, Person{name='大大', age=5}]
/**
* 3、交集
*/
System.out.println(CollectionUtils.intersection(personList, person1List));
//输出:[Person{name='中中', age=4}]
/**
* 4、交集的补集(析取)
*/
System.out.println(CollectionUtils.disjunction(personList, person1List));
//输出:[Person{name='小小', age=3}, Person{name='大大', age=5}]
}总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
SpringBoot中@Autowired与@Resource的区别小结
本文主要介绍了SpringBoot中@Autowired与@Resource的区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2025-01-01
Spring Boot 利用WebUploader进行文件上传功能
本文的重点是给大家介绍在Spring Boot项目中利用WebUploader如何进行文件上传,本文通过示例代码给大家介绍,需要的朋友参考下吧2018-03-03
基于bufferedreader的read()与readline()读取出错原因及解决
这篇文章主要介绍了bufferedreader的read()与readline()读取出错原因及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-12-12
Java Hutool工具包中HttpUtil的日志统一打印及统一超时时间配置
Hutool是一个Java基础工具类,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类,这篇文章主要给大家介绍了关于Java Hutool工具包中HttpUtil的日志统一打印及统一超时时间配置的相关资料,需要的朋友可以参考下2024-01-01
SpringBoot实现邮件发送的完整解决方案(附件发送、内嵌图片与中文乱码处理)
本文基于 Spring Boot 2.x + JDK 1.8 + Jakarta Mail 1.6.2,提供生产环境可用的完整邮件发送解决方案,涵盖附件发送、内嵌图片、中文乱码处理等核心场景,需要的朋友可以参考下2026-02-02


最新评论