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

У меня есть два объекта DTO, такие как следующие, пожалуйста, обратите внимание, что я использую lombok, чтобы избежать шаблонного кода.

DtoA

import lombok.Data;
import java.util.List;

@Data
public class DtoA {

    private String name;
    private String number;
    private List<String> aList;
}

DtoB

import lombok.Data;
import java.util.List;

@Data
public class DtoB {
    private String name;
    private String phone;
    private List<String> bList;
}

Я хочу сравнить конкретные поля обоих объектов, поэтому я создал объект типа адаптера, например:

DtoAdapter

import lombok.Data;
import java.util.List;

@Data
public class DtoAdapter {
    private String nameText;
    private List<String> xList;
}

Ниже приведен мой класс Test с методом main, в котором я пытаюсь выполнитьсравнение Это сравнение не удается, поскольку aList и bList содержат строки в разных порядках. Я хочу сравнить содержимое списка, не беспокоясь об их порядке.

Тест

import junit.framework.Assert;
import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        DtoA a = new DtoA();
        List<String> aList = new ArrayList<>();
        aList.add("x"); aList.add("y"); aList.add("z");
        a.setName("abc"); a.setNumber("123"); a.setAList(aList);

        DtoB b = new DtoB();
        List<String> bList = new ArrayList<>();
        bList.add("z"); bList.add("x"); bList.add("y");
        b.setName("abc"); b.setPhone("123"); b.setBList(bList);

        DtoAdapter a1 = new DtoAdapter();
        a1.setNameText(a.getName()); a1.setXList(a.getAList());

        DtoAdapter b1 = new DtoAdapter();
        b1.setNameText(b.getName()); b1.setXList(b.getBList());

        // comparision failing because of lists contains string in different orders
        Assert.assertEquals(a1, b1);
    }
}

Примечание. Я попытался написать CompareTo (реализуя сопоставимый интерфейс в классе DtoAdapter), но я не смогне пишите сравнение двух списков с методом сравнения, как показано ниже

DtoAdapter с сопоставимым интерфейсом

import lombok.Data;
import java.util.List;

@Data
public class DtoAdapter implements Comparable<DtoAdapter>{
    private String nameText;
    private List<String> xList;

    @Override
    public int compareTo(DtoAdapter o) {
        return this.getNameText().compareTo(o.getNameText());
        // how to compare this.getXList() and o.getXList() with compareTo?
    }
}

Ответы [ 5 ]

6 голосов
/ 11 октября 2019

То, что вы ожидаете, это не расширение Comparable, а переопределенная equals реализация для класса (вместе с hashcode, конечно).

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    DtoAdapter that = (DtoAdapter) o;
    // following line of code specifically
    return Objects.equals(nameText, that.nameText) &&
            that.getXList().containsAll(xList) && xList.containsAll(that.getXList());
}

Далее из документацииComparable, интерфейс в основном используется для упорядочивания элементов, а не для сравнения на равенство:

Этот интерфейс налагает полное упорядочение на объекты каждого класса, который его реализует. Это упорядочение называется естественным упорядочением класса, а метод compareTo класса называется его естественным методом сравнения .

1 голос
/ 11 октября 2019

Как и ответ от @Naman, вы можете переопределить метод equals, но попытаться сначала сравнить длину списков, потому что, если они имеют одинаковую длину, вам нужно только проверить, находятся ли элементы первого списка в другом.

@Override
public boolean equals(Object o) {
    if (o == this) {
        return true;
    } 

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

    DtoAdapter that = (DtoAdapter) o;

    return Objects.equals(nameText, that.nameText) && that.getXList().size() == xList.size() && that.getXList().containsAll(xList);

}
0 голосов
/ 11 октября 2019

Можно считать, что вы используете compareTo () класса String, как показано в следующем коде.

@Override
public int compareTo(DtoAdapter o) {
    int cmpName = this.getNameText().compareTo(o.getNameText());
    // how to compare this.getXList() and o.getXList() with compareTo?

    int cmpList = 0;
    if(this.list.size() != o.list.size()) {
        cmpList = this.list.size() - o.list.size();
    } else {
        for(int i = 0; i < list.size(); i++) {
            int v = list.get(i).compareTo(o.list.get(i));
            if(v != 0) {
                cmpList = v;
                break;
            }
        }
    }

    return cmpName + cmpList;
}
0 голосов
/ 11 октября 2019

Вы можете @Override метод равно в классе DtoAdapter.

@Override
public boolean equals(Object o) {
    if (o == this) {
        return true;
    } 

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

    DtoAdapter c = (DtoAdapter) o;

    if(c.getXList().size() != xList.size()) {
        return false;
    }

    // write logic for object comparison

    return c.getNameText().equals(nameText);
}

Если вы не хотите заботиться о порядке упорядочения списка, вы можете использовать метод removeAll ().

Сначала вы проверяете, имеют ли списки одинаковый размер. Затем вы удаляете все элементы из одного списка, используя другой список в качестве параметра.

c.getXList().removeAll(xList);

После удаления всех элементов вы проверяете, остался ли в первом списке какой-либо элемент. Если нет, это означает, что список содержит те же элементы.

0 голосов
/ 11 октября 2019

Я хочу сравнить содержимое списка, не беспокоясь об их порядке.

Я реализовал служебный метод, который позволяет сравнивать список, игнорируя порядок .

Библиотека доступна в Maven Central:

<dependency>
  <groupId>org.softsmithy.lib</groupId>
  <artifactId>softsmithy-lib-core</artifactId>
  <version>2.0</version>
</dependency>

Исходный код доступен из GitHub .

Также обратите внимание на лучшие практикиреализовать Comparable: https://stackoverflow.com/a/46287029/506855

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...