Java - 删除一个集合中另一个集合中的对象,具有任意含义 "equals"
Java - remove objects in a collection that are in another collection, with an arbitrary meaning of "equals"
如果我只想以绝对平等为基础,这很容易。我只想做:
collectionA.removeAll(collectionB).
但是,假设我有这个对象:
class Item {
private String color;
private String name;
private String type;
}
还有两个合集...
List<Item> items1, List<item> items2.
...但我只想从 item1 中删除与 item2 中具有相同 名称和类型 的所有内容。
请注意,我不能子class 或定义等号,为此 class 的哈希码。
我希望这与现有 collections.removeAll 方法的复杂性相同。
我能想到的最佳解决方案如下:
class SimpleItem {
String name;
String type;
Item item;
public SimpleItem(Item item) {
this.name = item.getName();
this.type = item.getType();
}
@Override
public boolean equals(Object obj) {
...
}
@Override
public int hashCode() {
...
}
}
Set<SimpleItem> simpleItems1 = ...;
for (Item item : items1) {
simpleItems1.add(new SimpleItem(item));
}
Set<SimpleItem> simpleItems2 = ...;
for (Item item : items2) {
simpleItems2.add(new SimpleItem(item));
}
simpleItems1.removeAll(simpleItems2);
Set<Item> items = ...;
for (SimpleItem simpleItem : simpleItems) {
items.add(simpleItem.item);
}
...但这太冗长了。是 Java 8. 我错过了什么巧妙的解决方案?
您可以使用 apache commons class to do so. Good examples are here
Another link
你提到它是 Java 8。在那种情况下,你有一个非常简单直接的方法来实现它:
list1.removeIf(item1 -> list2.stream().anyMatch(item2 -> customEquals(item1, item2));
如果您的 customEquals
方法是 Item
的成员,您可以使用方法参考使其更整洁:
list1.removeIf(item -> list2.stream().anyMatch(item::customEquals));
在您的情况下,您可以将条件直接放入语句中,而不是创建一个单独的方法:
list1.removeIf(item1 -> list2.stream().anyMatch(item2 ->
item1.getName().equals(item2.getName()) && item1.getType().equals(item2.getType())));
方便的是 removeIf
是 Collection
接口的默认成员,因此只要实现的迭代器支持 [=18],任何实现 Collection
的 class 都应该支持它=].
如果我只想以绝对平等为基础,这很容易。我只想做:
collectionA.removeAll(collectionB).
但是,假设我有这个对象:
class Item {
private String color;
private String name;
private String type;
}
还有两个合集...
List<Item> items1, List<item> items2.
...但我只想从 item1 中删除与 item2 中具有相同 名称和类型 的所有内容。
请注意,我不能子class 或定义等号,为此 class 的哈希码。
我希望这与现有 collections.removeAll 方法的复杂性相同。
我能想到的最佳解决方案如下:
class SimpleItem {
String name;
String type;
Item item;
public SimpleItem(Item item) {
this.name = item.getName();
this.type = item.getType();
}
@Override
public boolean equals(Object obj) {
...
}
@Override
public int hashCode() {
...
}
}
Set<SimpleItem> simpleItems1 = ...;
for (Item item : items1) {
simpleItems1.add(new SimpleItem(item));
}
Set<SimpleItem> simpleItems2 = ...;
for (Item item : items2) {
simpleItems2.add(new SimpleItem(item));
}
simpleItems1.removeAll(simpleItems2);
Set<Item> items = ...;
for (SimpleItem simpleItem : simpleItems) {
items.add(simpleItem.item);
}
...但这太冗长了。是 Java 8. 我错过了什么巧妙的解决方案?
您可以使用 apache commons class to do so. Good examples are here
Another link
你提到它是 Java 8。在那种情况下,你有一个非常简单直接的方法来实现它:
list1.removeIf(item1 -> list2.stream().anyMatch(item2 -> customEquals(item1, item2));
如果您的 customEquals
方法是 Item
的成员,您可以使用方法参考使其更整洁:
list1.removeIf(item -> list2.stream().anyMatch(item::customEquals));
在您的情况下,您可以将条件直接放入语句中,而不是创建一个单独的方法:
list1.removeIf(item1 -> list2.stream().anyMatch(item2 ->
item1.getName().equals(item2.getName()) && item1.getType().equals(item2.getType())));
方便的是 removeIf
是 Collection
接口的默认成员,因此只要实现的迭代器支持 [=18],任何实现 Collection
的 class 都应该支持它=].