Java TreeMap(比较器)和get方法忽略了比较器

d0p*_*0pe 8 java treemap comparator

public final Comparator<String> ID_IGN_CASE_COMP = new Comparator<String>() {

        public int compare(String s1, String s2) {
            return s1.compareToIgnoreCase(s2);
        }
    };

private Map< String, Animal > _animals = new TreeMap< String, Animal >(ID_IGN_CASE_COMP);
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何使用方法get(id)忽略给定的比较器.我希望地图按Case Insensitive排序,但是,当我通过给定键获取值时,我希望它区分大小写.

PSp*_*eed 8

我认为答案很简单.实现自己的比较,做一个不区分大小写的排序,但确实为"A"和"A" ...太对它们进行排序返回0.

问题是你的比较器为比较("A","a")情况返回0,这意味着就地图而言它是相同的密钥.

使用比较器,如:

public final Comparator<String> ID_IGN_CASE_COMP = new Comparator<String>() {

    public int compare(String s1, String s2) {
        int result = s1.compareToIgnoreCase(s2);
        if( result == 0 )
            result = s1.compareTo(s2);
        return result;
    }
};
Run Code Online (Sandbox Code Playgroud)

然后,无论大小写如何,所有键都将进入,"a"和"A"仍将一起排序.

换句话说,get("a")将为您提供与get("A")不同的值...并且它们都将显示在keySet()迭代器中.它们将被整理在一起.


Buh*_*uhb 7

在TreeMap中,添加两个键a和b(按此顺序)以使compare(a,b)返回0将导致最新添加的条目(b)将覆盖第一个(a).

在您的情况下,这意味着对于不区分大小写的get(id)将永远不会有任何用处.

引用http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html

请注意,如果此有序映射要正确实现Map接口,则由有序映射维护的排序(无论是否提供显式比较器)必须与equals一致.(请参阅Comparable或Comparator以获得与equals一致的精确定义.)这是因为Map接口是根据equals操作定义的,但是map使用compareTo(或compare)方法执行所有键比较,因此有两个键从排序地图的角度来看,通过这种方法被视为相等的是相等的.即使排序与equals不一致,也可以很好地定义有序映射的行为.它只是不遵守Map接口的一般合同.

这可能不是你想要的.

如果地图相对较小并且您不需要多次获取已排序的条目,则解决方案是使用HashMap(或TreeMap而不显式设置比较器),并在需要时对条目不敏感地对条目进行排序订购.