Java - 删除另一个集合中的集合中的对象,具有" equals"的任意含义。

时间:2015-05-21 23:35:06

标签: java collections equals

如果我只想基于绝对平等,这很容易。我只是这样做:

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.我错过了什么聪明的解决方案?

2 个答案:

答案 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())));

方便地removeIfCollection接口的默认成员,因此只要实现的迭代器支持Collection,任何实现remove的类都应该支持它。

答案 1 :(得分:0)

您可以使用apache commons类来执行此操作。好例子是here

Another link