HashSet源码分析1
2015-09-10 15:59
423 查看
import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class SetTest { public static void main(String[] args) { Set<String> set = new HashSet<>(); set.add("abc"); set.add("xyz"); set.add("abc"); for (Iterator<String> it = set.iterator(); it.hasNext();) { System.out.println(it.next()); } } }
查看add方法
/** * Adds the specified element to this set if it is not already present. * More formally, adds the specified element <tt>e</tt> to this set if * this set contains no element <tt>e2</tt> such that * <tt>(e==null ? e2==null : e.equals(e2))</tt>. * If this set already contains the element, the call leaves the set * unchanged and returns <tt>false</tt>. * * @param e element to be added to this set * @return <tt>true</tt> if this set did not already contain the specified * element */ public boolean add(E e) { return map.put(e, PRESENT)==null; }
查看map.put方法:
/** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>.) */ public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) return putForNullKey(value); int hash = hash(key); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { 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; }
关于set:当向Set集合中添加对象时,集合首先要计算出待添加对象的hashCode值,根据该值来得到一个位置,用于存放当前的对象。如果该位置没有对象存在,那么集合Set就会认为该对象在集合中不存在,直接添加进去。如果该位置已经有一个对象存在,接着将准备添加到集合中的对象与该位置上的对象进行equals方法比较,如果该equals方法返回false,那么集合认为该集合中不存在该对象的,再进行一次散列,将该对象放到散列后计算的地址里。如果equals方法返回true,那么集合认为该对象已经存在了,不会再将对象添加到集合中。
在上面的例子中我们的执行结果为:
true true false abc xyz
第三个abc插入失败了,原因就是String类型的字符串“abc”的hashcode是相等的而且equals也是相等的(equals方法使一个字符一个字符的进行比较)。
再看下面的例子:
import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class SetTest { public static void main(String[] args) { /* Set<String> set = new HashSet<>(); System.out.println(set.add("abc")); System.out.println(set.add("xyz")); System.out.println(set.add("abc")); for (Iterator<String> it = set.iterator(); it.hasNext();) { System.out.println(it.next()); }*/ Set<People> set2 = new HashSet<>(); set2.add(new People("zhangsan")); set2.add(new People("lisi")); set2.add(new People("zhangsan")); for(Iterator<People> it = set2.iterator();it.hasNext();){ System.out.println(it.next().getName()); } } } class People{ String name; public People(String name){ this.name = name; } public String getName(){ return this.name; } }
运行结果为:
lisi zhangsan zhangsan
同样是zhangsan却能添加两次。
如果想根据name来判断,修改代码如下:
import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class SetTest { public static void main(String[] args) { /* * Set<String> set = new HashSet<>(); * System.out.println(set.add("abc")); * System.out.println(set.add("xyz")); * System.out.println(set.add("abc")); * * for (Iterator<String> it = set.iterator(); it.hasNext();) { * System.out.println(it.next()); } */ /* * String a = "abc"; String b = "abc"; System.out.println(a.hashCode()); * System.out.println(b.hashCode()); */ Set<People> set2 = new HashSet<>(); set2.add(new People("zhangsan")); set2.add(new People("lisi")); set2.add(new People("zhangsan")); for (Iterator<People> it = set2.iterator(); it.hasNext();) { System.out.println(it.next().getName()); } } } class People { String name; public People(String name) { this.name = name; } public String getName() { return this.name; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof People) { People people = (People) obj; if(this.name.equals(people.getName())); return true; } return false; } @Override public int hashCode() { return this.name.hashCode(); } }
执行结果为:
lisi zhangsan
当重写equals方法时,必须要重写hashCode方法。如果一个类的两个对象,使用equals方法比较时返回true,那么这两个对象必须要具有相同的hashCode。
相关文章推荐
- 在Xcode中使用Git进行源码版本控制
- 【传奇】全新“游戏角色命名规范”
- 使用remalloc的注意事项
- ORA-07445: :一个意料之外的问题发生了 核心转储 [ldxsnf()+625] [SIGSEGV
- angular 时间戳 转 格式化日期( 过滤器 )
- php之无限极分类
- 0909 编译原理
- 图的深度优先搜索和广度优先搜索
- R连接 oralce数据库
- sql server 行转化成列数据 小结
- iOS UIWebView 加载本地h5总结
- <a4j:keeyAlive>的英文介绍
- Windows_dll的含义和Dependency Walker使用说明( 查找函数定义 )
- maven与springMVC之接收form表单防止乱码
- HDU 4268 Alice and Bob(lower_bound)
- 0909编译原理
- HDU 4268 Alice and Bob(lower_bound)
- Rails, ActiveRecord::Base.include_root_in_json
- boost 1.47.0 linux/windows 编译库:regex与iostreams
- wget命令详解