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

使用自定义逻辑比较2个java列表,java,java-stream,Java,Java Stream,我想比较两个java列表,其中包含两种不同类型的对象。但是,这两种类型的对象都有一些共同的属性,我想对它们进行比较 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())

我想比较两个java列表,其中包含两种不同类型的对象。但是,这两种类型的对象都有一些共同的属性,我想对它们进行比较

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;
  }
}
A类{
int-id;
} 
B类{
INTID2;
}
列表a;//包含一些对象
列表B
//比较逻辑
布尔相等=真;
如果(listA.size()!=listB.size())
isEqual=假;

对于(inti=0;i一种方法是使用
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()
对其进行改进:


最简单的方法是,您可以实际检查和控制所有要比较的变量,如下所示。只需保留模式并在希望进行
.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;
              }
           }
        }
    }
A类{
int-id;
} 
B类{
INTID2;
}
List listA;//包含一些对象
名单b;
//比较逻辑
布尔相等=真;

对于(int i=0;i我认为您应该引入一些服务类,其方法使用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)));
        }
    }
公共类比较服务{
公共布尔比较ObjectAtoB(ObjectA,ObjectB){
//逻辑
}
}
公共类服务{
private CompareService CompareService=新的CompareService();
公共布尔比较({
List listA=new ArrayList();
List list2=新的ArrayList();
//填写列表、空支票等的逻辑
返回listA.stream().anyMatch(o1->list2.stream().anyMatch(o2->compareService.comparteObjectAToB(o1,o2));
}
}

对于您的代码,如果A大于B,则可能引发if 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;
     }
}
//将类A和B中的id从int更改为整数
布尔isEqual=Boolean.True;
迭代器iterA=listA.Iterator();
迭代器iterB=listB.Iterator();
while(iterA.hasNext()&&iterB.hasNext()){
A=iterA.next();
B=iterB.next();
如果(!a.getA().等于(b.getB()){
isEqual=Boolean.False;
返回;
}
}

首先创建一个包含公共属性的接口。然后将implements NewInterface添加到类A和类B。然后实现comparator,比较这些接口。然后使用该comparator比较它们。

给定两个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));
}
@测试
公共void testCompareLists(){
函数person2CommonData=p->newcommondata(p.getPhoneNumber());
函数company2CommonData=c->newcommondata(c.getPhoneNumber());
List persons=Arrays.asList(新人(“詹姆斯”、“库克”、“1234566”)、新人(“弗朗西斯”、“德雷克”、“234567”);
List companys=Arrays.asList(新公司(“谷歌”、“1234566”)、新公司(“IBM”、“234567”);
List personcommondata=persons.stream().map(person2CommonData.collect(Collectors.toList());
列出companysCommonData=companys.stream().map(company2CommonData.collect(Collectors.toList());
Assert.assertTrue(personCommonData.equals(CompanyCommonData));
}

不太可能(但我可能错了)。但我会使用
迭代器
而不是
get(int)
方法。比较逻辑怎么可能工作?a等于(b)当a.id=b.id2时为true?@Michal,你可以假设这是一个验证检查而不是相等,如果这更合理的话,我想问题和接受的答案在以b为参数的实例上都是相等的,我猜应该是a.id和b.id2。这只是一个玩具示例。在实际用例中,我想比较3个属性为类A和B对象设置一个参数,以确定验证是否成功。如果
listB.size()
?如果listB的元素数量少于listA,它不会失败吗?如果第一个元素不相等,您仍然会检查其余的元素。我会使用带有相反条件的
anyMatch
。谢谢,我之前误解了。这将按预期工作。但是,我现在不太确定这看起来是否比以前的方法更好。
@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));
}