HashSet源码分析 jdk1.6

Set的特点:Set元素无顺序,且元素不可以重复。

1、定义

public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable

Set接口定义:

public interface Set<E> extends Collection<E> {
    // Query Operations
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    <T> T[] toArray(T[] a);
    // Modification Operations
    boolean add(E e);
    boolean remove(Object o);
    // Bulk Operations
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
    boolean retainAll(Collection<?> c);
    boolean removeAll(Collection<?> c);
    void clear();
    // Comparison and hashing
    boolean equals(Object o);
    int hashCode();
}

2、底层存储

// 底层使用HashMap来保存HashSet的元素
    private transient HashMap<E,Object> map;

    // Dummy value to associate with an Object in the backing Map
    // 由于Set只使用到了HashMap的key,所以此处定义一个静态的常量Object类,来充当HashMap的value
    //用于避免java.lang.NullPointerException异常private static final Object PRESENT = new Object();

3、构造方法

/**
     * 使用HashMap的默认容量大小16和默认加载因子0.75初始化map,构造一个HashSet
     */
    public HashSet() {
        map = new HashMap<E,Object>();
    }

    /**
     * 构造一个指定Collection参数的HashSet,这里不仅仅是Set,只要实现Collection接口的容器都可以
     */
    public HashSet(Collection<? extends E> c) {
        map = new HashMap<E,Object>(Math. max((int) (c.size()/.75f) + 1, 16));
       // 使用Collection实现的Iterator迭代器,将集合c的元素一个个加入HashSet中
       addAll(c);
    }

    /**
     * 使用指定的初始容量大小和加载因子初始化map,构造一个HashSet
     */
    public HashSet( int initialCapacity, float loadFactor) {
        map = new HashMap<E,Object>(initialCapacity, loadFactor);
    }

    /**
     * 使用指定的初始容量大小和默认的加载因子0.75初始化map,构造一个HashSet
     */
    public HashSet( int initialCapacity) {
        map = new HashMap<E,Object>(initialCapacity);
    }

    /**
     * 不对外公开的一个构造方法(默认default修饰),底层构造的是LinkedHashMap,dummy只是一个标示参数,无具体意义
     */
    HashSet( int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);
}

4、增加和删除

/**
     * 利用HashMap的put方法实现add方法
     */
    public boolean add(E e) {
        return map .put(e, PRESENT)== null;
    }

    /**
     * 利用HashMap的remove方法实现remove方法
     */
    public boolean remove(Object o) {
        return map .remove(o)==PRESENT;
    }

    /**
     * 添加一个集合到HashSet中,该方法在AbstractCollection中
     */
    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
       // 取得集合c迭代器Iterator
       Iterator<? extends E> e = c.iterator();
       // 遍历迭代器
        while (e.hasNext()) {
           // 将集合c的每个元素加入到HashSet中
           if (add(e.next()))
              modified = true;
       }
        return modified;
    }

    /**
     * 删除指定集合c中的所有元素,该方法在AbstractSet中
     */
    public boolean removeAll(Collection<?> c) {
        boolean modified = false;

        // 判断当前HashSet元素个数和指定集合c的元素个数,目的是减少遍历次数
        if (size() > c.size()) {
            // 如果当前HashSet元素多,则遍历集合c,将集合c中的元素一个个删除
            for (Iterator<?> i = c.iterator(); i.hasNext(); )
                modified |= remove(i.next());
        } else {
            // 如果集合c元素多,则遍历当前HashSet,将集合c中包含的元素一个个删除
            for (Iterator<?> i = iterator(); i.hasNext(); ) {
                if (c.contains(i.next())) {
                    i.remove();
                    modified = true;
                }
            }
        }
        return modified;
}

Hashset的很多地方就是利用 hashmap的key实现的

原文地址:https://www.cnblogs.com/L-a-u-r-a/p/8540828.html

时间: 2024-10-16 10:39:31

HashSet源码分析 jdk1.6的相关文章

Java集合系列之HashSet源码分析

一.HashSet简介 HashSet是Set接口典型实现,它按照Hash算法来存储集合中的元素,具有很好的存取和查找性能.主要具有以下特点: 不保证set的迭代顺序 HashSet不是同步的,如果多个线程同时访问一个HashSet,要通过代码来保证其同步 集合元素值可以是null 当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该值确定对象在HashSet中的存储位置.在Hash集合中,不能同时存放两个相等的

LinkedList源码分析--jdk1.8

JDK1.8 ArrayList源码分析--jdk1.8LinkedList源码分析--jdk1.8 LinkedList概述 ??1.LinkedList是用双向链表实现的集合,基于内部类Node<E>实现的集合.??2.LinkedList支持双向链表访问.克隆.序列化,元素有序且可以重复.??3.LinkedList没有初始化大小,也没有扩容机制,通过头结点.尾节点迭代查找. LinkedList数据结构 ??数据结构是集合的精华所在,数据结构往往也限制了集合的作用和侧重点,了解各种数据

HashMap源码分析--jdk1.8

JDK1.8 ArrayList源码分析--jdk1.8LinkedList源码分析--jdk1.8HashMap源码分析--jdk1.8 HashMap概述 ??1. HashMap是可以动态扩容的数组,基于数组.链表.红黑树实现的集合.??2. HashMap支持键值对取值.克隆.序列化,元素无序,key不可重复value可重复,都可为null.??3. HashMap初始默认长度16,超出扩容2倍,填充因子0.75f.??4.HashMap当链表的长度大于8的且数组大小大于64时,链表结构

AQS源码分析--jdk1.8

JDK1.8 ArrayList源码分析--jdk1.8LinkedList源码分析--jdk1.8HashMap源码分析--jdk1.8AQS源码分析--jdk1.8 AbstractQueuedSynchronizer概述 ??1. AQS是一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.??2. AQS提供了双向链表.??3. AQS分为共享模式和独占模式.??4.AQS基于volatile内存可见性和CAS原子性操作实现线程间通信操作. AbstractQueuedS

ReentrantLock源码分析--jdk1.8

JDK1.8 ArrayList源码分析--jdk1.8LinkedList源码分析--jdk1.8HashMap源码分析--jdk1.8AQS源码分析--jdk1.8ReentrantLock源码分析--jdk1.8 ReentrantLock概述 ??1. ReentrantLock是独占锁.??2. ReentrantLock分为公平模式和非公平模式.??3. ReentrantLock锁可重入(重新插入) ReentrantLock源码分析 /** * @since 1.5 * @aut

ConcurrentHashMap源码分析(JDK1.7和1.8对比)

一.ConcurrentHashMap简介 并发编程大师Doug Lea开发的并发容器之一.ConcurrentHashMap是线程安全且高效的HashMap,在HashMap的基础上增加了线程安全,当然结构方面也有所改变. 为什么要使用ConcurrentHashMap? 1.多线程环境下,HashMap会处于不安全状态.例如put操作可能会引起程序死循环,Cpu占有率达百分百,原因是多线程会导致HashMap的Entry链表形成环形数据结构,如此一来,他的next结点将永不为空,就会产生死循

Vector 源码分析 jdk1.8

Vector简介 Vector 是矢量队列,它是JDK1.0版本添加的类.继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口.Vector 继承了AbstractList,实现了List:所以,它是一个队列,支持相关的添加.删除.修改.遍历等功能.Vector 实现了RandmoAccess接口,即提供了随机访问功能.RandmoAccess是java中用来被List实现,为List提供快速访问功能的.在Vector中,我们即可以通过元素的序

死磕 java集合之HashSet源码分析

问题 (1)集合(Collection)和集合(Set)有什么区别? (2)HashSet怎么保证添加元素不重复? (3)HashSet是否允许null元素? (4)HashSet是有序的吗? (5)HashSet是同步的吗? (6)什么是fail-fast? 简介 集合,这个概念有点模糊. 广义上来讲,java中的集合是指java.util包下面的容器类,包括和Collection及Map相关的所有类. 中义上来讲,我们一般说集合特指java集合中的Collection相关的类,不包含Map相

ArrayList源码分析--jdk1.8

ArrayList概述   1. ArrayList是可以动态扩容和动态删除冗余容量的索引序列,基于数组实现的集合.  2. ArrayList支持随机访问.克隆.序列化,元素有序且可以重复.  3. ArrayList初始默认长度10,使用Object[]存储各种数据类型. ArrayList数据结构   数据结构是集合的精华所在,数据结构往往也限制了集合的作用和侧重点,了解各种数据结构是我们分析源码的必经之路.  ArrayList的数据结构如下: ArrayList源码分析 /* * 用数