使用自定义相等函数检查两个集合是否相同(忽略顺序)
Check if two collections are the same (ignoring order) using a custom equality function
我有两个 Foo 集合。我无法更改 Foo 的实现,并且 Foo 的 equals 函数实现不正确。我也不能继承 Foo。我执行自定义相等函数:我已经使用 guava 的 Predicate 函数实现了。为了给你一个想法,实现看起来有点像这样。
new Predicate<Pair<Foo, Foo>>() {
@Override
public boolean apply(@Nullable Pair<Foo, Foo> input) {
Foo one = input.getFirst();
Foo two = input.getSecond();
return Objects.equals(one.getId(), two.getId());
}
};
现在我需要检查我的两个 Foo 集合是否包含相同的项目忽略顺序
我正在寻找使用此自定义相等函数执行此操作的最佳方法。
而不是自定义 Predicate
,为什么不使用带有自定义 Comparator
的简单 SortedSet
?
Comparator<Foo> comparator = new Comparator<Foo>() {
public int compare(Foo o1, Foo o2) {
return //your custom comparison
}
};
SortedSet<Foo> sortedSet1 = newTreeSet(comparator);
sortedSet1.addAll(firstCollection);
SortedSet<Foo> sortedSet2 = newTreeSet(comparator);
sortedSet2.addAll(secondCollection);
sortedSet1.equals(sortedSet); //this is what you want
如果您不想在操作后对列表进行排序,请复制它或使用带有 Set
的答案(但带有 Set
[1,1,1] == [1]) .
public class ListTest {
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list3 = Arrays.asList(1, 2, 3, 4, 4);
System.out.println(compare(list1, list2, (a, b) -> a - b));
System.out.println(compare(list1, list3, (a, b) -> a - b));
}
private static <E> boolean compare(List<E> list1, List<E> list2, Comparator<E> comparator) {
if(list1.size() != list2.size()) {
return false;
}
Collections.sort(list1, comparator);
Collections.sort(list2, comparator);
Iterator<E> iterator1 = list1.iterator();
Iterator<E> iterator2 = list2.iterator();
while (iterator1.hasNext()) {
if(comparator.compare(iterator1.next(), iterator2.next()) != 0) {
return false;
}
}
return true;
}
}
您可以将 class 包裹在 Guava Equivalence
中并将其存储在集合中。
Equivalence<Foo> eq = new Equivalence<Foo>{
// implement equals and hashcode
};
Set<Equivalence<Foo>> set1 = new HashSet<>();
set1.add(eq.wrap(someFoo));
这样你就可以进行双向 containsAll()
或
Sets.difference(set1, set2).isEmpty()
我有两个 Foo 集合。我无法更改 Foo 的实现,并且 Foo 的 equals 函数实现不正确。我也不能继承 Foo。我执行自定义相等函数:我已经使用 guava 的 Predicate 函数实现了。为了给你一个想法,实现看起来有点像这样。
new Predicate<Pair<Foo, Foo>>() {
@Override
public boolean apply(@Nullable Pair<Foo, Foo> input) {
Foo one = input.getFirst();
Foo two = input.getSecond();
return Objects.equals(one.getId(), two.getId());
}
};
现在我需要检查我的两个 Foo 集合是否包含相同的项目忽略顺序
我正在寻找使用此自定义相等函数执行此操作的最佳方法。
而不是自定义 Predicate
,为什么不使用带有自定义 Comparator
的简单 SortedSet
?
Comparator<Foo> comparator = new Comparator<Foo>() {
public int compare(Foo o1, Foo o2) {
return //your custom comparison
}
};
SortedSet<Foo> sortedSet1 = newTreeSet(comparator);
sortedSet1.addAll(firstCollection);
SortedSet<Foo> sortedSet2 = newTreeSet(comparator);
sortedSet2.addAll(secondCollection);
sortedSet1.equals(sortedSet); //this is what you want
如果您不想在操作后对列表进行排序,请复制它或使用带有 Set
的答案(但带有 Set
[1,1,1] == [1]) .
public class ListTest {
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list3 = Arrays.asList(1, 2, 3, 4, 4);
System.out.println(compare(list1, list2, (a, b) -> a - b));
System.out.println(compare(list1, list3, (a, b) -> a - b));
}
private static <E> boolean compare(List<E> list1, List<E> list2, Comparator<E> comparator) {
if(list1.size() != list2.size()) {
return false;
}
Collections.sort(list1, comparator);
Collections.sort(list2, comparator);
Iterator<E> iterator1 = list1.iterator();
Iterator<E> iterator2 = list2.iterator();
while (iterator1.hasNext()) {
if(comparator.compare(iterator1.next(), iterator2.next()) != 0) {
return false;
}
}
return true;
}
}
您可以将 class 包裹在 Guava Equivalence
中并将其存储在集合中。
Equivalence<Foo> eq = new Equivalence<Foo>{
// implement equals and hashcode
};
Set<Equivalence<Foo>> set1 = new HashSet<>();
set1.add(eq.wrap(someFoo));
这样你就可以进行双向 containsAll()
或
Sets.difference(set1, set2).isEmpty()