我有一个具有多个列表属性的POJO / DTO类,例如
class Boo {
private List<Foo> foos;
private List<Integer> pointers;
}
我想比较两个列表是否包含相同的值而忽略列表的顺序。是否可以在不打开对象和对列表进行排序的情况下实现这一目标?
我们将不胜感激。在此先感谢
答案 0 :(得分:1)
“我想比较两个值是否包含相同的值,而不是列表的顺序。”
没有通用相等运算符。有时您想按某些属性比较对象。典型的例子可能是比较字符串,有时“计算机”等于或不等于“计算机”或“Vesterålen”等于或不等于“ Vesteralen”。
在 Java 中,您可以重新定义对象之间的默认等价关系(修改默认行为!)。
对象List
使用所包含对象的默认等价关系作为默认的等价关系,并按顺序检查该相等性。
下面的示例仅忽略一个属性中的元素顺序:
class My {
private final List<String> xs;
private final List<Integer> ys;
My(List<String> xs, List<Integer> ys) {
this.xs = xs;
this.ys = ys;
}
public List<Integer> getYs() {
return ys;
}
public List<String> getXs() {
return xs;
}
@Override
public int hashCode() {
return xs.hashCode() + 7 * ys.hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof My))
return false;
My o = (My) obj;
return
// ignoring order
getXs().stream().sorted().collect(toList()).equals(o.getXs().stream().sorted().collect(toList()))
// checking order
&& getYs().equals(o.getYs());
}
}
public class Callme {
public static void main(String... args) {
My m1 = new My(asList("a", "b"), asList(1, 2));
My m2 = new My(asList("b", "a"), asList(1, 2));
My m3 = new My(asList("a", "b"), asList(2, 1));
System.out.println(m1.equals(m2));
System.out.println(m1.equals(m3));
}
}
有输出
true
false
但是我无法定义您所需的等价关系,例如,我不会忽略一个列表是否包含比另一个列表更多的元素,但也许您希望(例如,您等于{{1 }}比{a, b, a}
)。
因此,请为您的对象定义等价关系,并覆盖{b, a}
和hashCode
。
答案 1 :(得分:0)
这归结为比较列表。如果项目的顺序无关紧要,则最好使用Set
代替List
。
然后,您的等于
public boolean equals(object other) {
//here be class and null checks
return foos.equals(other.foos) && pointers.equals(other.pointers);
}
如果您不能使用Set,则可能是因为您可以多次拥有相同的商品,或者是因为订单很重要,所以您可以通过互惠的containsAll()
进行与上述相同的操作。仍然不会考虑重复的条目,但否则可以很好地工作。
您声明不能编辑类Boo
。一种解决方案是拥有一个服务类,该类为您执行类似于Objects.equals()
的服务。
class BooComparer {
public static bool equals(Boo a, Boo b) {
//again do some null checks here
return a.foos.containsAll(b.foos)
&& b.foos.containsAll(a.foos)
&& a.pointers.containsAll(b.pointers)
&& b.pointers.containsAll(a.pointers)
}
}
如果这对您有用-很好。也许您也必须比较其他成员。再说一次:如果其中一个列表有两次输入,这将忽略。