2
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()

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

4

2 回答 2

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

于 2013-10-30T12:40:53.800 回答
-1

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

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

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

如果您使用然后创建包装器对象,new keyword那么它只会进入堆内存,否则它将保存在常量池中。

于 2013-10-30T12:56:04.090 回答