如果我只想基于绝对平等,这很容易。我只是这样做:
collectionA.removeAll(collectionB).
但是,我们说我有这个对象:
class Item {
private String color;
private String name;
private String type;
}
还有两个系列......
List<Item> items1, List<item> items2.
...但我只想删除item1中与item2中具有相同名称和类型的所有内容。
请注意,我不能为此类创建子类或定义equals,hashcode。
我希望这与现有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.我错过了什么聪明的解决方案?
答案 0 :(得分:3)
你提到它是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
接口的默认成员,因此只要实现的迭代器支持Collection
,任何实现remove
的类都应该支持它。
答案 1 :(得分:0)
您可以使用apache commons类来执行此操作。好例子是here