簡體   English   中英

合並Java 8中的兩個對象列表

[英]Merging two List of objects in java 8

我有一個Java類Parent有20個屬性(attrib1, attrib2 .. attrib20)及其相應的getter和setter。 我還有兩個Parent對象列表: list1list2

現在我想合並兩個列表並避免基於attrib1attrib2重復對象。

使用Java 8:

List<Parent> result = Stream.concat(list1.stream(), list2.stream())
                .distinct()
                .collect(Collectors.toList());   

但是我必須在哪個地方指定屬性? 我應該覆蓋hashCodeequals方法嗎?

如果你想實現equalshashCode ,那么它的位置就 Parent類中。 在該類中添加類似的方法

    @Override
    public int hashCode() {
        return Objects.hash(getAttrib1(), getAttrib2(), getAttrib3(),
            // …
                            getAttrib19(), getAttrib20());
    }

    @Override
    public boolean equals(Object obj) {
        if(this==obj) return true;
        if(!(obj instanceof Parent)) return false;
        Parent p=(Parent) obj;
        return Objects.equals(getAttrib1(), p.getAttrib1())
            && Objects.equals(getAttrib2(), p.getAttrib2())
            && Objects.equals(getAttrib3(), p.getAttrib3())
            // …
            && Objects.equals(getAttrib19(), p.getAttrib19())
            && Objects.equals(getAttrib20(), p.getAttrib20());
    }

如果你這樣做,在Stream<Parent>上調用distinct()將自動做正確的事情。


如果您不希望(或不能)更改類Parent ,則沒有用於相等的委派機制,但您可以使用具有委派機制的排序

Comparator<Parent> c=Comparator.comparing(Parent::getAttrib1)
        .thenComparing(Parent::getAttrib2)
        .thenComparing(Parent::getAttrib3)
        // …
        .thenComparing(Parent::getAttrib19)
        .thenComparing(Parent::getAttrib20);

這定義了基於屬性的訂單。 它要求屬性本身的類型具有可比性。 如果你有這樣的定義,你可以使用它來實現基於該Comparatordistinct()的等價物:

List<Parent> result = Stream.concat(list1.stream(), list2.stream())
        .filter(new TreeSet<>(c)::add)
        .collect(Collectors.toList());

如果您想將其與並行流一起使用,還有一個線程安全的變體:

List<Parent> result = Stream.concat(list1.stream(), list2.stream())
        .filter(new ConcurrentSkipListSet<>(c)::add)
        .collect(Collectors.toList());

例如:

public class Parent {

    public int no;
    public String name;

    @Override
    public int hashCode() {
        return (no << 4) ^ name.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Parent))
            return false;
        Parent o = (Parent)obj;
        return this.no == o.no && this.name.equals(o.name);
    }
}

覆蓋Parent類中的equalshashCode方法,以避免列表中的重復。 這將為您提供您想要的確切結果。

如果要覆蓋.equals(…).hashCode() ,則需要在Parent類上執行此操作。 請注意,這可能會導致Parent其他用途失敗。 Alexis C.的鏈接解決方案更加保守。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM