Java 带有未定义好的比较器的已排序映射

Java 带有未定义好的比较器的已排序映射,java,Java,我正在搜索一个Map实现,它可以根据键和比较器进行排序 我知道TreeMap是一条路要走,但我有一个巨大的问题:比较器没有很好地定义(我知道这是一个错误,但我目前无法修复),因为它返回0,即使对于不相等的键(根据equals()方法) 如果比较器返回0并且没有考虑hashCode或对象的equals方法,则TreeMap实现假定对象是相等的(因此覆盖值)。这是记录在案的,并且在大多数情况下是期望的行为。通过查看TreeMap.put()方法,可以检查实现是否基于比较器,该方法包含以下snipse

我正在搜索一个Map实现,它可以根据键和比较器进行排序

我知道
TreeMap
是一条路要走,但我有一个巨大的问题:比较器没有很好地定义(我知道这是一个错误,但我目前无法修复),因为它返回0,即使对于不相等的键(根据equals()方法)

如果比较器返回0并且没有考虑hashCode或对象的equals方法,则TreeMap实现假定对象是相等的(因此覆盖值)。这是记录在案的,并且在大多数情况下是期望的行为。通过查看TreeMap.put()方法,可以检查实现是否基于比较器,该方法包含以下snipset:

        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);
do{
父代=t;
cmp=心肺复苏比较(键,t键);
if(cmp<0)
t=t左;
否则如果(cmp>0)
t=t右;
其他的
返回t.setValue(值);
}而(t!=null);
此代码遍历树,如果它在树中发现一个节点(使用比较器
cpr
)与应插入的节点相等(
),则该值将被覆盖


但是:我正在搜索Map接口的实现,它是基于比较器排序的,但不用于检测哪些是相等的。

TreeMap在您的情况下应该可以。但是,听起来您并没有使用字符串或包装类对象作为键。如果您使用自己的类对象作为键,则必须实现hashcode()和equals()方法。

只需实现一个从不返回0的比较器,并使用常规树映射。

我怀疑您是否会找到这样做的映射,因为它违背了比较器接口的建议

比较器c对一组元素S施加的排序称为 当且仅当c.compare(e1,e2)==0 与e1相同的布尔值。S中的每个e1和e2等于(e2)

当使用能够 施加与等于不一致的顺序以对已排序集进行排序 (或已排序的地图)。假设一个带有显式 比较器c与从集合S中提取的元素(或键)一起使用。如果 c对S施加的排序与等号不一致,排序后的 集合(或已排序的映射)的行为将“奇怪地”,尤其是已排序的映射 set(或已排序地图)将违反set(或 映射),它是根据相等来定义的

您可以始终使用自己的比较器来装饰比较器,如so
newmycomparator(faultyComparator)


当您删除对故障比较器的调用时,请检查其返回值。如果为0,请确保对象的
equals()
契约一致。如果没有,请更正返回值。更好的解决方案是正确重写比较器并使用树映射(如果该选项是打开的)。

这会更加内务化,但在我看来,您需要某种两级结构,
TreeMap
,其中外部映射基于您的“错误”比较器,其值是正常的(根据比较器,它们的键都是相等的,但根据hashCode和equals不同)。

您是否将一些类或java类放入映射中?对于键和值:据我所知,映射是由集合实现的,而对象是否在集合中则由hashCode()决定对象本身,而不是比较器中的相等值,那么为什么TreeMap不起作用呢?请参见我上面的编辑,它不是基于
集合
@Miloš
映射
(接口)不是以任何特定的方式实现的,它只是描述功能。
java.util.TreeMap
实现则使用比较器来确定对象相等性,正如其Javadocs所描述的那样。theomega是对的,如果他的比较器与equals.My equals和hashcode imp不一致,他就不能使用TreeMap元件是正确的,问题是比较器不正确,我(如上所述)无法更改。为什么您需要担心Comparator?您是否在自己的程序中与TreeMap一起使用任何Comparator?是的,我使用的自定义Comparator实现不正确。如果您对Comparator进行类扩展,则可以使用compareTo()比较对象现在,如果equals方法实现包含使用compareTo()检查两个对象,这不应该工作吗?但是您需要小心,因为compareTo有三个不同的输出(-1,0,+1)包装比较器的解决方案很好,我希望不要被迫使用它…包装比较器的困难部分是确保
ab>a
对所有对都一致,即使原始比较器认为它们相等。你不能简单地让它总是返回-1或+1,因为这会破坏树映射。不幸的是如果你不能修改
比较器本身,那么你的选择是有限的。@IanRoberts所指的也是正确的。我的decorator解决方案假设你有足够的信息对a>b做出明智的决定,反之亦然。任意返回-1/+1是行不通的。如果包装好的比较器r返回0?