users@jsr311.java.net

Re: Case insensitive map

From: Marc Hadley <Marc.Hadley_at_Sun.COM>
Date: Tue, 02 Sep 2008 11:54:22 -0400

Given the lack of time and the unlikelihood that the status quo will
cause any real problems I think we should leave this unspecified for
now and tighten things up in the next release when we'll have more
time to get it completely right.

Please create a new issue to track this.

Thanks,
Marc.

On Sep 2, 2008, at 10:20 AM, Reto Bachmann-Gmür wrote:

> Bill Burke wrote:
>> Reto Bachmann-Gmür wrote:
>>> Bill Burke wrote:
>>>> I wrote a CaseInsensitiveMap. I don't see what the problem is.
>>> 1. To which object are instances of your class equals?
>>> 2. How to you calculate the hashCode?
>>>
>> Go see for yourself:
>> http://resteasy.svn.sourceforge.net/viewvc/resteasy/trunk/jaxrs/resteasy-jaxrs/src/main/java/org/jboss/resteasy/util/CaseInsensitiveMap.java?view=markup
>> Its probably not a perfect implementation, but, IIRC, it was
>> pretty damn close. Granted, what I really wanted was a case-
>> insensitive lookup of headers, so I didn't test much beyond that,
>> but I'm confident I could make it work... Then again, I'm usually
>> overconfident.
> Your implementations seems fine, you're using the lower-case string
> for hash-computation. This would cause a different hash than when
> the same entries with keys containing upper-case letters are added
> to another Map. While this seems like the best thing to do, if we
> have to do a case-insensitive map, strictly speaking this breaks the
> definition of java.util.Map. So to me the clean solution to reduce
> the support for mixed case keys to
> HttpHeaders.getRequestHeader(name) and have the Map contain lower-
> case keys.
>>> If you do consider the case of the keys (i.e. use the keys as
>>> added) this is against the concept of case-insensitiveness. Also
>>> you would have two maps which result as different even though they
>>> answer the same value for the same set of keys. If you take the
>>> hashCode of key in specific casing you're making an arbitrary
>>> choice and it not longer workds properly across different
>>> implementations (which is why java.util.Map defines how these
>>> Methods are to be implemented).
>>>
>> Internally, you create your own CaseInsensitiveKey and your own
>> internal map based on that.
>>> java.util.Map.get(key) is defined as:
>>>> More formally, if this map contains a mapping from a key k to a
>>>> value v such that (key==null ? k==null : key.equals(k)), then
>>>> this method returns v; otherwise it returns null. (There can be
>>>> at most one such mapping.)
>>>
>>> 3. How do you implement your Map do satisfy this inherited
>>> requirement and be case-insensitive for keys?
>>>
>> What you are logically doing is two things:
>> 1) Overriding the behavior of hashCode() to be consistent in a case-
>> insensitive way
> For which you make arbitrary decision, so that your implementation
> is not only not a map according to java.util.Map but may also
> incompatible with other case-insensitive implementations.
>> 2) Overriding the behavior of String.equals().
>> In the implementation, what you have to do is write *a lot* of
>> wrapper classes to provide this logical behavior.
>>> 4. Do map.comtainsKey(k) and map.keySet().contains(k) return the
>>> same value?
>> Yes.
>>> (do you return a case-insensitive set)
>>>
>> IIRC, I do. There's probably bugs, but, I think I was on to the
>> right approach.
>
> I think your implementation is at least very close to the best one
> can do, but it's about satisfying incompatible requirements between
> jax-rs and java.util.Map.
>
> Reto
>
>

---
Marc Hadley <marc.hadley at sun.com>
CTO Office, Sun Microsystems.