dtcms 源码 远程桌面登陆 firebase swing email recursion dom Ractivejs Notify.js bootstrap后台模版 jq获取最后一个子元素 软件测试项目实战案例 etc文件夹 python正则 mysql函数 pythonfor循环 java的string java数据类型 java编译环境 java表达式 javastring类型 java语言代码大全 java获取ip地址 java实例变量 java遍历 java单继承 java创建文件夹 java的安装 linux系统简介 sql语句大全实例教程 flash实例教程 ip隐藏 两表关联查询 思源黑体cn tar解压 c4dr19 xapk安装器 安卓adb 视频后期处理软件 pr放大画面
当前位置: 首页 > 学习教程  > 编程语言

HashCode集合保证元素唯一性的源码分析

2020/8/11 19:45:50 文章标签:

相关源码:

//创建集合对象
HashSet<String> hs = new HashSet<>();

//添加元素
hs.add("hello");
hs.add("world");
hs.add("java");

//跟进add方法,其中调用了put方法
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

//跟进put方法,其中调用了hash方法和putVal方法
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

//跟进hash方法, 调用了hashCode方法, 返回元素的哈希值
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

//跟进putVal方法
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {

    //创建哈希表, 哈希表是一个元素为Node的数组
    Node<K,V>[] tab; Node<K,V> p; int n, i;

    //如果哈希表未初始化, 对哈希表初始化
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;

    //根据对象的哈希值计算对象的储存位置, 如果该位置没有元素, 就储存元素
    if ((p = tab[i = (n - 1) & hash]) == null)
        tab[i] = newNode(hash, key, value, null);
    else {
        Node<K,V> e; K k;
        /*
            存入的元素和以前的元素比较哈希值
                如果哈希值不同, 会继续向下执行, 把元素添加到集合
                如果哈希值相同, 会调用对象的equals()方法比较
                    如果返回false, 会继续向下执行
                    如果返回true, 说明元素重复,不储存
        */
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        else if (p instanceof TreeNode)
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
            for (int binCount = 0; ; ++binCount) {
                if ((e = p.next) == null) {
                    p.next = newNode(hash, key, value, null);
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        treeifyBin(tab, hash);
                    break;
                }
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    break;
                p = e;
            }
        }
        if (e != null) { // existing mapping for key
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
        }
    }
    ++modCount;
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
}

 哈希值和equals方法的搭配原理:

  • 哈希值不同,元素一定不同
  • 哈希值相同,元素不一定相同(碰撞现象),调用equals方法
    • equals返回true,元素相同
    • euqals返回false,元素不同

 


本文链接: http://www.dtmao.cc/news_show_100178.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?