比较具有多个列表属性的两个对象的最佳方法是什么
What is the best way to compare two objects having multiple list attributes
我有一个 POJO/DTO class 具有多个列表属性,例如
class Boo {
private List<Foo> foos;
private List<Integer> pointers;
}
我想比较两个列表是否包含相同的值而忽略列表的顺序。是否可以在不打开对象并对列表进行排序的情况下实现这一点?
帮助将不胜感激。提前致谢
这归结为比较列表。如果项目的顺序无论如何都无关紧要,那么使用 Set
而不是 List
可能会更好。
你的 equals 看起来像
public boolean equals(object other) {
//here be class and null checks
return foos.equals(other.foos) && pointers.equals(other.pointers);
}
如果您不能使用 Set - 要么是因为您可以多次拥有相同的项目,要么是因为顺序很重要 - 您可以通过相互 containsAll()
调用来执行与上述相同的操作。这仍然不会考虑重复条目,但在其他情况下会工作得很好。
您声明无法编辑 class Boo
。一种解决方案是拥有一项服务 class ,它为您执行此操作有点类似于 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)
}
}
如果这对您有用 - 很好。也许你也必须比较其他成员。再说一遍:如果其中一个列表有两次条目,这将被忽略。
"I want to compare if both contains same values instead of the order of list."
没有通用的相等运算符。有时您希望通过某些属性比较对象。可能典型的例子是比较字符串,有时 "computer" 等于或不等于 "Computer" 或 "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
但是我无法定义你需要的等价关系,例如,如果一个列表包含的元素多于另一个但也许你希望(例如对你等于 {a, b, a}
比 {b, a}
).
因此,为您的对象定义等价关系并覆盖 hashCode
和 equals
。
我有一个 POJO/DTO class 具有多个列表属性,例如
class Boo {
private List<Foo> foos;
private List<Integer> pointers;
}
我想比较两个列表是否包含相同的值而忽略列表的顺序。是否可以在不打开对象并对列表进行排序的情况下实现这一点?
帮助将不胜感激。提前致谢
这归结为比较列表。如果项目的顺序无论如何都无关紧要,那么使用 Set
而不是 List
可能会更好。
你的 equals 看起来像
public boolean equals(object other) {
//here be class and null checks
return foos.equals(other.foos) && pointers.equals(other.pointers);
}
如果您不能使用 Set - 要么是因为您可以多次拥有相同的项目,要么是因为顺序很重要 - 您可以通过相互 containsAll()
调用来执行与上述相同的操作。这仍然不会考虑重复条目,但在其他情况下会工作得很好。
您声明无法编辑 class Boo
。一种解决方案是拥有一项服务 class ,它为您执行此操作有点类似于 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)
}
}
如果这对您有用 - 很好。也许你也必须比较其他成员。再说一遍:如果其中一个列表有两次条目,这将被忽略。
"I want to compare if both contains same values instead of the order of list."
没有通用的相等运算符。有时您希望通过某些属性比较对象。可能典型的例子是比较字符串,有时 "computer" 等于或不等于 "Computer" 或 "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
但是我无法定义你需要的等价关系,例如,如果一个列表包含的元素多于另一个但也许你希望(例如对你等于 {a, b, a}
比 {b, a}
).
因此,为您的对象定义等价关系并覆盖 hashCode
和 equals
。