在标准Java库中,找出两个list是否包含完全相同的元素的最简单方法是什么?
这两个list是否为相同实例并不重要,这两个list的类型参数是否不同也不重要。
e.g.
List list1
List<String> list2;
// ... construct etc
list1.add("A");
list2.add("A");
// the function, given these two lists, should return true
我知道可能有什么东西在盯着我的脸:-)
编辑:为了澄清,我正在寻找完全相同的元素和元素的数量,按顺序。
我知道这可能非常晚,但我个人使用这个功能。
如果有人想做一些基准测试,那就太好了。
public static<X> boolean areEqual(List<X> a, List<X> b, BiPredicate<X, X> AEqualsB) {
boolean aIsNull = a == null;
boolean bIsNull = b == null;
if (aIsNull || bIsNull) {
return aIsNull == bIsNull;
}
int size = a.size();
boolean sameSize = size == b.size();
if (!sameSize) {return false;} else {
for (int i = 0; i < size; i++) {
X aX = a.get(i), bX = b.get(i);
boolean areEqual = AEqualsB.test(aX, bX);
if (!areEqual) {
return false;
}
}
return true;
}
}
顺便说一句,我知道前5行可以用一个异或“^”加上一个else来简化,但信不信由你,我很难得出正确的异或。
我想它的效率取决于谓词的类型,但同时它允许您检查自定义的潜在相等,而忽略对编码器来说可能无关紧要的差异。
下面是一个代码示例。
ListUtils.areEqual(newElements, oldElements, Element::areEqual)
public boolean areEqual(Element e) {
return optionalAdapterId() == e.optionalAdapterId()
&& value == e.value
&& valueTotal == e.valueTotal
&& stockTotal == e.stockTotal
&& element_title.equals(e.element_title);
}
至于效率,我认为任何迭代总是昂贵,这就是为什么每当我需要使用这个函数与大名单,我在一个单独的线程执行的操作,和检索响应的需要,即使它很高兴知道此时,它是有益的在一个不同的线程,是什么项目,要求这些线程的数量,这些信息将被添加文档。
如果你关心顺序,那么只需使用equals方法:
list1.equals(list2)
来自javadoc:
Compares the specified object with
this list for equality. Returns true
if and only if the specified object is
also a list, both lists have the same
size, and all corresponding pairs of
elements in the two lists are equal.
(Two elements e1 and e2 are equal if
(e1==null ? e2==null :
e1.equals(e2)).) In other words, two
lists are defined to be equal if they
contain the same elements in the same
order. This definition ensures that
the equals method works properly
across different implementations of
the List interface.
如果你想检查与顺序无关,你可以复制所有的元素到set,并在结果集上使用equals:
public static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
return new HashSet<>(list1).equals(new HashSet<>(list2));
}
这种方法的一个局限性是它不仅忽略了顺序,而且还忽略了重复元素的频率。例如,如果list1是["A", "B", "A"], list2是["A", "B", "B"],则Set方法将认为它们相等。
如果你需要对顺序不敏感,但对重复的频率敏感,你可以:
在比较它们之前对两个列表(或副本)进行排序,就像在回答另一个问题时所做的那样
或复制所有元素到Multiset
我知道这可能非常晚,但我个人使用这个功能。
如果有人想做一些基准测试,那就太好了。
public static<X> boolean areEqual(List<X> a, List<X> b, BiPredicate<X, X> AEqualsB) {
boolean aIsNull = a == null;
boolean bIsNull = b == null;
if (aIsNull || bIsNull) {
return aIsNull == bIsNull;
}
int size = a.size();
boolean sameSize = size == b.size();
if (!sameSize) {return false;} else {
for (int i = 0; i < size; i++) {
X aX = a.get(i), bX = b.get(i);
boolean areEqual = AEqualsB.test(aX, bX);
if (!areEqual) {
return false;
}
}
return true;
}
}
顺便说一句,我知道前5行可以用一个异或“^”加上一个else来简化,但信不信由你,我很难得出正确的异或。
我想它的效率取决于谓词的类型,但同时它允许您检查自定义的潜在相等,而忽略对编码器来说可能无关紧要的差异。
下面是一个代码示例。
ListUtils.areEqual(newElements, oldElements, Element::areEqual)
public boolean areEqual(Element e) {
return optionalAdapterId() == e.optionalAdapterId()
&& value == e.value
&& valueTotal == e.valueTotal
&& stockTotal == e.stockTotal
&& element_title.equals(e.element_title);
}
至于效率,我认为任何迭代总是昂贵,这就是为什么每当我需要使用这个函数与大名单,我在一个单独的线程执行的操作,和检索响应的需要,即使它很高兴知道此时,它是有益的在一个不同的线程,是什么项目,要求这些线程的数量,这些信息将被添加文档。