Как сравнить список объектов и их свойств, а затем обновить исходный список в Java - PullRequest
0 голосов
/ 01 марта 2019

У меня есть объект, у которого в качестве свойства есть список, например,

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.

Обратите внимание, что мы также сравниваемсписок B для A в обоих списках, поэтому, если есть совпадающие A, но есть дельта их B, мы должны быть в состоянии добавить его вexistingList A bList.

Аналогичным образом, если мы обнаружим, что элемент был удален из newList, мы должны удалить его из existingList.

Обратите внимание, что речь идет не просто о сравнении двух объектов, а скорее о нахождении дельты глубоко в графе объектов и обновлении или добавлении новых и / или существующих частей.Вот пример примера:

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("");
    }

}

Ответы [ 3 ]

0 голосов
/ 01 марта 2019

Если вы заботитесь о порядке, просто используйте метод equals:

list1.equals(list2);

Из javadoc:

Сравнивает указанный объект с этим списком на равенство.Возвращает true, если и только если указанный объект также является списком, оба списка имеют одинаковый размер, и все соответствующие пары элементов в двух списках равны.(Два элемента e1 и e2 равны, если (e1 == null? E2 == null: e1.equals (e2)).) Другими словами, два списка определяются как равные, если они содержат одинаковые элементы в одинаковом порядке.,Это определение гарантирует, что метод equals работает должным образом в разных реализациях интерфейса List.

Если вы хотите проверять независимо от порядка, вы можете скопировать все элементы в Sets и использовать equals в результирующемНаборы:

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 рассматривал бы их как равные.

Если вам нужно быть нечувствительным к порядку, но чувствительным к частоте дубликатов, вы можете:

отсортировать оба списка (или копии) перед их сравнением или скопировать все элементы в мультисеть.

0 голосов
/ 02 марта 2019

Это работает:

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);
    }

}
0 голосов
/ 01 марта 2019

Шаг 1: Реализуйте equals() и hashCode для обоих классов.

Шаг 2: Преобразуйте списки в наборы.

Шаг 3: Используйте один или несколько из Set методы addAll, removeAll и / или retainAll для выполнения операций над множествами, таких как объединение, пересечение и разность.

...