我正在搜索Map实现,可以根据其键和比较器进行排序。
我知道TreeMap
是要走的路,但我有一个很大的问题:比较器没有明确定义(我知道这是一个错误,但我目前无法修复它)即使对于不相等的键(就equals()方法而言)也会返回0。
如果比较器返回0并且未考虑对象的hashCode或equals方法,则TreeMap实现假定对象相等(因此会覆盖值)。这是记录在案并且在大多数情况下是期望的行为。您可以通过查看TreeMap.put()方法来检查实现是否基于比较器,该方法包含以下片段:
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
此代码遍历树,如果它在树中找到一个相等的节点(使用比较器cpr
)到应该插入的节点(key
),则该值将被覆盖。
但是:我正在搜索Map接口的实现,它基于Comparator进行排序,但不会用它来检测哪些是相等的。
答案 0 :(得分:2)
我怀疑你会发现这样做的Map,因为它违反了Comparator界面的建议。
比较器c对一组元素S施加的排序被称为 当且仅当c.compare(e1,e2)== 0具有与equals 一致时 对于S中的每个e1和e2,与e1.equals(e2)相同的布尔值。
使用能够比较的比较器时应该小心 强加与equals不一致的排序以排序有序集 (或排序的地图)。假设一个带有显式的有序集(或有序映射) 比较器c与从集合S中绘制的元素(或键)一起使用 c对S施加的排序与equals,排序后的顺序不一致 set(或有序地图)将表现为“奇怪”。特别是排序 set(或有序映射)将违反set的一般合同(或 map),用等号定义。
您可以随时使用自己的比较器装饰比较器,如new MyComparator(faultyComparator);
当您删除对故障比较器的调用时,请检查其返回值。如果为0,请确保对象的equals()
合同一致。如果他们不这样做,请纠正返回值。更好的解决方案是正确地重写比较器并使用TreeMap,如果该选项是打开的。
答案 1 :(得分:0)
在您的情况下,TreeMap应该没问题。但是,听起来你并没有使用Strings或Wrapper类对象作为键。如果使用自己的类对象作为键,则必须实现hashcode()和equals()方法。
答案 2 :(得分:0)
只需实现一个永不返回0且使用常规TreeMap的Comparator。
答案 3 :(得分:0)
这是更多的内务管理,但听起来像你需要某种两级结构,TreeMap<K, LinkedHashMap<K, V>>
外部地图基于你的“错误”比较器,其值正常等于 - 知觉地图(根据比较器,它们的键都相等,但根据hashCode和equals不同)。