Сравните 2 списка Java, используя пользовательскую логику - PullRequest
0 голосов
/ 12 октября 2018

Я хочу сравнить 2 списка Java, которые содержат 2 различных типа объектов.Однако оба типа объектов имеют некоторые общие свойства, и я хочу сравнить их.

class A {
  int id;
} 

class B {
  int id2;
}

List<A> listA; // contains some objects
List<B> listB

// comparison logic
boolean isEqual = true;
if(listA.size() != listB.size())
  isEqual = false;

for(int i=0;i<listA.size();++i) {
  if(!listA.get(i).equals(listB.get(i)) {
    isEqual = false;
    break;
  }
}

Есть ли хороший способ написать это кратко через потоки Java?

Ответы [ 6 ]

0 голосов
/ 12 октября 2018

Учитывая два класса бинов, например,

@Immutable
static class Person {
    private final String firstName;
    private final String secondName;
    private final String phoneNumber;

    public Person(String firstName, String secondName, String phoneNumber) {
        this.firstName = firstName;
        this.secondName = secondName;
        this.phoneNumber = phoneNumber;
    }
    public String getFirstName() {
        return this.firstName;
    }
    public String getSecondName() {
        return this.secondName;
    }
    public String getPhoneNumber() {
        return this.phoneNumber;
    }
}

@Immutable
static class Company {
    private final String name;
    private final String phoneNumber;
    public Company(String name, String phoneNumber) {
        this.name = name;
        this.phoneNumber = phoneNumber;
    }
    public String getName() {
       return this.name;
    }
    public String getPhoneNumber() {
       return this.phoneNumber;
    }
}

, общие свойства могут быть помещены в третий класс, например,

static class CommonData {
    private final String phoneNumber;

    public CommonData(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getPhoneNumber() {
        return this.phoneNumber;
    }   

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof ListComparisTest.CommonData) {
            ListComparisTest.CommonData rhs = (ListComparisTest.CommonData) obj;
            return new EqualsBuilder()
                .append(this.phoneNumber, rhs.phoneNumber)
                .isEquals();
        }
        return false;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder()
            .append(phoneNumber)
            .toHashCode();
    }

}

и два списка, сравниваемых как этот

@Test
public  void testCompareLists() {
    Function<Person, CommonData> person2CommonData = p->new CommonData(p.getPhoneNumber());
    Function<Company, CommonData> company2CommonData = c->new CommonData(c.getPhoneNumber());

    List<Person> persons = Arrays.asList(new Person("James", "Cook", "1234566" ), new Person("Francis", "Drake", "2345667" )); 
    List<Company> companys = Arrays.asList(new Company("Google",  "1234566" ), new Company("IBM",  "2345667" )); 

    List<CommonData> personsCommonData = persons.stream().map(person2CommonData).collect(Collectors.toList());
    List<CommonData> companysCommonData = companys.stream().map(company2CommonData).collect(Collectors.toList());

    Assert.assertTrue(personsCommonData.equals(companysCommonData));
}
0 голосов
/ 12 октября 2018

Сначала создайте интерфейс, содержащий общие свойства.Затем добавьте реализации NewInterface в класс A и класс B. Затем реализуйте компаратор, сравнивая эти интерфейсы.А затем используйте этот компаратор, чтобы сравнить их.

0 голосов
/ 12 октября 2018

С вашим кодом можно выкинуть, если IndexOutOfBoundsException, если A больше B.

Для меня я сделаю это.

//Change id in class A and B from int to Integer

Boolean isEqual = Boolean.True;
Iterator<A> iterA = listA.iterator();
Iterator<B> iterB = listB.iterator();

while( iterA.hasNext() && iterB.hasNext()){
     A a = iterA.next();
     B b = iterB.next();

     if( !a.getA().equals(b.getB()){
          isEqual = Boolean.False;
          return;
     }
}
0 голосов
/ 12 октября 2018

Я думаю, что вы должны представить некоторый класс обслуживания с методом, который использует A и B в качестве аргументов объектов, сравнивать эти объекты и возвращать логическое значение.Этот подход позволяет сравнивать два разных объекта по свойствам.Примерно так:

public class CompareService {

    public boolean comparteObjectAToB(ObjectA a, ObjectB b) {
        //logic
    }
}

public class SomeService {

    private CompareService compareService = new CompareService();

    public boolean compare() { 
        List<ObjectA> listA = new ArrayList<>();
        List<ObjectB> list2 = new ArrayList<>();
        //some logic which fill lists, empty checks etc

        return listA.stream().anyMatch(o1 -> list2.stream().anyMatch(o2 -> compareService.comparteObjectAToB(o1, o2)));
        }
    }
0 голосов
/ 12 октября 2018

Самый простой способ сделать так, чтобы вы могли на самом деле проверять и контролировать все переменные, которые вы хотите сравнить, это что-то вроде следующего.Просто сохраните шаблон и добавьте больше if, где вы хотите сделать проверки .equals(), а также он будет работать с любыми размерами списков, и вы не получите исключение IndexOutOfBounds

   class A {
      int id;
    } 

    class B {
      int id2;
    }

    List<A> listA; // contains some objects
    List<B> listB;

    // comparison logic
    boolean isEqual = true;
        for(int i=0;i<listA.size();++i) {
            A objectA = listA.get(i);
            for(int y=0; y<listB.size();y++){
              B objectB = listB.get(y);

              if(!objectA.getVar().equals(objectB.getVar())) { 
                //And so on for every same object the two classes have and can be compared.
                isEqual = false;
                break;
              }
           }
        }
    }
0 голосов
/ 12 октября 2018

Один из способов сделать это - использовать IntStream:

boolean equal = (IntStream.range(0, listA.size())
     .filter(i -> listA.get(i).equals(listB.get(i))).count() == listA.size());

Это не сработает для списка разных размеров, но это просто простое условие (listA.size() == listB.size()), которое я опущу для краткости.

РЕДАКТИРОВАТЬ:

Это может быть улучшено с помощью noneMatch():

boolean equal = IntStream.range(0, listA.size())
                         .noneMatch(i -> listA.get(i).id != listB.get(i).id2);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...