集合框架_HashSet保证元素唯一性的源码解析
2017-01-03 22:21
417 查看
package cn.itcast_02; import java.util.HashSet; /* * HashSet:存储字符串并遍历 * 问题:为什么存储字符串的时候,字符串内容相同的只存储了一个呢? * 通过查看add方法的源码,我们知道这个方法底层依赖两个方法:hashCode()和equals()。 * 步骤: * 首先比较哈希值 * 如果相同,继续走,比较地址值或者走equals() * 如果不同,就直接添加到集合中 * 按照方法的步骤来说: * 先看hashCode()值是否相同 * 相同:继续走equals()方法 * 返回true:说明元素重复,就不添加 * 返回false:说明元素不重复,就添加到集合中 * 不同:就值接把元素添加到集合。 * 如果类没有重写这两个方法,默认使用Object()。一般来说不会相同 * 而String类重写了hashCode()和equals()方法,所以,它就可以把内容相同的字符串去掉。只留下一个。 */ public class HashSetDemo { public static void main(String[] args) { // 创建集合对象 HashSet<String> hs = new HashSet<String>(); // 创建并添加元素 hs.add("hello"); hs.add("world"); hs.add("java"); hs.add("android"); // 遍历集合 for (String s : hs) { System.out.println(s); } } }
interface Collection {
...
}
interface Set extends Collection {
...
}
class HashSet implements Set {
private static final Object PRESENT = new Object();
private transient HashMap<E,Object> map;
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) { //e=hello,world
return map.put(e, PRESENT)==null;
}
}
class HashMap implements Map {
public V put(K key, V value) { //key=e=hello,world
//看哈希表是否为空,如果空,就开辟空间
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
//判断对象是否为null
if (key == null)
return putForNullKey(value);
int hash = hash(key); //和对象的hashCode()方法相关
//在哈希表中查找hash值
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
//这次的e其实是第一次的world
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
//走这里其实是没有添加元素
}
}
modCount++;
addEntry(hash, key, value, i); //把元素添加
return null;
}
transient int hashSeed = 0;
final int hash(Object k) { //k=key=e=hello,
int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode(); //这里调用的是对象的hashCode()方法
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
}
hs.add("hello");
hs.add("world");
hs.add("java");
hs.add("world");
相关文章推荐
- 重要BPR——mark
- 第六百一十二、三、四、五天 how can I 坚持
- 欢迎使用CSDN-markdown编辑器
- 方法
- 4.struts2_4_配置文件详解
- android binder机制 简析
- ES5基础之正则表达式02:范围类、预定义类和边界字符
- 使用JavaScript为一张图片设置备选路径
- 正则表达式小试牛刀
- 使用sz rz命令在windows和linux系统之间传文件
- Deep Image Homography Estimation 个人解读
- 测试xss和xsf
- Tomcat性能优化
- WPS文献自动索引
- Android Fragment 小结(1)
- mockito使用心得
- 2017-01-03
- djcelery的定时任务问题
- 完全二叉树的概念
- Ubuntu右键打开一个终端脚本