Java 比较一个类的两个集合,不带等号

Java 比较一个类的两个集合,不带等号,java,junit,assertj,Java,Junit,Assertj,我有一节课: public class Something { public String a; public String b; } 假设我不能在类中编写equals或compare方法 我的测试: Set<Something> aSet; Set<Something> otherSet; assertEquals(aSet, otherSet);//Fails because it only compares references of element

我有一节课:

public class Something {
   public String a;
   public String b;
}
假设我不能在类中编写equals或compare方法

我的测试:

Set<Something> aSet;
Set<Something> otherSet;

assertEquals(aSet, otherSet);//Fails because it only compares references of elements and does not perform a deep comparision field by field
设置aSet;
设置其他设置;
资产质量(aSet,其他集合)//失败,因为它只比较元素的引用,不逐字段执行深度比较

是否有任何方法可以断言两个集合是否相等,并逐字段比较元素(而不在某个类中写入equals方法)?

您可以使用Hamcrest库并执行以下操作

assertThat( aSet, both(everyItem(isIn(otherSet))).and(containsInAnyOrder(aSet)));

您可以使用Hamcrest库并执行以下操作:

assertThat( aSet, both(everyItem(isIn(otherSet))).and(containsInAnyOrder(aSet)));

当我无法在遗留代码中实现
equals/hashCode
时,我遇到了类似的情况

让我分享一个基于包装器模式的解决方案。将遗留类包装起来,并在那里实现
equals/hashCode
。在您的测试中,您创建了一组包装对象,并以常规方式对其进行测试

public class SomethingTest {
    class SomethingWrapper {
        private final Something value;

        SomethingWrapper(Something value) {
            this.value = value;
        }

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

            if (o == null || getClass() != o.getClass()) return false;

            SomethingWrapper that = (SomethingWrapper) o;

            return new EqualsBuilder()
                    .append(value.a, that.value.a)
                    .append(value.b, that.value.b)
                    .isEquals();
        }

        @Override
        public int hashCode() {
            return new HashCodeBuilder(17, 37)
                    .append(value.a)
                    .append(value.b)
                    .toHashCode();
        }
    }

    @Test
    public void compareSomethingSetsWithoutEquals() {
        final Set<Something> originalA = new HashSet<>();
        originalA.add(new Something("a1", "b1"));
        originalA.add(new Something("a2", "b2"));

        final Set<Something> originalB = new HashSet<>();
        originalB.add(new Something("a1", "b1"));
        originalB.add(new Something("a2", "b2"));

        final Set<SomethingWrapper> aWrappedSetA =
                originalA.stream().map(SomethingWrapper::new).collect(Collectors.toSet());

        final Set<SomethingWrapper> aWrappedSetB =
                originalB.stream().map(SomethingWrapper::new).collect(Collectors.toSet());

        assertEquals(aWrappedSetA, aWrappedSetB);
    }
}
公共类SomethingTest{
类SomethingWrapper{
私人最终价值;
SomethingWrapper(somethingvalue){
这个值=值;
}
@凌驾
公共布尔等于(对象o){
如果(this==o)返回true;
如果(o==null | | getClass()!=o.getClass())返回false;
SomethingWrapper,它=(SomethingWrapper)o;
返回新的EqualBuilder()
.append(value.a,that.value.a)
.append(value.b,that.value.b)
.isEquals();
}
@凌驾
公共int hashCode(){
返回新的HashCodeBuilder(17,37)
.append(value.a)
.append(value.b)
.toHashCode();
}
}
@试验
public void compareSomethingSetsWithoutEquals(){
final Set originalA=新HashSet();
添加(新事物(“a1”、“b1”);
添加(新事物(“a2”、“b2”);
final Set originalB=新HashSet();
添加(新事物(“a1”、“b1”);
添加(新事物(“a2”、“b2”);
最后一组A拉佩德塞塔=
originalA.stream().map(SomethingWrapper::new).collect(Collectors.toSet());
最终设定aWrappedSetB=
originalB.stream().map(SomethingWrapper::new).collect(Collectors.toSet());
资产质量(aWrappedSetA、aWrappedSetB);
}
}

当我无法在遗留代码中实现
equals/hashCode
时,我遇到了类似的情况

让我分享一个基于包装器模式的解决方案。将遗留类包装起来,并在那里实现
equals/hashCode
。在您的测试中,您创建了一组包装对象,并以常规方式对其进行测试

public class SomethingTest {
    class SomethingWrapper {
        private final Something value;

        SomethingWrapper(Something value) {
            this.value = value;
        }

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

            if (o == null || getClass() != o.getClass()) return false;

            SomethingWrapper that = (SomethingWrapper) o;

            return new EqualsBuilder()
                    .append(value.a, that.value.a)
                    .append(value.b, that.value.b)
                    .isEquals();
        }

        @Override
        public int hashCode() {
            return new HashCodeBuilder(17, 37)
                    .append(value.a)
                    .append(value.b)
                    .toHashCode();
        }
    }

    @Test
    public void compareSomethingSetsWithoutEquals() {
        final Set<Something> originalA = new HashSet<>();
        originalA.add(new Something("a1", "b1"));
        originalA.add(new Something("a2", "b2"));

        final Set<Something> originalB = new HashSet<>();
        originalB.add(new Something("a1", "b1"));
        originalB.add(new Something("a2", "b2"));

        final Set<SomethingWrapper> aWrappedSetA =
                originalA.stream().map(SomethingWrapper::new).collect(Collectors.toSet());

        final Set<SomethingWrapper> aWrappedSetB =
                originalB.stream().map(SomethingWrapper::new).collect(Collectors.toSet());

        assertEquals(aWrappedSetA, aWrappedSetB);
    }
}
公共类SomethingTest{
类SomethingWrapper{
私人最终价值;
SomethingWrapper(somethingvalue){
这个值=值;
}
@凌驾
公共布尔等于(对象o){
如果(this==o)返回true;
如果(o==null | | getClass()!=o.getClass())返回false;
SomethingWrapper,它=(SomethingWrapper)o;
返回新的EqualBuilder()
.append(value.a,that.value.a)
.append(value.b,that.value.b)
.isEquals();
}
@凌驾
公共int hashCode(){
返回新的HashCodeBuilder(17,37)
.append(value.a)
.append(value.b)
.toHashCode();
}
}
@试验
public void compareSomethingSetsWithoutEquals(){
final Set originalA=新HashSet();
添加(新事物(“a1”、“b1”);
添加(新事物(“a2”、“b2”);
final Set originalB=新HashSet();
添加(新事物(“a1”、“b1”);
添加(新事物(“a2”、“b2”);
最后一组A拉佩德塞塔=
originalA.stream().map(SomethingWrapper::new).collect(Collectors.toSet());
最终设定aWrappedSetB=
originalB.stream().map(SomethingWrapper::new).collect(Collectors.toSet());
资产质量(aWrappedSetA、aWrappedSetB);
}
}

尝试一下AssertJ,它提供了一种方法,例如:

// the Dude class does not override equals
Dude jon = new Dude("Jon", 1.2);
Dude sam = new Dude("Sam", 1.3);
jon.friend = sam;
sam.friend = jon;

Dude jonClone = new Dude("Jon", 1.2);
Dude samClone = new Dude("Sam", 1.3);
jonClone.friend = samClone;
samClone.friend = jonClone;

assertThat(asList(jon, sam)).usingRecursiveFieldByFieldElementComparator()
                            .contains(jonClone, samClone);
另一种可能是使用so
SomethingComparator
比较集合。在您的情况下,这需要比第一个选项多一点工作,但您可以完全控制比较


希望有帮助

尝试一下AssertJ,它提供了一种方法,例如:

// the Dude class does not override equals
Dude jon = new Dude("Jon", 1.2);
Dude sam = new Dude("Sam", 1.3);
jon.friend = sam;
sam.friend = jon;

Dude jonClone = new Dude("Jon", 1.2);
Dude samClone = new Dude("Sam", 1.3);
jonClone.friend = samClone;
samClone.friend = jonClone;

assertThat(asList(jon, sam)).usingRecursiveFieldByFieldElementComparator()
                            .contains(jonClone, samClone);
另一种可能是使用so
SomethingComparator
比较集合。在您的情况下,这需要比第一个选项多一点工作,但您可以完全控制比较


希望有帮助

您可以使用带有自定义比较器的树集。因此,这个问题看起来也很有希望:请仅使用与您的问题真正相关的标记。你的问题与嘲笑框架没有任何关系!那么,当类中没有适当的equals/hashcode方法时,使用集合有什么意义呢?是否真的有“东西”可以多次添加实例?您可以使用带有自定义比较器的树集。因此,这个问题看起来也很有希望:请仅使用与您的问题真正相关的标记。你的问题与嘲笑框架没有任何关系!那么,当类中没有适当的equals/hashcode方法时,使用集合有什么意义呢?是否真的存在多次添加实例的“东西”?如果没有equals方法,这将如何工作?我同意@shmosel的观点-我真的怀疑这是否能回答这个问题。那些汉克雷斯特配对者。。。最终将调用equals()。如果没有equals方法,这将如何工作?我同意@shmosel-我真的怀疑这是否能回答这个问题。那些汉克雷斯特配对者。。。我最终会调用equals(),之所以选择它,是因为它正确、简单、流畅。这样做没有意义