【问题标题】:How to use Collections methods(removeAll() and retainAll()) for two objects如何对两个对象使用 Collections 方法(removeAll() 和 retainAll())
【发布时间】:2017-11-28 02:02:33
【问题描述】:

我预计会出现以下结果,但实际上并非如此。即使当我尝试使用字符串而不是项目对象时它也有效。 我想知道为什么会这样以及如何编码以获得预期的结果。谢谢。

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;
 }

}

【问题讨论】:

    标签: java list collections apache-commons


    【解决方案1】:

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

    你需要实现equals。

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

    【讨论】:

    • 谢谢!有效!我使用 Eclipse 的代码补充添加了 equals 方法。
    • @yusaku - 邀请您将对您有用的答案标记为已接受。 (在投票柜台下方打勾)
    • 抱歉。我对这个网站还不是很熟悉。
    • 不要忘记在覆盖 equals() 时实现 hashCode()
    • @PSIXO 如果您使用的是哈希集合,而 OP 不是。
    【解决方案2】:

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

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

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

    【讨论】:

    • 谢谢!但我不确定为什么需要 hasCode() 。在我的环境中,它在没有 hasCode() 的情况下工作。我会检查的。
    • 是的,在这种情况下它会起作用。但是如果你决定将你的对象放在一个 HashMap 中,你会遇到意想不到的行为。
    • 我明白了。谢谢你的好意。
    【解决方案3】:

    在您的项目类中实现 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;
    }
    

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

    【讨论】:

    • 为什么result的值是1(37*1永远是37)?
    • @Kwadz 这个答案是 7 岁。这些天我的 hashCode 将是一个单行:return Objects.hash(id)
    【解决方案4】:

    您需要覆盖 Item 类的 equalshashCode 方法。如果你不这样做,那么 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.
    

    如果您正确实现equals,则输出将是false,后跟true

    【讨论】:

      【解决方案5】:

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

      • 使用相同的引用
      • 从对象覆盖等于

      【讨论】:

        猜你喜欢
        • 2011-05-26
        • 1970-01-01
        • 2016-01-18
        • 2012-01-12
        • 2017-04-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-13
        相关资源
        最近更新 更多