为什么IdentityHashMap.keySet()。removeAll(keys)不使用标识?这是一个错误吗?

时间:2013-10-30 12:40:54

标签: java identity removeall

public static void main(String[] args) {
    IdentityHashMap<Integer, Object> m1 = new IdentityHashMap<Integer, Object>();
    Integer ONE = 1;
    Integer TWO = 2;
    Integer OTHER_ONE = new Integer(1);
    Integer OTHER_TWO = new Integer(2);
    m1.put(ONE, new Object());
    m1.put(TWO, new Object());
    System.out.println(m1.keySet()); // [1, 2]

    m1.remove(OTHER_ONE); // Does not remove
    System.out.println(m1.keySet()); // [1, 2]

    m1.remove(ONE); // Does remove
    System.out.println(m1.keySet()); // [2]

    m1.keySet().removeAll(Arrays.asList(OTHER_TWO)); // ...
    System.out.println(m1.keySet()); // [] WHAT?
}

此处参考IdentityHashMap.keySet()

我在源代码中找到了答案(见下文),但我不知道最终的原因。这是一个错误吗?

2 个答案:

答案 0 :(得分:1)

我在java 1.7.0_11

中找到了这个源代码
    public boolean removeAll(Collection<?> c) {
        boolean modified = false;
        for (Iterator<K> i = iterator(); i.hasNext(); ) {
            if (c.contains(i.next())) {
                i.remove();
                modified = true;
            }
        }
        return modified;
    }

它正在使用c.contains(),因此行为取决于集合类。我从javadoc中无法理解。

我发现这是6年前报道的一个错误,但仍未解决! http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6588783

答案 1 :(得分:-1)

试试这个。它将说明发生了什么。

  System.out.println(OTHER_ONE == ONE);
  System.out.println(Arrays.asList(OTHER_ONE).contains( ONE));

OTHER_ONE是堆内存中的对象。 ONE不是对象,因此它驻留在常量池内存中。

如果使用new keyword创建包装器对象,则只会将其转到堆内存,否则它将保存在常量池中。