java兩個List的交集,並集


文章來源:https://www.cnblogs.com/qdhxhz/p/10787130.html

非對象集合交、並、差處理

方法一:使用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}]
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM