HashSet容器
来源:互联网 发布:编程语言能用中文 编辑:程序博客网 时间:2024/06/16 04:04
关于HashSet 传入对象,怎么过滤
HashSet底层的数据结构用的是HashMap,使用Map的key存值,Value存放一个固定的Object,这是适配器模式。
如果传入的是两个对象,我们通过怎样的机制来判断他们是不是相等的,旧的会不会替换新的对象,以及怎么替换或者不替换呐?
是不是相等的?
//若存在相同,则直接覆盖value,返回旧value if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; //旧值 = 新值 e.value = value; e.recordAccess(this); return oldValue; //返回旧值 }
这是代码的判断语句,可以看出,这里用hash和equals都比较了,需要俩个都返回true才可以
需要说明的是hash
并不等同hashCode
方法,而是根据hashCode
计算出来的,二者结果线性相关.
//求hash值的方法,重新计算hash值 static int hash(int h) { h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); }
如果我们没有实现hashCode
或者equals
,二者都会调用Object
上的方法,Object
上hashCode
方法是一个本地方法,返回的值应该是对象在内存中地址,而equals
方法内是通过==
判断地址是否一致.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
所以,这一问的结论就有了,hashCode
和equals
方法都会用来判断相等,根据hashCode
计算出的hash相等(这和直接要求hashCode
相等有些区别),而且equals
返回true
时,才断定二者相等.
旧的会不会替换新的对象?
Value
我们知道,旧的会被新传入的Value
替换,那么Key
呢?
答案是不会替换,依旧是旧值,其实这个结论试一下就出来了,所以接下来,我们说一下细节,也就是如何判断不替换?
如何判断不替换?
之前我们提到Set
里套了Map
,Set
的操作是适配到Map
上完成的,所以Set.add
方法也是这样,需要注意的是add
方法有返回值,如果传入的Set
中存在的重复值返回fasle
表示add
失败,传入不存在的新值返回true
表示add
成功.
- 1
- 2
- 3
- 1
- 2
- 3
这里判断map.put
的操作是否为null来决定返回true
还是false
,而map.put
什么情况下返回null
,不返回null
返回什么呢?
HashMap.put实现细节
// 将“key-value”添加到HashMap中 public V put(K key, V value) { // 若“key为null”,则将该键值对添加到table[0]中。 if (key == null) return putForNullKey(value); // 若“key不为null”,则计算该key的哈希值,然后将其添加到该哈希值对应的链表中。 int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; // 若“该key”对应的键值对已经存在,则用新的value取代旧的value。然后退出! if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } // 若“该key”对应的键值对不存在,则将“key-value”添加到table中 modCount++; //将key-value添加到table[i]处 addEntry(hash, key, value, i); return null; }这个方法返回一个V,也就是Map 里放入Value,查看代码,可以知道:
1. 如果put
入Map
的是一个已存在的Key
,那么在将Key
对应的Value
更新后,将返回旧的Value
,也就是oldValue
2. 如果put
入Map
的是新的Key
,那么将返回null
这样,就可以串起来了:
1. HashMap.put
传入新的Key-Value
,返回null
,HashSet
判断返回结果是null
后,add
方法返回true
表示增加成功
2. HashMap.put
传入已存在的Key
和新的Value
,返回oldValue
,HashSet
判断返回结果不是null
后,add
方法返回false
表示增加失败
- HashSet容器
- HashSet (容器)学习
- 对象容器——HashSet
- Java 容器之Hashset 详解.
- java容器类---HashMap、HashSet
- java 数据结构容器之HashSet
- 对象容器 ArrayList HashSet HashMap
- java容器类---HashMap、HashSet
- [Java] 容器-02 HashSet 类 / Iterator 接口
- Java容器 HashMap与HashSet的学习
- Java容器:HashMap和HashSet解析
- HashSet容器 删除/添加数据实例
- Java容器----HashMap和HashSet的区别
- 【第二十三课】容器---HashSet与HashMap
- Java容器HashSet和LinkedHashSet源代码解析
- 111_容器_自定义实现HashSet
- 容器类HashSet和TreeSet习题
- Java容器类List、ArrayList、Vector、Map、HashSet等 ( 转载 )
- dataTables-使用详细说明整理
- 基于Reactor模式的libevent网络库之浅析与使用
- 顶层const与底层const
- List<Map<String,Object>>集合根据map里面的一个字段排序
- [转]pycharm的一些快捷键
- HashSet容器
- BZOJ 2463 谁能赢呢?[博弈论]
- Javascript 脚本语言详解
- 启动hadoop时,datanode启动不起来的问题
- java常用2种for循环的区别
- Java基本方法——String数组转List,删除List1中与List2中相同的元素
- Android Studio 集成 kotlin
- 详解location.href几种用法
- 应用被强杀