Java TreeMap(比较器)和忽略比较器的get方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1782674/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java TreeMap (comparator) and get method ignoring the comparator
提问by d0pe
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);
My problem is, how to use method get(id) ignoring the given comparator. I want the map to be order by Case Insensitive but, I want it to be case sensitive when I fetch the values by a given key.
我的问题是,如何使用方法 get(id) 忽略给定的比较器。我希望地图按不区分大小写的顺序排序,但是,当我通过给定的键获取值时,我希望它区分大小写。
采纳答案by PSpeed
I think the answer is easy. Implement your own comparator that does a case insensitive sort but does NOTreturn 0 for "A" and "a"... sort them too.
我认为答案很简单。实现自己的比较,做一个不区分大小写的排序,但确实不为“A”和“A” ......排序他们也返回0。
The issue is that your comparator returns 0 for the compare( "A", "a" ) case which means it is the same key as far as the map is concerned.
问题是您的比较器在 compare( "A", "a" ) 情况下返回 0,这意味着就地图而言,它是相同的键。
Use a comparator like:
使用比较器,如:
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;
}
};
Then all keys will go in regardless of case and "a" and "A" will still be sorted together.
然后,无论大小写,所有键都将进入,并且“a”和“A”仍将一起排序。
In other words, get("a") will give you a different value from get("A")... and they will both show up in keySet() iterators. They will just be sorted together.
换句话说, get("a") 会给你一个与 get("A") 不同的值......它们都会出现在 keySet() 迭代器中。它们只会被排序在一起。
回答by Buhb
In a TreeMap, adding two keys a and b (in that order) so that compare(a, b) returns 0 will result in that the latest added entry (b) will overwrite the first one (a).
在 TreeMap 中,添加两个键 a 和 b(按该顺序)以便 compare(a, b) 返回 0 将导致最新添加的条目 (b) 将覆盖第一个 (a)。
In your case, this means that there will never be any use for case insensitive get(id).
在您的情况下,这意味着不区分大小写的 get(id) 永远不会有任何用处。
quoting http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html
引用http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html
Note that the ordering maintained by a sorted map (whether or not an explicit comparator is provided) must be consistent with equals if this sorted map is to correctly implement the Map interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Map interface is defined in terms of the equals operation, but a map performs all key comparisons using its compareTo (or compare) method, so two keys that are deemed equal by this method are, from the standpoint of the sorted map, equal. The behavior of a sorted map is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Map interface.
请注意,如果排序映射要正确实现 Map 接口,则排序映射维护的排序(无论是否提供显式比较器)必须与 equals 一致。(请参阅 Comparable 或 Comparator 以获得与等于一致的精确定义。)这是因为 Map 接口是根据等于操作定义的,但映射使用其 compareTo(或比较)方法执行所有键比较,因此两个键从排序映射的角度来看,被这种方法视为相等的对象是相等的。排序映射的行为是明确定义的,即使它的排序与 equals 不一致;它只是不遵守 Map 接口的一般约定。
This is probably not what you want.
这可能不是您想要的。
If the map is comparably small and you don't need to fetch the sorted entries very many times, a solution is to use a HashMap (or a TreeMap without explicitly setting the comparator), and sort the entries case-insensitively when you need them ordered.
如果地图相对较小并且您不需要多次获取已排序的条目,则解决方案是使用 HashMap(或未显式设置比较器的 TreeMap),并在需要时对条目进行不区分大小写的排序下令。
回答by dfa
you need a multimap: each entry of this multimap keeps the case insensitivekeys and aanother map with the original keys as value.
你需要一个multimap:这个 multimap 的每个条目都保留不区分大小写的键和一个以原始键作为值的另一个映射。
There are many freely usable implementations of multimaps such as Common Collections, Google Collections, etc
有许多可免费使用的多重映射实现,例如Common Collections、Google Collections等
回答by Tom Bartel
You'll have to use two separate TreeMaps for that, with the same contents but different comparators.
为此,您必须使用两个单独的 TreeMap,它们具有相同的内容但比较器不同。
回答by Mirek Pluta
maybe it'll do the job:
也许它可以完成这项工作:
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);
}
};
}
回答by Andreas Dolk
In addition to all the other answers and agreeing, that it is impossible to have a single TreeMap structure with different comparators:
除了所有其他答案并同意之外,不可能有具有不同比较器的单个 TreeMap 结构:
From your question I understand that you have two requirements: the data model shall be case sensitive (you want the case sensitive values when you use get()), the presenter shall be case insensitive (you want an case sensitive ordering, presentation is just an assumption).
从您的问题我了解到您有两个要求:数据模型应区分大小写(您在使用时需要区分大小写的值get()),演示者应不区分大小写(您需要区分大小写的排序,演示文稿只是一个假设) .
Let's assume, we populate the Map with the mappings (aa,obj1), (aA,obj2), (Aa,obj3), (AA,obj4). The iterator will provides the values in the order: (obj4, obj3, obj2, obj1)(*). Now which order do you expect if the map was ordered case-insensitive? All four keys would be equal and the order undefined. Or are you looking for a solution that would resolve the collection {obj1, obj2, obj3, obj4} for the key 'AA'? But that's a different approach.
让我们假设,我们用映射 (aa,obj1)、(aA,obj2)、(Aa,obj3)、(AA,obj4) 填充 Map。迭代器将按以下顺序提供值:(obj4, obj3, obj2, obj1)(*)。现在,如果地图的排序不区分大小写,您期望哪个顺序?所有四个键都相等并且顺序未定义。或者您是否正在寻找一种解决方案来解析密钥“AA”的集合 {obj1, obj2, obj3, obj4}?但这是一种不同的方法。
SO encourages the community to be honest: therefore my advice at this point is to look at your requirement again :)
SO 鼓励社区诚实:因此我此时的建议是再次查看您的要求:)
(*) not tested, assumed that 'A' < 'a' = true.
(*) 未测试,假设 'A' < 'a' = true。
回答by Andrew Duffy
Use floorEntryand then higherEntryin a loop to find the entries case-insensitively; stop when you find the exact key match.
使用floorEntry然后higherEntry在循环中找到的条目不区分大小写; 当您找到完全匹配的键时停止。

