使用自定义逻辑比较2个Java列表

时间:2018-10-12 07:10:31

标签: java java-stream

我想比较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 :(得分:2)

一种方法是使用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);

答案 1 :(得分:0)

最简单的方法是,您实际上可以检查和控制要比较的所有变量,如下所示。只需保持模式并在要进行.equals()检查的位置添加更多ifs,它就可以与任何大小的列表一起使用,并且不会出现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;
              }
           }
        }
    }

答案 2 :(得分:0)

我认为您应该引入一些服务类,其方法使用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)));
        }
    }

答案 3 :(得分:0)

使用您的代码,如果A大于B,则可能抛出IndexOutOfBoundsException。

对我来说,我会这样做。

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

答案 4 :(得分:0)

首先创建一个包含通用属性的接口。然后将实现NewInterface添加到类A和类B。然后实现比较器,比较这些接口。然后使用该比较器进行比较。

答案 5 :(得分:0)

给出两个bean类,例如

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