当我们删除SET的所有元素时,为什么答案将以2:2:1:1的形式出现

时间:2015-06-04 05:05:44

标签: java collections set

当我们在Set中添加元素时,它将丢弃重复的值。当我们删除集合k1和k2的元素时。最终的大小是1.代码的答案是2:2:1:1。

class KeyMaster {
    public int i;

    public KeyMaster(int i) {
        this.i = i;
    }

    public boolean equals(Object o) {
        return i == ((KeyMaster) o).i;
    }

    public int hashCode() {
        return i;
    }
}


public class MapIt  {

    public static void main(String[] args) {
        Set<KeyMaster> set = new HashSet<KeyMaster>();
        KeyMaster k1 = new KeyMaster(1);
        KeyMaster k2 = new KeyMaster(2);
        set.add(k1);
        set.add(k1);
        set.add(k2);
        set.add(k2);

        System.out.print(set.size() + ":");
        k2.i = 1;

        System.out.print(set.size() + ":");
        set.remove(k1);

        System.out.print(set.size() + ":");
        set.remove(k2);

        System.out.print(set.size());
    }
}

2 个答案:

答案 0 :(得分:1)

这是因为HashSet中的键不是不可变的所以当您更改k2的字段值时,此字段值已更改但对象保持不变,因此当您要删除时来自集合的k2,它无法找到k2,因为您的对象已被更改。

为了更好地理解它,让k1去测试一下:

class MapIt {
    public static void main(String[] args) {
        Set<KeyMaster> set = new HashSet<KeyMaster>();
        KeyMaster k2 = new KeyMaster(2);
        set.add(k2);
        set.add(k2);

        System.out.print(set.size() + ":");
        k2.i = 3;
        System.out.print(set.size() + ":");
        set.remove(k2);

        System.out.println(set.size());
    }
}

答案 1 :(得分:1)

MapHashMap的幕后HashSet} API的界面说:

  

注意:如果将可变对象用作地图,则必须非常小心   键。如果对象的值,则不指定映射的行为   以一种影响等于比较的方式改变   对象是地图中的一个关键。

您的hashCode定义不明确,至少应该确保以下内容(来自API):

  

每当在同一个对象上多次调用它时   执行Java应用程序时,hashCode方法必须始终如一   返回相同的整数,前提是equals中没有使用的信息   对象的比较被修改。不需要保留该整数   从一个应用程序的执行到另一个执行的一致性   相同的申请。