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);
我的问题是,如何使用方法get(id)忽略给定的比较器。我希望地图按Case Insensitive排序,但是,当我按给定键获取值时,我希望它区分大小写。
答案 0 :(得分:8)
我认为答案很简单。实现你自己的比较器,它做一个不区分大小写的排序,但 NOT 为“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;
}
};
然后所有的密钥都会进入,无论大小写如何,“a”和“A”仍然会被整理在一起。
换句话说,get(“a”)将为您提供与get(“A”)不同的值...并且它们都将显示在keySet()迭代器中。它们将被整理在一起。
答案 1 :(得分:6)
在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而不显式设置比较器),并在不区分大小写的情况下对条目进行排序。你需要他们订购。
答案 2 :(得分:1)
你必须使用两个独立的TreeMaps,内容相同但比较器不同。
答案 3 :(得分:1)
也许它会完成这项工作:
new Comparator<String>(){
public int compare(String s1, String s2)
{
String s1n = s1.toLowerCase();
String s2n = s2.toLowerCase();
if(s1n.equals(s2n))
{
return s1.compareTo(s2);
}
return s1n.compareTo(s2n);
}
};
}
答案 4 :(得分:1)
您需要一个多图:此多图的每个条目都会保留不区分大小写键,另一个图标以原始键作为值。
有许多可自由使用的多重映射实现,例如Common Collections,Google Collections等
答案 5 :(得分:0)
除了所有其他答案并同意之外,不可能有一个具有不同比较器的TreeMap结构:
根据您的问题,我了解您有两个要求:数据模型应区分大小写(使用get()
时需要区分大小写的值),演示者不区分大小写(您希望区分大小写)订购,演示只是一个假设。)
让我们假设,我们使用映射(aa,obj1),(aA,obj2),(aa,obj3),(AA,obj4)填充Map。迭代器将按以下顺序提供值:(obj4,obj3,obj2,obj1)(*)。如果地图被排序为不区分大小,那么您现在期望哪个订单?所有四个键都相等,顺序未定义。或者您正在寻找一个解决方案,解决关键'AA'的集合{obj1,obj2,obj3,obj4}?但这是一种不同的方法。
SO鼓励社区诚实:因此,我的建议是再次查看您的要求:)
(*)未经测试,假设'A'&lt; 'a'= true。
答案 6 :(得分:-1)
在循环中使用floorEntry然后higherEntry来查找不区分大小写的条目;当你找到确切的钥匙匹配时停止。