zoukankan      html  css  js  c++  java
  • HashSet集合的add()方法的源码

    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);
        }
    }
    //对应源码 addEntry(hash, key, value, i); //把元素添加
    void addEntry(int hash, K key, V value, int bucketIndex) {
        Entry<K,V> e = table[bucketIndex];
            table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
            if (size++ >= threshold)
                resize(2 * table.length);
        }
      hs.add("hello");//由于table里面没有,直接进addEntry
      hs.add(
      "world");//同上
      hs.add(
      "java");//同上
      hs.add(
      "world");//table里已经存在,(hash和equals相等),则在put()时,用新值替代老值。ps:这里的老值和新值都是world。

    总结:

    首先比较哈希值
        如果相同,继续走,比较地址值或者走equals()
        如果不同,就直接添加到集合中
    按照方法的步骤来说:
        先看hashCode()值是否相同
            相同:继续走equals()方法
                返回true:说明元素重复,就不添加
                返回false:说明元素不重复,就添加到集合
            不同:就直接把元素添加到集合
    如果类没有重写这两个方法,默认使用的Object()。一般磊说不会相同。
    而String类重写了hashCode()和equals()方法,所以,它就把内容相同的字符串去掉,只留下一个。

  • 相关阅读:
    malloc函数具体解释
    GeeksforGeeks
    debugging python with IDLE
    sqlplus登录问题
    SNMP协议具体解释
    MP4文件格式具体解释——结构概述
    【C++模版之旅】项目中一次活用C++模板(traits)的经历
    简单的REST的框架实现
    23种设计模式(3):抽象工厂模式
    给字符数组赋值的方法
  • 原文地址:https://www.cnblogs.com/qq-757617012/p/4285627.html
Copyright © 2011-2022 走看看