作者:LucifinilC_925 | 来源:互联网 | 2023-06-16 18:52
之前看到过这样一个问题,大概是:能否把一个对象(自定义,没有任何方法)的两个实例同时存放到同一个Set中去? 当时很懵,但是这几天偶然看了Set和Map的源码就比较明了了。这里总结一
之前看到过这样一个问题,大概是:能否把一个对象(自定义,没有任何方法)的两个实例同时存放到同一个Set中去?
当时很懵,但是这几天偶然看了Set和Map的源码就比较明了了。这里总结一下。
首先,大体上为了存储,有通过树来存数据的,也有通过散列(hash)来存数据的,而且Set的实现其实就是维护了一个对应的Map(如HashSet就是构造一个HashMap),Set的值就是Map的键。所以这里只讨论TreeMap和HashMap。
TreeMap实现put和get
TreeMap主要是通过红黑树实现的。这里要求Key是实现了Comparable接口的。所以在TreeMap内部,就是通过compare方法来判断是否放入的键相同。以及你通过get获取元素时,也是通过compare方法来查找的。所以同一个对象的多个实例是否能同时存入Map/Set,就要看你如何定义compare方法了。
HashMap实现put和get
HashMap以及其优化类,都是通过计算散列值来查找的。大概方式是,所有的key会算出一个hashcode,根据这个hashcode得到在容器内部的槽位(这里注意hashcode不要求唯一,因为即使有多个key在同一个槽位,也可以通过一个线性查找来获得最后结果),然后如果有put或者get方法,不外乎就是通过equals方法来看这个槽位中的其他key和要进行操作的是否相等,如果相等说明已经存在,对于put,则无法插入,对于get,则会进一步返回这个key的value。
所以你会发现,当一个HashMap(或者HashSet)中的Key是一个对象时,那么主要看这个对象对于hashcode和equals方法的重写了。一般的,如果没有重写,直接继承Objec类的方法,那么hashcode是取得地址,equals方法是比较地址值。所以自然对于最开始的问题,是可以把两个实例放到同一个set中去的,因为他们有不同的地址,当然当你重写了hashcode和equals方法就不一定了(事实上,如果你需要用到自定义的类做Key或者放到Set中去,你需要注意是否需要重写hashcode和equals方法)。