JDK-5018254 : (coll) 'remove' operation fails in tailMap of a null-key-allowing TreeMap
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util:collections
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2004-03-23
  • Updated: 2012-10-08
  • Resolved: 2005-09-04
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
JDK 6
6 b51Fixed
Description
Name: gm110360			Date: 03/22/2004


FULL PRODUCT VERSION :
java version "1.4.2-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-beta-b19)
Java HotSpot(TM) Client VM (build 1.4.2-beta-b19, mixed mode)

FULL OS VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
I created a TreeMap that allows null keys.  The comparator puts the null key at the end of the map and uses natural ordering for all other keys.  If I create a new map with the 'tailMap' method, the 'remove' operation doesn't work properly with the new map.  When passing null to 'remove', the return value is always null instead of the associated value.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a Comparator that allows null keys
2. Create a TreeMap with the above comparator.
3. Add some key-value pairs to the map.  One key should be null with a non-null value.
4. Get a tailMap of the original Map.
5. Call 'remove(null)' on the tail map.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The 'remove' call should return the value originally associated with 'null.
ACTUAL -
The 'remove' call always returns null.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.*;

public class Test {
	private static final Comparator NULL_AT_END = new Comparator() {
		/**
		 * Allows for nulls.  Null is greater than anything non-null.
		 */
		public int compare(Object pObj1, Object pObj2) {
			if (pObj1 == null && pObj2 == null) return 0;
			if (pObj1 == null && pObj2 != null) return 1;
			if (pObj1 != null && pObj2 == null) return -1;
			return ((Comparable) pObj1).compareTo(pObj2);
		}
	};


	public static void main(String[] pArgs) {
		SortedMap m1 = new TreeMap(NULL_AT_END);
		m1.put("a", "a");
		m1.put("b", "b");
		m1.put("c", "c");
		m1.put(null, "d");

		SortedMap m2 = new TreeMap(m1);

		System.out.println(m1.lastKey());
		System.out.println(m1.get(m1.lastKey()));
		System.out.println(m1.remove(m1.lastKey())); // should (and does) output 'd'

		m2 = m2.tailMap("b");

		System.out.println(m2.lastKey());
		System.out.println(m2.get(m2.lastKey()));
		System.out.println(m2.remove(m2.lastKey())); // should output 'd' but outputs 'null'
	}
}
---------- END SOURCE ----------
(Incident Review ID: 192542) 
======================================================================

Comments
EVALUATION The reporter is correct; this is a bug. ###@###.### 2004-03-23 Will be fixed as part of JSR166 maintenance. ###@###.### 2005-03-09 03:07:15 GMT
2004-03-23