Java树映射:不同的对象在“之后”;把“放”进去;?

Java树映射:不同的对象在“之后”;把“放”进去;?,java,equals,comparator,hashcode,treemap,Java,Equals,Comparator,Hashcode,Treemap,我使用一个从TreeMap派生的类和我自己的比较器作为LinkedHashMap中的键。使用这种结构,我发现了一些我无法解释的奇怪行为。也许你们中的一个能帮上忙。我试图用原语重现我的问题。当我创建一个基元类型的树映射时,自然排序应该足够了,并且不需要在树映射的构造函数中使用比较器,对吧 以下是MWE: package treemapputtest; import java.util.LinkedHashMap; import java.util.Map; import java.util.Tr

我使用一个从TreeMap派生的类和我自己的比较器作为LinkedHashMap中的键。使用这种结构,我发现了一些我无法解释的奇怪行为。也许你们中的一个能帮上忙。我试图用原语重现我的问题。当我创建一个基元类型的树映射时,自然排序应该足够了,并且不需要在树映射的构造函数中使用比较器,对吧

以下是MWE:

package treemapputtest;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;

public class TreeMapPutTest {

    public static void main(String[] args) {

        System.out.println("simple:");
        simpleTest();

        System.out.println("\n\ncomplex:");
        complexTest();
    }

    private static void simpleTest(){

        TreeMap<Integer,String> map = new TreeMap<>();

        System.out.println("map: " + map.hashCode() + " | " + Integer.toHexString(map.hashCode()));

        map.put(1, "a");

        System.out.println("map: " + map.hashCode() + " | " + Integer.toHexString(map.hashCode()));

        map.put(2, "b");

        System.out.println("map: " + map.hashCode() + " | " + Integer.toHexString(map.hashCode()));

    }

    private static void complexTest(){

        TreeMap<Integer,String> internalMap = new TreeMap<>();
        internalMap.put(1, "a");
        internalMap.put(2, "b");

        System.out.println("prior: " + internalMap.hashCode() + " | " + Integer.toHexString(internalMap.hashCode()));

        LinkedHashMap<TreeMap<Integer,String>,Double> myMap = new LinkedHashMap<>();
        myMap.put(internalMap, 1.0);

        doSomethingWithMyInternalMap(myMap.keySet().iterator().next());

        System.out.println("after:");
        for (Map.Entry<TreeMap<Integer,String>,Double> entry : myMap.entrySet()){
            System.out.println("  " + Integer.toHexString(entry.getKey().hashCode()));
        }

    }

    private static void doSomethingWithMyInternalMap(TreeMap<Integer,String> intern){
        intern.put(3, "c");
    }
}
所以我的问题是:
hashCode()?仅对于树映射而言,这并不是什么大问题,但由于这会创建一个“新对象”/对旧对象的引用被更改,因此在LinkedHashMap中更新树映射后会出现错误

hashCode()的值为:

hashCode的一般约定是:在Java应用程序的执行过程中,每当在同一对象上多次调用hashCode时,hashCode方法必须一致地返回相同的整数,前提是不修改对象上的equals比较中使用的信息


在TreeMap中添加额外的内容会改变TreeMap的equals()方法吗?我是否必须以某种方式重写
equals()
hashCode()

我想你对这里的
hashCode
有误解。让我们强调你在这里引用的文本中的要点:

hashCode的一般约定是:在Java应用程序的执行过程中,每当在同一对象上多次调用hashCode时,hashCode方法必须一致地返回相同的整数,,前提是不修改对象的equals比较中使用的信息

无论何时在地图中添加(或删除)数据,都是在更改其
equals
方法中使用的信息-空地图不等于包含
[1->a]
的地图,包含
[1->a]
的地图不等于包含
[1->a;2->b]
的地图


这与创建新对象无关,对旧贴图的引用不会改变。如果调用而不是,则无论调用多少次
put
,对象引用都不会更改。

我认为您对这里的
hashCode
有误解。让我们强调你在这里引用的文本中的要点:

hashCode的一般约定是:在Java应用程序的执行过程中,每当在同一对象上多次调用hashCode时,hashCode方法必须一致地返回相同的整数,,前提是不修改对象的equals比较中使用的信息

无论何时在地图中添加(或删除)数据,都是在更改其
equals
方法中使用的信息-空地图不等于包含
[1->a]
的地图,包含
[1->a]
的地图不等于包含
[1->a;2->b]
的地图

这与创建新对象无关,对旧贴图的引用不会改变。如果调用而不是,则无论调用多少次
put
,对象引用都不会更改

在TreeMap中添加额外的内容会改变TreeMap的equals()方法吗

是的,当然,因为对于地图来说

将指定对象与此映射进行相等性比较。如果给定对象也是一个映射并且两个映射表示相同的映射,则返回true。更正式地说,如果m1.entrySet()等于(m2.entrySet()),则两个映射m1和m2表示相同的映射

因此,映射的每个条目都用于检查相等性,因此也用于计算哈希代码。并添加一个条目,从而修改哈希代码

您希望hashCode是对象的某种不可变标识符。不是。一点也不

在TreeMap中添加额外的内容会改变TreeMap的equals()方法吗

是的,当然,因为对于地图来说

将指定对象与此映射进行相等性比较。如果给定对象也是一个映射并且两个映射表示相同的映射,则返回true。更正式地说,如果m1.entrySet()等于(m2.entrySet()),则两个映射m1和m2表示相同的映射

因此,映射的每个条目都用于检查相等性,因此也用于计算哈希代码。并添加一个条目,从而修改哈希代码

您希望hashCode是对象的某种不可变标识符。不是。一点也不

在TreeMap中添加额外的内容会改变TreeMap的equals()方法吗?我是否必须以某种方式重写equals()和hashCode()

为什么不呢?新的
TreeMap
为空。因此,根据您的推理,如果它的
equals()
hashCode()
方法没有根据
TreeMap
的内容进行调整,那么
TreeMap
的所有实例(从空开始)都将具有相同的hashCode,因为它将是在创建时计算的相同实例,其中没有任何条目,不管后面添加了什么

大多数集合的
equals()
hashCode()
函数根据其内容进行调整。这样,可以将元素的
列表
与元素的
列表
的另一个实例进行比较,如果它们包含相同的元素(在
列表
的情况下,顺序相同),则
equals()
将返回true。类似地,对于
Map
而言,内部
equals()
实现确保检查该
Map
实现被视为等效的内容

在TreeMap中添加额外的内容会改变TreeMap的equals()方法吗?我是否必须以某种方式重写equals()和hashCode()

为什么不呢?一个新的
TreeMap
是em
simple:
map: 0 | 0
map: 96 | 60
map: 192 | c0

complex:
prior: 192 | c0
after:
  120