-
Bug
-
Resolution: Unresolved
-
P4
-
6, 9
-
Cause Known
FULL PRODUCT VERSION :
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
None - is a plain java bug
A DESCRIPTION OF THE PROBLEM :
I think I found a Bug in the IdentityHashMap collection: The removeAll Method removes Object by equality not by there Sytem.identityHashCode. Here is the code from the class: (line 411)
public boolean removeAll(Collection<?> c) {
boolean modified = false;
for (Iterator i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
}
}
return modified;
}
As you can see, the hashMap delegates to c.contains() which can be any collection. IMHO it must be:
@Override
public boolean removeAll(Collection<?> c) {
boolean modified = false;
for (Iterator i = c.iterator(); i.hasNext(); ) {
Object object = i.next();
if (PIdentityHashMap.this.containsKey(object)) {
PIdentityHashMap.this.remove(object);
modified = true;
}
}
return modified;
}
We iterate over the collection and not the entries of the map. Here is a little TestCase:
public void test_show_identityHashMap_Bug() {
List<WrongHashCode> removed = new ArrayList<WrongHashCode>();
removed.add(new WrongHashCode("1"));
IdentityHashMap<WrongHashCode, String> hashMap = new IdentityHashMap<WrongHashCode, String>();
hashMap.put(new WrongHashCode("2"), "");
assertFalse(hashMap.keySet().removeAll(removed));
assertEquals(1, hashMap.size());
}
The class WrongHashCode defines hashCode and equals in the following (wrong (-: ) way:
@Override
public int hashCode() {
return 0;
}
@Override
public boolean equals(Object object) {
return true;
}
I patched the class, so I can work on my software.
REPRODUCIBILITY :
This bug can be reproduced always.
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
None - is a plain java bug
A DESCRIPTION OF THE PROBLEM :
I think I found a Bug in the IdentityHashMap collection: The removeAll Method removes Object by equality not by there Sytem.identityHashCode. Here is the code from the class: (line 411)
public boolean removeAll(Collection<?> c) {
boolean modified = false;
for (Iterator i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
}
}
return modified;
}
As you can see, the hashMap delegates to c.contains() which can be any collection. IMHO it must be:
@Override
public boolean removeAll(Collection<?> c) {
boolean modified = false;
for (Iterator i = c.iterator(); i.hasNext(); ) {
Object object = i.next();
if (PIdentityHashMap.this.containsKey(object)) {
PIdentityHashMap.this.remove(object);
modified = true;
}
}
return modified;
}
We iterate over the collection and not the entries of the map. Here is a little TestCase:
public void test_show_identityHashMap_Bug() {
List<WrongHashCode> removed = new ArrayList<WrongHashCode>();
removed.add(new WrongHashCode("1"));
IdentityHashMap<WrongHashCode, String> hashMap = new IdentityHashMap<WrongHashCode, String>();
hashMap.put(new WrongHashCode("2"), "");
assertFalse(hashMap.keySet().removeAll(removed));
assertEquals(1, hashMap.size());
}
The class WrongHashCode defines hashCode and equals in the following (wrong (-: ) way:
@Override
public int hashCode() {
return 0;
}
@Override
public boolean equals(Object object) {
return true;
}
I patched the class, so I can work on my software.
REPRODUCIBILITY :
This bug can be reproduced always.
- relates to
-
JDK-6394757 (coll) AbstractSet.removeAll semantics are surprisingly dependent on relative sizes
- Open