如何比较对象列表及其属性,然后在 Java 中更新原始列表

How to Compare a List of Objects and Their Properties, then Update the Original List in Java

我有一个对象,它有一个列表作为其 属性,例如

public class A {
  private String aName;
  private List<B> bList;
}

public class B {
  private String bName;
}

假设我们有两个 A 的列表:

List<A> existingList = new ArrayList<A>();
// populate it with a list of A's which in turn, each has its own list of B's

List<A> newList = new ArrayList<A>();
// populate it with possibly some new A's and/or, an existing A which its property B has new items

考虑到这一点,我想知道比较这两个 A 列表并将这两个列表的增量添加到 existingList 的最快方法。

请注意,我们还在比较两个列表中 BA 的列表,因此如果有匹配的 A,但是有他们 B 的增量,我们应该能够将其添加到 existingListAbList.

同样,如果我们检测到某个项目已从 newList 中删除,我们应该将其从 existingList 中删除。

请注意,这不仅仅是比较两个对象,而是在对象图中找到增量并更新或添加新的 and/or 现有部分。这是示例:

package collection.delta.model;

import java.util.List;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;

package collection.delta.model;

import java.util.List;
import java.util.Objects;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

public class A {
    private String aName;

    private List<B> bList;

    public String getaName() {
        return aName;
    }

    public void setaName(String aName) {
        this.aName = aName;
    }

    public List<B> getbList() {
        return bList;
    }

    public void setbList(List<B> bList) {
        this.bList = bList;
    }

    public A(String name, List<B> bList) {
        this.aName = name;
        this.bList = bList;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null) {
            return false;
        }

        if (o == this) {
            return true;
        }

        if (!(o instanceof A)) {
            return false;
        }

        A b = (A) o;
        return StringUtils.isNotBlank(aName) && StringUtils.equalsAnyIgnoreCase(b.getaName(), aName)
                && CollectionUtils.disjunction(this.getbList(), b.getbList()).isEmpty();
    }

    @Override
    public int hashCode() {
        if (StringUtils.isBlank(aName)) {
            return 31;
        }

        return Objects.hashCode(aName);
    }   

package collection.delta.model;

import java.util.Objects;

import org.apache.commons.lang3.StringUtils;

public class B {
    private String bName;

    public String getbName() {
        return bName;
    }

    public void setbName(String bName) {
        this.bName = bName;
    }

    public B(String name) {
        this.bName = name;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null) {
            return false;
        }

        if (o == this) {
            return true;
        }

        if (!(o instanceof B)) {
            return false;
        }

        B b = (B) o;
        return StringUtils.isNotBlank(bName) && StringUtils.equalsAnyIgnoreCase(b.getbName(), bName);
    }

    @Override
    public int hashCode() {
        if (StringUtils.isBlank(bName)) {
            return 31;
        }

        return Objects.hashCode(bName);
    }
}

package collection.delta;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import collection.delta.model.A;
import collection.delta.model.B;

public class App {
    public static void main( String[] args ) {

        List<A> originalA = new ArrayList<A>();
        List<A> newA = new ArrayList<A>();

        List<B> bListOriginalA1 = new ArrayList<B>();
        bListOriginalA1.add(new B("originalA1_B1"));
        bListOriginalA1.add(new B("originalA1_B2"));
        bListOriginalA1.add(new B("originalA1_B3"));
        bListOriginalA1.add(new B("originalA1_B4"));

        A originalA1 = new A("originalA1", bListOriginalA1);

        List<B> bListOriginalA2 = new ArrayList<B>();
        bListOriginalA2.add(new B("originalA2_B1"));
        bListOriginalA2.add(new B("originalA2_B2"));
        bListOriginalA2.add(new B("originalA2_B3"));
        bListOriginalA2.add(new B("originalA2_B4"));

        A originalA2 = new A("originalA2", bListOriginalA2);

        List<B> bListOriginalA3 = new ArrayList<B>();
        bListOriginalA3.add(new B("originalA3_B1"));
        bListOriginalA3.add(new B("originalA3_B2"));
        bListOriginalA3.add(new B("originalA3_B3"));
        bListOriginalA3.add(new B("originalA3_B4"));

        A originalA3 = new A("originalA3", bListOriginalA3);

        originalA.add(originalA1);
        originalA.add(originalA2);
        originalA.add(originalA3);


        List<B> bListNewA1 = new ArrayList<B>();
        bListNewA1.add(new B("originalA1_B1"));
        bListNewA1.add(new B("originalA1_B2"));
        bListNewA1.add(new B("originalA1_B3"));
        bListNewA1.add(new B("originalA1_B4"));

        A newA1 = new A("originalA1", bListNewA1);

        List<B> bListNewA2 = new ArrayList<B>();
        bListNewA2.add(new B("originalA2_B1"));
        bListNewA2.add(new B("originalA2_B2"));
        bListNewA2.add(new B("originalA2_B3"));
        bListNewA2.add(new B("originalA2_B4"));

        A newA2 = new A("originalA2", bListNewA2);

        List<B> bListNewA3 = new ArrayList<B>();
        bListNewA3.add(new B("originalA3_B1"));
        bListNewA3.add(new B("originalA3_B2"));
        bListNewA3.add(new B("originalA3_B5"));
        bListNewA3.add(new B("originalA3_B4"));

        A newA3 = new A("originalA3", bListNewA3);

        List<B> bListNewA4 = new ArrayList<B>();
        bListNewA4.add(new B("A4_B1"));
        bListNewA4.add(new B("A4_B2"));
        bListNewA4.add(new B("A4_B3"));
        bListNewA4.add(new B("A4_B4"));

        A newA4 = new A("originalA4", bListNewA4);

        newA.add(newA1);
        newA.add(newA2);
        newA.add(newA3);
        newA.add(newA4);

        List<A> result = CollectionUtils.disjunction(originalA, newA).stream().collect(Collectors.toList());
        for (A a : newA) {
            for (A aResult : result) {
                if (StringUtils.equalsAnyIgnoreCase(a.getaName(), aResult.getaName())) {
                    originalA.add(aResult);
                }
            }
        }

        System.out.println("");
    }

}

第 1 步:为 类.

实施 equals()hashCode

第 2 步:将列表转换为集合。

第 3 步:使用一种或多种 Set 方法 addAllremoveAll、and/or retainAll 来练习集合操作,例如联合、交集,差异。

如果你关心顺序,那么就用equals方法:

list1.equals(list2);

来自 javadoc:

Compares the specified object with this list for equality. Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).) In other words, two lists are defined to be equal if they contain the same elements in the same order. This definition ensures that the equals method works properly across different implementations of the List interface.

如果您想独立于顺序进行检查,您可以将所有元素复制到集合中,并对结果集合使用等于:

public static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
    return new HashSet<>(list1).equals(new HashSet<>(list2));
}

这种方法的局限性在于它不仅忽略了顺序,而且忽略了重复元素的频率。例如,如果 list1 是 ["A"、"B"、"A"] 并且 list2 是 ["A"、"B"、"B"] Set 方法会认为它们是相等的。

如果您需要对顺序不敏感但对重复频率敏感,您可以:

在比较之前对两个列表(或副本)进行排序 或将所有元素复制到 Multiset。

这个有效:

package collection.delta;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import collection.delta.model.A;
import collection.delta.model.B;

public class App {
    public static void main( String[] args ) {

        List<A> originalA = new ArrayList<A>();
        List<A> newA = new ArrayList<A>();

        List<B> bListOriginalA1 = new ArrayList<B>();
        bListOriginalA1.add(new B("originalA1_B1"));
        bListOriginalA1.add(new B("originalA1_B2"));
        bListOriginalA1.add(new B("originalA1_B3"));
        bListOriginalA1.add(new B("originalA1_B4"));

        A originalA1 = new A("originalA1", bListOriginalA1);

        List<B> bListOriginalA2 = new ArrayList<B>();
        bListOriginalA2.add(new B("originalA2_B1"));
        bListOriginalA2.add(new B("originalA2_B2"));
        bListOriginalA2.add(new B("originalA2_B3"));
        bListOriginalA2.add(new B("originalA2_B4"));

        A originalA2 = new A("originalA2", bListOriginalA2);

        List<B> bListOriginalA3 = new ArrayList<B>();
        bListOriginalA3.add(new B("originalA3_B1"));
        bListOriginalA3.add(new B("originalA3_B2"));
        bListOriginalA3.add(new B("originalA3_B3"));
        bListOriginalA3.add(new B("originalA3_B4"));

        A originalA3 = new A("originalA3", bListOriginalA3);

        originalA.add(originalA1);
        originalA.add(originalA2);
        originalA.add(originalA3);


        List<B> bListNewA1 = new ArrayList<B>();
        bListNewA1.add(new B("originalA1_B1"));
        bListNewA1.add(new B("originalA1_B2"));
        bListNewA1.add(new B("originalA1_B3"));
        bListNewA1.add(new B("originalA1_B4"));

        A newA1 = new A("originalA1", bListNewA1);

        List<B> bListNewA2 = new ArrayList<B>();
        bListNewA2.add(new B("originalA2_B1"));
        bListNewA2.add(new B("originalA2_B3"));
        bListNewA2.add(new B("originalA2_B4"));
        bListNewA2.add(new B("originalA2_B2"));

        A newA2 = new A("originalA2", bListNewA2);

        List<B> bListNewA3 = new ArrayList<B>();
        bListNewA3.add(new B("originalA3_B1"));
        bListNewA3.add(new B("originalA3_B2"));
        bListNewA3.add(new B("originalA3_B5"));
        bListNewA3.add(new B("originalA3_B4"));

        A newA3 = new A("originalA3", bListNewA3);

        List<B> bListNewA4 = new ArrayList<B>();
        bListNewA4.add(new B("A4_B1"));
        bListNewA4.add(new B("A4_B2"));
        bListNewA4.add(new B("A4_B3"));
        bListNewA4.add(new B("A4_B4"));

        A newA4 = new A("originalA4", bListNewA4);

        newA.add(newA1);
        newA.add(newA2);
        newA.add(newA3);
        newA.add(newA4);

        List<A> result = newA.stream()
                .filter(not(new HashSet<A>(originalA)::contains))
                .collect(Collectors.toList());

        A tempA = null;
        B tempB = null;
        List<B> bList = null;
        for (A a : result) {
            if (!containsName(originalA, a.getaName())) {
                originalA.add(a);
            } else {
                tempA = getAIfPresent(originalA, a.getaName());

                if (tempA != null) {

                    bList = a.getbList().stream()
                            .filter(not(new HashSet<B>(tempA.getbList())::contains))
                            .collect(Collectors.toList());

                    if (bList != null) {
                        tempA.getbList().addAll(bList);
                    }
                }
            }
        }

        System.out.println("");
    }

    public static <T> Predicate<T> not(Predicate<T> predicate) {
        return predicate.negate();
    }

    public static boolean containsName(final List<A> list, final String name){
        return list.stream().map(A::getaName).filter(name::equals).findFirst().isPresent();
    }

    public static A getAIfPresent(final List<A> list, final String name) {
        return list.stream().filter(x -> x.getaName().equalsIgnoreCase(name)).findFirst().orElse(null);
    }

}