文章标题 【Java源码浅析】关于HashMap和HashSet的异同和源码分析

来源:互联网 发布:mac连不上wifi 编辑:程序博客网 时间:2024/06/06 14:07

最近学了JAVA之后,对JAVA源码实现很感兴趣,于是就在自己的Eclipse里看JAVA里的一些常用的类的源码实现,自己水平也不是很高,有不懂的代码还是要去看别人写的博客,我写的这篇文章也是看了别人的博客后,加上自己看了源码后的理解而作,既是希望自己能从此掌握这两个类的实现,也能帮助那些渴望成为编程大牛的孩子。大家有不理解的可以看这篇文章 https://www.baidu.com/link?url=IqZUK4wSjRAZ-yDH2wgp_x3uosAcN1bFUv7GYaQk4DStjeU559QtWuUsHAu9WViOKJXaaW3qJnBJv3KH9jRI2nhOdw-zjOi-GA4OspLHYUK&wd=&eqid=cf09827d00034226000000035991cae8
HashMap和HashSet是java里很常用的两个类,他们有
相同之处
1:都是用Hash算法来存储元素的值
2:查找存取的性能都很好(当然比数组还是稍微差一些)
3:存储的值都允许为null
4:都不是线程安全的
5:都不维护元素的顺序,也就是说,是乱序存放的
6:都是collection框架的一部分
不同之处
1:HashSet里的value不允许重复,但是HashMap的value是允许重复的
2:HashMap是以键值对来存储的,而HashSet仅仅是存放值
3:HashMap实现的是Map接口,HashSet实现的是Set接口
4:HashMap使用键对象来计算Hashcode,HashSet使用值对象来计算hashcode(因为它只存放值,所以只能用值来计算hashcode)

下面就是具体的分析源码了,先把源码贴上,我们边看源码边分析。先分析HashMap(hashmap的实现原理图接我建议先看这篇博文,我觉得讲的很清楚 http://blog.csdn.net/eson_15/article/details/51158865?locationNum=2&fps=1)

/*HashMap 继承的是AbstractMap,它实现了Map, Cloneable, Serializable 三个类*/public class HashMap extends AbstractMap    implements Map, Cloneable, Serializable{   /*DEFAULT_INITIAL_CAPACITY = 16 默认容量为16*/    static final int DEFAULT_INITIAL_CAPACITY = 16;    static final int MAXIMUM_CAPACITY = 1073741824;    /*默认的负载因子的值*/    static final float DEFAULT_LOAD_FACTOR = 0.75F;    /*说一下  transient 。transient是Java语言的关键字,用来表示一个域不象串行化的一部分。当持久化对象时,可能有一个特殊的对象数据成员,我们不想serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。然而非transient型的变量是被包括进去的。*/    transient Entry[] table;/* table 是Entry[]数组变量,也就是键值对类型的数组,一个可以对应一个value*/    transient int size;    int threshold; /* 极限容量*/    final float loadFactor; /*负载因子*/    transient volatile int modCount; /*用来记录对map的操作次数,这个变量特别重要*/    private transient Set entrySet = null;    private static final long serialVersionUID = 362498820763181265L;    /*静态的Entry类,实现Map.Entry,里面就定义了,key,value,next,hash我们需要用的变量,key,value不说了,next变量相当于一个指针,在用 Iterator 遍历时会发挥很大的作用*/    static class Entry implements Map.Entry    {    final Object key;    Object value;    Entry next;    final int hash;    /*Entry 的构造函数*/    Entry(int i, Object object, Object object_0_, Entry entry_1_) {        value = object_0_;        next = entry_1_;        key = object;        hash = i;    }     /*得到map里存储的key值*/    public final Object getKey() {        return key;    }    /*得到value值*/    public final Object getValue() {        return value;    }    /*设置value值*/    public final Object setValue(Object object) {        Object object_2_ = value; /*用一个变量来保存旧的值*/        value = object; /*设置新的值*/        return object_2_; /*返回旧值*/    }    /*判断两个对象是否相等的方法*/    public final boolean equals(Object object) {        if (!(object instanceof Map.Entry))        return false;   /*首先判断类型是否相等,不相等直接返回false*/        /*强制转换object为Entry对象类型,用entry_3_ 变量表示*/        Map.Entry entry_3_ = (Map.Entry) object;        Object object_4_ = getKey(); /*用getKey方法得到key值(这是用equals方法的那个对象的key值,而不是object的key值)*/        /*这才是object的key值,entry_3_ 表示的就是object*/        Object object_5_ = entry_3_.getKey();        /*判断key值是否相等(object_4_ == object_5_), (object_4_ != null && object_4_.equals(object_5_))key值不能为null且要相等,否则就没必要比较value值了*/        if (object_4_ == object_5_        || object_4_ != null && object_4_.equals(object_5_)) {        /*就可以比较value值是否相等,逻辑与比较key值相同*/        Object object_6_ = getValue();        Object object_7_ = entry_3_.getValue();        if (object_6_ == object_7_            || object_6_ != null && object_6_.equals(object_7_))            return true;        }        return false;    }    /*根据key值和value值来计算hash值,来定位此对象在hashmap中的位置*/    public final int hashCode() {        return ((key == null ? 0 : key.hashCode())            ^ (value == null ? 0 : value.hashCode()));    }    /*toString() 方法,没什么好说的*/    public final String toString() {        return new StringBuilder().append(getKey()).append("=").append               (getValue()).toString();    }    void recordAccess(HashMap hashmap) {        /* empty */    }    void recordRemoval(HashMap hashmap) {        /* empty */    }    }    /*内部类,定义EntryIterator 迭代器和一些其他方法,是可以被hashmap类直接访问的,从名字可以知道,它是用来迭代Entry类型对象的迭代器*/    private final class EntryIterator extends HashIterator    {    final HashMap this$0 = HashMap.this; (HashMap.this表示引用的是HashMap这个类的实例,不这样声明编译器会不知道引用的是哪个实例)    /*直接继承父类的EntryIterator()*/    private EntryIterator() {        super();    }     /*next()方法,迭代器时会使用,是实现迭代器的重要方法*/    public Map.Entry next() {        return nextEntry();    }    public volatile Object next() {        return next();    }    EntryIterator(ANONYMOUS CLASS java.util.HashMap$1 var_1) {        this();    }    }    /*EntrySet类,将Entry对象封装成一个Set,这样可以用来作遍历hashmap集合,速度很快*/    private final class EntrySet extends AbstractSet    {    final HashMap this$0 = HashMap.this;    /*使用父类的构造函数*/    private EntrySet() {        super();    }    /*EntrySet的迭代器*/    public Iterator iterator() {        return this$0.newEntryIterator();    }    /*判断是否包含此object对象*/    public boolean contains(Object object) {        if (!(object instanceof Map.Entry))        return false;   /*同样是先判断类型是否相等*/        Map.Entry entry = (Map.Entry) object;        /*通过getEntry()方法通过entry.getKey()得到Entry对象*/        Entry entry_8_ = this$0.getEntry(entry.getKey());        /*调用之前的equals方法来判断是否相等,相等则返回true*/        return entry_8_ != null && entry_8_.equals(entry);    }     /*调用hashmap.removeMapping(object)方法,如果成功删除,则放回true,否则object不在keyset里,则放回false*/    public boolean remove(Object object) {        return this$0.removeMapping(object) != null;    }   /*整个map的大小*/    public int size() {        return this$0.size;    }    /*调用hashmap的clear()方法,这个方法在下面会说到*/    public void clear() {        this$0.clear();    }    EntrySet(ANONYMOUS CLASS java.util.HashMap$1 var_1) {        this();    }    }    /*真正到了重要的地方,这个类特别重要,也是个迭代类,是内部抽象类,这个类的方法常常拿来做hashmap的迭代*/    private abstract class HashIterator implements Iterator    {    Entry next; /*entry类型的变量,是用来保存下一个迭代对象的  指针  */    int expectedModCount; /* 这个int 型变量是跟前面 modCount 对应的,他们一定要相等,不然就会报错,他们是用来记录对map集合的操作次数,即增删改的次数*/    int index; /*hash 下标,标识map中元素的位置*/    Entry current; /*迭代过程中当前的迭代对象*/    final HashMap this$0 = HashMap.this; /* 要记得它还是当前这个hashmap的引用实例*/    /*构造函数 注意 expectedModCount = modCount; 是要相等的 */    HashIterator() {        super();        expectedModCount = modCount;        if (size > 0) {        Entry[] entrys = table;         while (index < entrys.length               && (next = entrys[index++]) == null) {            /* empty */  /*为什么里面是空的,我也不是太清楚,我看别人博客说的是,这是为了让你自己写你需要的实现,while里的条件也不难理解*/        }        }    }    /* hasNext 方法,是不是很简单?只要还有next指针,就可以继续遍历,否则返回false*/    public final boolean hasNext() {        return next != null;    }    /*这个类返回Entry类型的对象 */    final Entry nextEntry() {    / * 先判断modCount == expectedModCount 是否相等,如果不等,就会抛出异常 ConcurrentModificationException()*/         if (this$0.modCount != expectedModCount)        throw new ConcurrentModificationException();        /*将next对象赋给 entry变量*/        Entry entry = next;       /*判断是否为null,为null表示没有这个元素存在map里*/        if (entry == null)        throw new NoSuchElementException();        /*以上的判断都通过了,就可以真正进行nextEntry 的判断了,(next = entry.next) == null 因为 hashmap里存放数据是不连续的,如果下一个指针所指的entry对象为null,就通过下面的代码来找到下一个不为null的对象,当entry.next为空时,就要循环找到下一个不为空的entry对象,entry.next不为null,则会跳过这段代码*/        if ((next = entry.next) == null) {        Entry[] entrys = this$0.table;        /*while 的作用,当遇到不为null的entry对象就跳出循环,并且赋给了 next 指针 要是一直是null,那么next指针也是null,index标识当前entry对象在进入循环时的位置,并且会执行index++操作*/        while (index < entrys.length               && (next = entrys[index++]) == null) {            /* empty */        }        }        /*当前迭代的对象是entry*/        current = entry;        return entry; /*返回entry*/    }    /* 删除操作*/    public void remove() {    /*当前要删除的对象不能为null*/        if (current == null)        throw new IllegalStateException();        /*modCount ,expectedModCount 一定要相等*/        if (this$0.modCount != expectedModCount)        throw new ConcurrentModificationException();        /*先得到key*/        Object object = current.key;        /*将它设为null,这样GC就会回收它*/        current = null;        /*调用此方法,就能以key来删除 entry对象*/        this$0.removeEntryForKey(object);        /*删除操作后要再次令 expectedModCount = this$0.modCount*/        expectedModCount = this$0.modCount;    }    }    /*这是以key来作迭代的 内部类,继承 HashIterator 原理都差不多*/    private final class KeyIterator extends HashIterator    {    final HashMap this$0 = HashMap.this;    private KeyIterator() {        super();    }    /*得到下一个key*/    public Object next() {        return nextEntry().getKey();    }    KeyIterator(ANONYMOUS CLASS java.util.HashMap$1 var_1) {        this();    }    }    /* keyset 也就是所有的key的集合,也可以拿来遍历map的key的集合*/    private final class KeySet extends AbstractSet    {    final HashMap this$0 = HashMap.this;    private KeySet() {        super();    }    public Iterator iterator() {        return this$0.newKeyIterator();    }    public int size() {        return this$0.size;    }    /*调用containsKey(object) 来判断是否包含,containsKey(object) 在后面会说*/    public boolean contains(Object object) {        return this$0.containsKey(object);    }    /*同上的remove方法的逻辑*/    public boolean remove(Object object) {        return this$0.removeEntryForKey(object) != null;    }    public void clear() {        this$0.clear();    }    KeySet(ANONYMOUS CLASS java.util.HashMap$1 var_1) {        this();    }    }    /*同keyIterator 的实现原理和思路*/    private final class ValueIterator extends HashIterator    {    final HashMap this$0 = HashMap.this;    private ValueIterator() {        super();    }    public Object next() {        return nextEntry().value;    }    ValueIterator(ANONYMOUS CLASS java.util.HashMap$1 var_1) {        this();    }    }    private final class Values extends AbstractCollection    {    final HashMap this$0 = HashMap.this;    private Values() {        super();    }    public Iterator iterator() {        return this$0.newValueIterator();    }    public int size() {        return this$0.size;    }    public boolean contains(Object object) {        return this$0.containsValue(object);    }    public void clear() {        this$0.clear();    }    Values(ANONYMOUS CLASS java.util.HashMap$1 var_1) {        this();    }    }    /*终于找到hashmap的构造方法了。i 是设置 entry[] 数组的大小, i不能小于0,也不能大于1073741824,f是负载因子的大小*/    public HashMap(int i, float f) {    if (i < 0)        throw new IllegalArgumentException              (new StringBuilder().append               ("Illegal initial capacity: ").append               (i).toString());    if (i > 1073741824)        i = 1073741824;    if (f <= 0.0F || Float.isNaN(f))        throw new IllegalArgumentException(new StringBuilder().append                           ("Illegal load factor: ")                           .append                           (f).toString());    int i_9_;    for (i_9_ = 1; i_9_ < i; i_9_ <<= 1) {        /* empty */    }    loadFactor = f;    threshold = (int) ((float) i_9_ * f);    table = new Entry[i_9_];    /*初始化的方法,是空的*/    init();    }    /*这个大家都能看懂吧*/    public HashMap(int i) {    this(i, 0.75F);    }    /*默认的构造方法,如果不加参数,就默认这么设置*/    public HashMap() {    loadFactor = 0.75F;    threshold = 12;    table = new Entry[16];    init();    }    /*这个构造方法比较复杂,好像也不常用*/    public HashMap(Map map) {    this(Math.max((int) ((float) map.size() / 0.75F) + 1, 16), 0.75F);    /*注意这个方法,后面会说到*/    putAllForCreate(map);    }    void init() {    /* empty */    }    /*这就是计算hash值的方法,想深入研究的可以去查查实现原理,我不是太懂*/    static int hash(int i) {    i ^= i >>> 20 ^ i >>> 12;    return i ^ i >>> 7 ^ i >>> 4;    }    /*这个方法计算出该entry对象在table数组里存放的位置, i_10_ 变量将要存的是table数组的长度,传入table数组的长度就不会使计算出的位置超越数组的长度*/    static int indexFor(int i, int i_10_) {    return i & i_10_ - 1;    }    public int size() {    return size;    }    /*这个方法也是很简单的,size大于0,就不是空的*/    public boolean isEmpty() {    return size == 0;    }    /*get方法会根据object(实际上它是key的值)得到所存贮的值*/    public Object get(Object object) {    if (object == null)  /*为null时,用getForNullKey() 方法得到它的值*/        return getForNullKey();    int i = hash(object.hashCode()); /*得到hash值,即索引*/    /*用for循环来循环此table[indexFor(i, table.length)]处是否存在链表,有链表则遍历找出要找的key和它的值*/    for (Entry entry = table[indexFor(i, table.length)]; entry != null;         entry = entry.next) {        Object object_11_;        /*if条件里是要对比key值和计算出的hash值的,最后还得用equals方法进行比较,才能真正返回value值*/        if (entry.hash == i && ((object_11_ = entry.key) == object                    || object.equals(object_11_)))        return entry.value;    }    return null;    }    /*当key为空时,调用此方法得到对应value*/        private Object getForNullKey() {        /*为什么从0开始遍历呢?因为hashmap里默认将key=null的key-value对放在table[0]处,for循环用来检查是否有链表存在,有则遍历得到第一个key为null的值*/    for (Entry entry = table[0]; entry != null; entry = entry.next)    {        if (entry.key == null)        return entry.value;    }    return null;    }    /*通过key值来判断此key是否包含在table数组里*/    public boolean containsKey(Object object) {    return getEntry(object) != null;    }    /*getEntry方法,很重要,在很多方法里都调用了它*/    final Entry getEntry(Object object) {    /*首先还是先计算它的hash值,它是用来在indexFor(i, table.length)方法里定位此key在table数组里的地址的*/    int i = object == null ? 0 : hash(object.hashCode());    /*此for循环的作用和之前的一样,大家很容易看懂的*/    for (Entry entry = table[indexFor(i, table.length)]; entry != null;         entry = entry.next) {        Object object_12_;        if (entry.hash == i        && ((object_12_ = entry.key) == object            || object != null && object.equals(object_12_)))        return entry;    }    return null;    }    /*hashmap里的put方法,大家经常用,现在看看是怎么实现的*/    public Object put(Object object, Object object_13_) {    /*先判断key是否为空,为空则用另外的方法来put它,即putForNullKey(object_13_) 方法*/    if (object == null)        return putForNullKey(object_13_);        /*一样得到hash值*/    int i = hash(object.hashCode());    int i_14_ = indexFor(i, table.length); /*定位在table数组的位置*/    /*判断此位置是否有链表,此段代码会判断是否已经有相同的key值存在,如果已经有了,会覆盖value值,没有则会在此位置插入一个entry对象*/    for (Entry entry = table[i_14_]; entry != null; entry = entry.next) {        Object object_15_;        if (entry.hash == i && ((object_15_ = entry.key) == object                    || object.equals(object_15_))) {        Object object_16_ = entry.value;        entry.value = object_13_; /*替换value值*/        entry.recordAccess(this);        return object_16_; /*会返回旧值*/        }    }    /*如果没有已经存在的key值,会直接执行下面的代码*/    modCount++; /*操作标识数+1*/    addEntry(i, object, object_13_, i_14_); /*新加了一个entry对象*/    return null;    }    /*当key值为空时,object代表的要插入的value值*/    private Object putForNullKey(Object object) {    for (Entry entry = table[0]; entry != null; entry = entry.next) {       /*也替换key为null的entry对象的value值*/        if (entry.key == null) {        Object object_17_ = entry.value;        entry.value = object;        entry.recordAccess(this);        return object_17_;        }    }    /*前面的代码执行后没有找到null的key,则新插入一个新entry对象*/    modCount++;    addEntry(0, null, object, 0);    return null;    }    /*这个方法实现原理和前面的方法相同*/    private void putForCreate(Object object, Object object_18_) {    int i = object == null ? 0 : hash(object.hashCode());    int i_19_ = indexFor(i, table.length);    for (Entry entry = table[i_19_]; entry != null; entry = entry.next) {        Object object_20_;        if (entry.hash == i        && ((object_20_ = entry.key) == object            || object != null && object.equals(object_20_))) {        entry.value = object_18_;        return;        }    }    createEntry(i, object, object_18_, i_19_);    }    /*和上面的putAllForCreate方法是同一个方法,只是传入的是map*/    private void putAllForCreate(Map map) {    /*用iterator迭代器来迭代entrySet()集合里的entry对象*/    Iterator iterator = map.entrySet().iterator();    while (iterator.hasNext()) {        Map.Entry entry = (Map.Entry) iterator.next();        putForCreate(entry.getKey(), entry.getValue());    }    }    /*重置table数组的大小*/    void resize(int i) {    Entry[] entrys = table;    int i_21_ = entrys.length;    if (i_21_ == 1073741824)        threshold = 2147483647; /*threshold=i_21*2-1 ,即如果table数组的大小已经达到1073741824了,就扩容*/    else {    / *不然,就按传入的i来重新创建Entry[]数组*/        Entry[] entrys_22_ = new Entry[i];        transfer(entrys_22_); /*此方法是重新复制table数组*/        table = entrys_22_; /*将entrys_22_新数组的引用地址赋给table数组*/        threshold = (int) ((float) i * loadFactor);    }    }    /*这就是上面的transfer方法的实现*/    void transfer(Entry[] entrys) {    Entry[] entrys_23_ = table; /*这是没复制前的table*/    int i = entrys.length;    /*for循环遍历table,并将table里的entry对象存入entrys数组里*/    for (int i_24_ = 0; i_24_ < entrys_23_.length; i_24_++) {        Entry entry = entrys_23_[i_24_];        if (entry != null) {        entrys_23_[i_24_] = null; /*将它变成null*/        do {            Entry entry_25_ = entry.next;            int i_26_ = indexFor(entry.hash, i); /*定位在entrys数组里的位置*/            entry.next = entrys[i_26_];            entrys[i_26_] = entry; /*复制操作,将entry赋给entrys[i_26_]*/            entry = entry_25_; /*将原来的entry.next赋给entry,用来作while循环*/        } while (entry != null);        }    }    }    /*将map里的对象全放进hashmap里*/    public void putAll(Map map) {    int i = map.size(); /*判断map的对象的多少*/    /*对i的值进行判断,这是有必要的*/    if (i != 0) {        if (i > threshold) {        int i_27_ = (int) ((float) i / loadFactor + 1.0F);        if (i_27_ > 1073741824)            i_27_ = 1073741824;        int i_28_;        for (i_28_ = table.length; i_28_ < i_27_; i_28_ <<= 1) {            /* empty */        }        if (i_28_ > table.length)            resize(i_28_);        }        /*用迭代器来迭代put每一个元素进hashmap*/        Iterator iterator = map.entrySet().iterator();        while (iterator.hasNext()) {        Map.Entry entry = (Map.Entry) iterator.next();        put(entry.getKey(), entry.getValue());        }    }    }    /*删除操作*/    public Object remove(Object object) {    Entry entry = removeEntryForKey(object);    return entry == null ? null : entry.value;    }    /*删除操作具体实现*/    final Entry removeEntryForKey(Object object) {    /*得到hash值*/    int i = object == null ? 0 : hash(object.hashCode());    int i_29_ = indexFor(i, table.length); /*table    数组里object key值对应的地址*/    Entry entry = table[i_29_]; /*得到key对应的那个对象*/    Entry entry_30_;    Entry entry_31_;    /*还是在遍历当前位置是否有链表存在,有的话就遍历判断*/    for (entry_31_ = entry; entry_31_ != null; entry_31_ = entry_30_) {        entry_30_ = entry_31_.next; /*entry_30_存链表上当前entry对象的下一个对象的指针*/        Object object_32_;        if (entry_31_.hash == i        && ((object_32_ = entry_31_.key) == object            || object != null && object.equals(object_32_))) {        modCount++; /*删除操作后要modCount++*/        size--; /*大小要减一*/        if (entry == entry_31_) /*如果要删除的是当前的第一个entry对象*/            table[i_29_] = entry_30_; /*则将entry_31_.next存在table[i_29_]中,即将原来是在链表头的entry对象的下一个对象移到表头来,因为当前在表头的entry对象要被删除了*/        else            entry.next = entry_30_; /*不是当前的第一个entry对象*/        entry_31_.recordRemoval(this);        return entry_31_;        }        entry = entry_31_;    }    return entry_31_; /*返回删除的entry对象的value*/    }   /*和上面的removeEntryForKey 原理类似*/    final Entry removeMapping(Object object) {    if (!(object instanceof Map.Entry)) /*先判断类型是否相同*/        return null;    Map.Entry entry = (Map.Entry) object; /*此传入的object就是一个对象类型了,强制转换成entry类型*/    Object object_33_ = entry.getKey(); /*得到key*/    /*得到hash值*/    int i = object_33_ == null ? 0 : hash(object_33_.hashCode());    /*得到在table数组里的定位*/    int i_34_ = indexFor(i, table.length);    Entry entry_35_ = table[i_34_];    Entry entry_36_;    Entry entry_37_;    /*实现原理和上面的方法一致,就不细说了*/    for (entry_37_ = entry_35_; entry_37_ != null; entry_37_ = entry_36_) {        entry_36_ = entry_37_.next;        if (entry_37_.hash == i && entry_37_.equals(entry)) {        modCount++;        size--;        if (entry_35_ == entry_37_)            table[i_34_] = entry_36_;        else            entry_35_.next = entry_36_;        entry_37_.recordRemoval(this);        return entry_37_;        }        entry_35_ = entry_37_;    }    return entry_37_;    }    /*clear方法,遍历table数组将每一个entry对象置为null,等待虚拟机将其回收*/    public void clear() {    modCount++;    Entry[] entrys = table;    for (int i = 0; i < entrys.length; i++)        entrys[i] = null;    size = 0; /*将size置为0*/    }    /*object代表的是value的值*/    public boolean containsValue(Object object) {    if (object == null)        return containsNullValue();    Entry[] entrys = table;    /*用两个for循环来遍历,其实效率不高啦*/    for (int i = 0; i < entrys.length; i++) {    /*防止有出现链表的情况,所以在每个table数组的位置在遍历一次,逐个对比*/        for (Entry entry = entrys[i]; entry != null; entry = entry.next) {        if (object.equals(entry.value))            return true; /*找到则返回true*/        }    }    return false;    }    /*当传进来的value等于null时调用这个方法,原理和上面的方法一致*/    private boolean containsNullValue() {    Entry[] entrys = table;    for (int i = 0; i < entrys.length; i++) {        for (Entry entry = entrys[i]; entry != null; entry = entry.next) {        if (entry.value == null)            return true;        }    }    return false;    }    /*用来克隆的方法,此方法比较简单*/    public Object clone() {    HashMap hashmap_38_ = null;/*新创建一个hashmap对象*/    try {        hashmap_38_ = (HashMap) super.clone();    } catch (CloneNotSupportedException clonenotsupportedexception) {        /* empty */    }    hashmap_38_.table = new Entry[table.length];/*创建一个新的table*/    hashmap_38_.entrySet = null;    hashmap_38_.modCount = 0; /*将它设为0是因为putAllForCreate(this)方法会在内部进行modCount++ */    hashmap_38_.size = 0;    hashmap_38_.init();    hashmap_38_.putAllForCreate(this);    return hashmap_38_; /最后返回此hashmap对象/    }    /*此方法在指定的地方添加一个新的对象,指定的地方为 i_40_*/    void addEntry(int i, Object object, Object object_39_, int i_40_) {    Entry entry = table[i_40_];    table[i_40_] = new Entry(i, object, object_39_, entry); /*这句代码将新加的对象加到table[i_40_]处*/    /*进行容量大小判定,如果因为多加一个对象而超出容量,则扩容*/    if (size++ >= threshold)        resize(2 * table.length);    }    /*原理同上*/    void createEntry(int i, Object object, Object object_41_, int i_42_) {    Entry entry = table[i_42_];    table[i_42_] = new Entry(i, object, object_41_, entry);    size++;    }    Iterator newKeyIterator() {    return new KeyIterator(null);    }    Iterator newValueIterator() {    return new ValueIterator(null);    }    Iterator newEntryIterator() {    return new EntryIterator(null);    }    public Set keySet() {    Set set = keySet;    return set != null ? set : (keySet = new KeySet(null));    }    public Collection values() {    Collection collection = values;    return collection != null ? collection : (values = new Values(null));    }    /*entrySet集合*/    public Set entrySet() {    return entrySet0();    }    private Set entrySet0() {    Set set = entrySet;    return set != null ? set : (entrySet = new EntrySet(null));    }    /*下面两个方法我几乎没用过,建议去百度看看其他大神的解释,我这就不多说了*/    private void writeObject(ObjectOutputStream objectoutputstream)    throws IOException {    Iterator iterator = size > 0 ? entrySet0().iterator() : null;    objectoutputstream.defaultWriteObject();    objectoutputstream.writeInt(table.length);    objectoutputstream.writeInt(size);    if (iterator != null) {        while (iterator.hasNext()) {        Map.Entry entry = (Map.Entry) iterator.next();        objectoutputstream.writeObject(entry.getKey());        objectoutputstream.writeObject(entry.getValue());        }    }    }    private void readObject(ObjectInputStream objectinputstream)    throws IOException, ClassNotFoundException {    objectinputstream.defaultReadObject();    int i = objectinputstream.readInt();    table = new Entry[i];    init();    int i_43_ = objectinputstream.readInt();    for (int i_44_ = 0; i_44_ < i_43_; i_44_++) {        Object object = objectinputstream.readObject();        Object object_45_ = objectinputstream.readObject();        putForCreate(object, object_45_);    }    }    int capacity() {    return table.length;    }    float loadFactor() {    return loadFactor;    }}

HashSet源码及分析 因为hashset实际上就是hashmap的封装,所以它内容很少,基本很多方法都是直接用hashmap里的方法,不过只是hashset里面的value值是不重复的而已

/* 可以看到,hashset继承了AbstractSet接口,实现了Set,Cloneable, Serializable接口*/public class HashSet extends AbstractSet    implements Set, Cloneable, Serializable{/*serialVersionUID序列id,transient HashMap map   说一下transient 。transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。然而非transient型的变量是被包括进去的。我们也可以看到,Hashset里有以HashMap定义的map,可以说,HashSet实际上就是用HashMap来实现的*/    static final long serialVersionUID = -5024744406713321676L;    private transient HashMap map;    /*HashSet里的value就是PRESENT对象,*/    private static final Object PRESENT = new Object();    /*默认构造函数,创建出一个HashMap对象,以HashMap默认的16容量和0.75的负载因子创建*/    public HashSet() {    map = new HashMap();    }    /*传入collection集合对象来创建一个map对象,也是使用的是hashmap里的一个构造函数来创建map对象*/    public HashSet(Collection collection) {    map = new HashMap(Math.max(((int) ((float) collection.size() / 0.75F)                    + 1),                   16));    addAll(collection);/*addall() hashmap里的静态方法*/    }    /*以下几个都是hashmap的构造函数,大家看看就知道什么意思了,后面的代码里会说*/    public HashSet(int i, float f) {    map = new HashMap(i, f);    }    public HashSet(int i) {    map = new HashMap(i);    }    HashSet(int i, float f, boolean bool) {    map = new LinkedHashMap(i, f);    }    /*Iterator迭代器,用来迭代出keySet里的值*/    public Iterator iterator() {    return map.keySet().iterator();    }    /*map的大小*/    public int size() {    return map.size();    }    /*判断是否为空*/    public boolean isEmpty() {    return map.isEmpty();    }    /*由于hashset里面只存value,所以contains方法里直接调用map里的containsKey()方法就行了,因为其实hashmap里的key集合就是一个hashset,key的值是不会重复的*/    public boolean contains(Object object) {    return map.containsKey(object);    }    /*add方法,调用map的put方法,上面hashmap里已经解释过了*/    public boolean add(Object object) {    return map.put(object, PRESENT) == null;    }    /*和hashmap的remove方法原理一样的*/    public boolean remove(Object object) {    return map.remove(object) == PRESENT;    }    /*和hashmap的clear的实现步骤是一样的*/    public void clear() {    map.clear();    }    /*基本上都是直接用的hashmap的clone方法*/    public Object clone() {    HashSet hashset_0_;    try {        HashSet hashset_1_ = (HashSet) super.clone();        hashset_1_.map = (HashMap) map.clone();        hashset_0_ = hashset_1_;    } catch (CloneNotSupportedException clonenotsupportedexception) {        throw new InternalError();    }    return hashset_0_;    }    private void writeObject(ObjectOutputStream objectoutputstream)    throws IOException {    objectoutputstream.defaultWriteObject();    objectoutputstream.writeInt(map.capacity());    objectoutputstream.writeFloat(map.loadFactor());    objectoutputstream.writeInt(map.size());    Iterator iterator = map.keySet().iterator();    while (iterator.hasNext())        objectoutputstream.writeObject(iterator.next());    }    private void readObject(ObjectInputStream objectinputstream)    throws IOException, ClassNotFoundException {    objectinputstream.defaultReadObject();    int i = objectinputstream.readInt();    float f = objectinputstream.readFloat();    map = (this instanceof LinkedHashSet           ? (HashMap) new LinkedHashMap(i, f) : new HashMap(i, f));    int i_2_ = objectinputstream.readInt();    for (int i_3_ = 0; i_3_ < i_2_; i_3_++) {        Object object = objectinputstream.readObject();        map.put(object, PRESENT);    }    }}

分析完了hashmap和hashset的源码,我们来总结一下他们的遍历方式吧。
1:hashmap遍历的方式
第一种:
  Map map = new HashMap();
  Iterator iter = map.entrySet().iterator();
  while (iter.hasNext()) {
  Map.Entry entry = (Map.Entry) iter.next();
  Object key = entry.getKey();
  Object val = entry.getValue();
  }
  效率高,以后一定要使用此种方式!

第二种:
  Map map = new HashMap();
  Iterator iter = map.keySet().iterator();
  while (iter.hasNext()) {
  Object key = iter.next();
  Object val = map.get(key);
  }
  效率低,以后尽量少使用!
2:hashset的遍历方式
hashset遍历的方式很单一,就是直接使用迭代器来遍历

Set set = new HashSet(); //集合都可以用Iterator来遍历
Iterator it = set.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
}
hashmap和hashset的源码和分析就到这里了,第一次写博客,可能有很多地方写的不好,要是有写的不对的地方,欢迎前来指正!谢谢!

原创粉丝点击