java 如何为两个对象使用集合方法(removeAll() 和 retainAll())

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4461459/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 06:29:34  来源:igfitidea点击:

How to use Collections methods(removeAll() and retainAll()) for two objects

javalistcollectionsapache-commons

提问by zono

I expected to result below but actually not. Even though it worked when I tried to use String instead of Item Object. I would like to know why the reasons about that and how to code in order to get expected result.Thanks.

我希望结果低于但实际上不是。即使当我尝试使用 String 而不是 Item Object 时它也有效。我想知道为什么会这样,以及如何编码以获得预期的结果。谢谢。

EXPECTED
------------------------------
removed object are:
2
same object are:
1
3
add object are:
4
------------------------------


ACTUAL
------------------------------
removed object are:
1
2
3
same object are:
add object are:
1
3
4
------------------------------


package com.javastudy;

import java.util.ArrayList;
import java.util.List;

public class CollectionCompareToObjects {

 public static void main(String[] args) {

  List<Item> before = new ArrayList<Item>();
  List<Item> after = new ArrayList<Item>();

  before.add(new Item(1L));
  before.add(new Item(2L)); // delete
  before.add(new Item(3L));

  after.add(new Item(1L));
  after.add(new Item(3L));
  after.add(new Item(4L)); // added

  List<Item> removed = new ArrayList<Item>(before);
  removed.removeAll(after);

  System.out.println("removed objects are:");
  for(Item item : removed){
   System.out.println(item.getId());
  }

  List<Item> same = new ArrayList<Item>(before);
  same.retainAll(after);

  System.out.println("same objects are:");
  for(Item item : same){
   System.out.println(item.getId());
  }

  List<Item> added = new ArrayList<Item>(after);
  added.removeAll(before);

  System.out.println("add objects are:");
  for(Item item : added){
   System.out.println(item.getId());
  }

 }

}

package com.javastudy;

public class Item {

 Long id;

 public Item(Long id) {
  this.id = id;
 }

 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

}

回答by Peter Lawrey

You haven't implemented equals() so ALL your Items are different objects some happen to have a field which is the same.

你还没有实现 equals() 所以你所有的项目都是不同的对象,有些碰巧有一个相同的字段。

You need to implement equals.

你需要实现equals。

I also suggest you use long instead of Long, unless you want id = null.

我还建议您使用 long 而不是 Long,除非您想要 id = null。

回答by Bozho

You have to override the equals(..)method of your Itemand compare the id field (basically, the equals method should simply do return id.equals(other.getId()), with the appropriate null-checks.

您必须覆盖您的equals(..)方法Item并比较 id 字段(基本上,equals 方法应该简单地执行return id.equals(other.getId()),并进行适当的空检查。

With equals comes and hashCode()- the two methods must always be implemented together, with the same fields.

使用 equals 和hashCode()- 这两种方法必须始终一起实现,具有相同的字段。

And you need to override these methods, because the removeAlland retainAllmethods work by iterating the collections and comparing the existing items with the items from the passed collection via equals(..)

并且您需要覆盖这些方法,因为removeAllretainAll方法通过迭代集合并将现有项目与传递的集合中的项目进行比较来工作equals(..)

回答by Sean Patrick Floyd

implement equals()and hashCode()in your item class, e.g. like this:

在您的项目类中实现equals()hashCode(),例如:

@Override
public int hashCode(){
    return Objects.hash(id);
}

@Override
public boolean equals(Object obj){
    if(this == obj) return true;
    else if(obj instanceOf Item){ // implicit null check
        Item other = (Item) obj;
        return Objects.equals(this.id, other.id);
    }
    else return false;
}

I'm guessing it will work as expected after that.

我猜在那之后它会按预期工作。

回答by Cameron Skinner

You need to override the equalsand hashCodemethods of your Itemclass. If you don't then Java uses a default implementation of equalswhich is equivalent to ==:

您需要覆盖类的equalshashCode方法Item。如果不这样做,则 Java 使用equals等效于的默认实现==

Item first = new Item(1);
Item second = new Item(1);
System.out.println(first == second); // Prints false, as expected: they are different objects.
System.out.println(first.equals(second)); // Prints false because of the default equals method.

If you implement equalscorrectly then the output will be falsefollowed by true.

如果您equals正确实施,则输出后将falsetrue.

回答by fego

When you instantiate twice an Item even with the same parameter, you will have 2 differents objects. Two solutions :

即使使用相同的参数将 Item 实例化两次,您也会有 2 个不同的对象。两种解决方案:

  • use the same reference
  • override equals from Object
  • 使用相同的参考
  • 覆盖等于对象