HashSet源码探讨(基于JDK1.8)

来源:互联网 发布:君临天下青囊师数据 编辑:程序博客网 时间:2024/05/21 05:57
HashSet 简介

如果对HashMap没有了解,应该先学习HashMap再学习HashSet 。
HashSet结构
  1. public class HashSet<E>
  2. extends AbstractSet<E>
  3. implements Set<E>, Cloneable, java.io.Serializable

HashSet 是一个没有重复元素的集合,它其实是由HashMap实现的,HashMap中保存的是键值对,然而我们只能向HashSet中添加key,原因在于
HashSet的Value其实都是同一个对象,这是HashSet添加元素的方法,可以看到辅助实现HashSet的map中的value其实都是Object类的同一个对象。
  1. private static final Object PRESENT = new Object();
  2. public boolean add(E e) {
  3. return map.put(e, PRESENT)==null;
  4. }

HashSet 不保证元素的顺序,而且HashSet允许使用 null 元素。
HashSet是非同步的。如果多个线程同时访问一个哈希 set,而其中至少一个线程修改了该 set,那么它必须 保持外部同步。这通常是通过对自然封装该 set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来“包装” set。最好在创建时完成这一操作,以防止对该 set 进行意外的不同步访问:

  1. public static <T> Set<T> synchronizedSet(Set<T> s) {
  2. return new SynchronizedSet<>(s);
  3. }

SynchronizedSet如下
  1. static class SynchronizedSet<E>
  2. extends SynchronizedCollection<E>
  3. implements Set<E> {
  4. private static final long serialVersionUID = 487447009682186044L;
  5. SynchronizedSet(Set<E> s) {
  6. super(s);
  7. }
  8. SynchronizedSet(Set<E> s, Object mutex) {
  9. super(s, mutex);
  10. }
  11. public boolean equals(Object o) {
  12. if (this == o)
  13. return true;
  14. synchronized (mutex) {return c.equals(o);}
  15. }
  16. public int hashCode() {
  17. synchronized (mutex) {return c.hashCode();}
  18. }
  19. }

HashSet的两种遍历方式
  1. public class HashSetIteratorTest {
  2. public static void main(String[] args) {
  3. HashSet set = new HashSet();
  4. for (int i=0; i<5; i++)
  5. set.add(""+i);
  6. iteratorHashSet(set) ;
  7. foreachHashSet(set);
  8. }
  9. /*
  10. * 通过Iterator遍历HashSet。推荐方式
  11. */
  12. private static void iteratorHashSet(HashSet set) {
  13. for(Iterator iterator = set.iterator();
  14. iterator.hasNext(); ) {
  15. System.out.printf("iterator : %s\n", iterator.next());
  16. }
  17. }
  18. /*
  19. * 通过for-each遍历HashSet。不推荐!此方法需要先将Set转换为数组
  20. */
  21. private static void foreachHashSet(HashSet set) {
  22. String[] arr = (String[])set.toArray(new String[0]);
  23. for (String str:arr)
  24. System.out.printf("for each : %s\n", str);
  25. }
  26. }