2

我有一个如下的类(Bean):

class KeysHolder {
   Long kitId;
   String packId;
   String boxId;

   // getters and setters
    .......
   // @Override equals and hashCode
}

我有一个包含上述对象的集合

 Set<KeysHolder> keys;

现在,如果我继续将对象添加到集合中,它是否会根据每个元素的值自动删除重复项?(我知道它在内部使用 Overridden equals 和 hashCode 方法)。

最终集合不应包含基于每个字段相等性的任何重复项。

  obja.kitId = objb.kitId
  objb.packid = objb.packId
  obja.boxId = objb.boxId

谢谢!

4

5 回答 5

7

现在,如果我继续将对象添加到集合中,它是否会根据每个元素的值自动删除重复项。

如果实现发现元素重复,则Set根本不会插入。

HashSet#add(E e)的Javadocs :

如果指定的元素尚不存在,则将其添加到此集合中。更正式地说,如果此集合不包含元素 e2,则将指定元素 e 添加到此集合中,使得(e==null ? e2==null : e.equals(e2))。如果该集合已包含该元素,则调用将保持该集合不变并返回 false。

于 2013-06-20T19:35:16.443 回答
2

Yes, any Set implementation would not allow duplicates.

But, it comes with a caveat. For a Set and other hash-based collections you need to make sure that the objects that you try to insert override their equals() as well as hashCode() method correctly.

By correct, I mean that equals() should return true for two meaningfully equivalent objects and that the hashCode() should try to return as disparate values as possible for the range of objects in your input set.

While an improper equals() implementation would most likely break your program; an inefficient hashCode() implementation would degrade your Set's performance i.e. operations like add(), contains() etc. would be as slow as bad the implementation.

于 2013-06-20T19:45:32.823 回答
2

简短的回答是肯定的,任何集合都会自行执行重复数据删除。但这只有在您遵守合同的情况下才能得到保证;并且每个Set实现的合同都有些不同:

对于 a HashSet,正如您所注意到的,您必须实现hashCode()and equals()。但这还不够:如果您在 a 中保留可变实例HashSet并修改影响hashCode()/equals()结果的属性,您仍然会遇到奇怪的情况。

另一方面,对于 a TreeSet,您需要确保您的Comparable.compareTo()orComparator.compare()方法与equals().

因此,请阅读文档Set和适合您需求的实际实现之一,并尝试遵守合同。

于 2013-06-20T19:49:03.690 回答
1

HashSet 内部使用 HashMap,此映射使用键作为要添加到集合中的值来维护,值是 Object 类的实例(final private static final Object PRESENT = new Object();)。现在,当您将相同的对象添加到此集合时,它与 map 在同一键上使用相同的 map.put 执行的操作相同,只是更新值。

但是,要更新的值仍然保持不变,即PRESENT。因此,在某种程度上,您可以说 set 不会增加相同的值。虽然实际上,内部用于实现该集合的 map 正在使用*相同的键* 和相同的值(PRESENT)更新自身。

于 2013-06-20T19:48:17.757 回答
0

我写了一个例子来说明如何在类中基于一个字段的集合中删除重复的员工条目,这里name

public class Employee {
    private String id;
    private String name;
    private String age;
    public Employee(String i, String n, String a) {
        id = i; name = n; age = a;
    }
    @Override
    public boolean equals(Object obj) {
        if (obj == this) { 
            return true; 
        } 

        if (!(obj instanceof Employee)) { 
            return false; 
        }

        Employee e = (Employee) obj;

        return name.equals(e.name); 
    }
    @Override
    public int hashCode() {
        return name.hashCode();
    }
    @Override
    public String toString() {
        return id + " " + name + " " + age;
    }
    public static void main(String[] args) {
        Employee e1 = new Employee("1", "abc", "10");
        Employee e2 = new Employee("2", "def", "20");
        Employee e3 = new Employee("3", "abc", "30");
        HashSet<Employee> empSet = new HashSet<>();
        empSet.add(e1);
        empSet.add(e2);
        empSet.add(e3);
        System.out.println(empSet.toString());
    }
}

我需要做的就是覆盖方法hashCodeequalsEmployee 类。它打印:

[1 abc 10, 2 def 20] 
于 2018-10-19T09:00:28.170 回答