首先将源码逐级找出来
1.HashSet<String> hs=new HashSet<String>();
        hs.add("hello");
        hs.add("world");
        hs.add("java");
        hs.add("world");//因为是Set集合所以不带重复元素
因为调用的是HashSet集合中的add方法,所以我们要找出来add方法
2. public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
通过add方法我们可以看出它调用了一个put方法,我们在找出来
3.public V put(K key, V value) {
      return putVal(hash(key), key, value, false, true);
  }
然后我们可以看到它里面调用了一个putVal方法,然后第一个参数还是个hash方法,那我们就把两个方法一次拿出来
4. static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    //hash值和元素的hashCode()方法有关
5.final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                    boolean evict) {
        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;
    }

HashSet集合添加一个元素的过程:

1.调用HsahSet集合对象的hashCode()方法获取哈希值

2.根据对象的哈希值计算对象的存储位置

3.判断该位置是否已有元素存在

没有:就将该元素存储在此位置

有:遍历该位置的所有元素,并和新存入的元素比较哈希值是否相同

不相同:将元素存入该位置

相同:调用对象的equals()方法进行比较

相同:说明该元素重复,不用存储

不相同:将元素存入该位置

4.结束

Java思考——HashSet集合如何保证元素的唯一性也就是不包含重复元素?的更多相关文章

  1. [LeetCode] 219. Contains Duplicate II 包含重复元素 II

    Given an array of integers and an integer k, find out whether there are two distinct indices i and j ...

  2. [LeetCode] 220. Contains Duplicate III 包含重复元素 III

    Given an array of integers, find out whether there are two distinct indices i and j in the array suc ...

  3. [LeetCode] 217. Contains Duplicate 包含重复元素

    Given an array of integers, find if the array contains any duplicates. Your function should return t ...

  4. 从n个元素中选择k个的所有组合(包含重复元素)

    LeetCode:Combinations这篇博客中给出了不包含重复元素求组合的5种解法.我们在这些解法的基础上修改以支持包含重复元素的情况.对于这种情况,首先肯定要对数组排序,以下不再强调 修改算法 ...

  5. JS 验证数组中是否包含重复元素

    验证JS中是否包含重复元素,有重复返回true:否则返回false 方案一. function isRepeat(data) { var hash = {}; for (var i in data) ...

  6. Java 之 HashSet 集合

    一.概述 java.util.HashSet  是 Set 接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致). java.util.HashSet 底层的实现是一个 ...

  7. leetcode-两个数组交集(包含重复元素)

    Python解法代码: class Solution: def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]: ...

  8. leetcode350之实现求解两数组交集(包含重复元素)

    给定两个数组,编写一个函数来计算它们的交集. 说明: 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致. 我们可以不考虑输出结果的顺序 def binarySearch(nums, t ...

  9. Java中的集合框架

    概念与作用 集合概念 现实生活中:很多事物凑在一起 数学中的集合:具有共同属性的事物的总体 java中的集合类:是一种工具类,就像是容器,储存任意数量的具有共同属性的对象 在编程时,常常需要集中存放多 ...

随机推荐

  1. Python基础—基础数据类型list(Day4)

    基础数据类型 四.list列表  存放大量数据,大量的数据在列表中便于操作,列表示有序的,有索引值,可切片,方便取值.  1.list的增    1).append('元素') 在列表后面按元素添加 ...

  2. vue的事件监听

    <div id="app"> <button type="button" @click="btnClick(a,$event)&qu ...

  3. 拒绝for循环,从take_along_axis开始

    技术背景 在前一篇文章中,我们提到了关于Numpy中的各种取index的方法,可以用于取出数组里面的元素,也可以用于做切片,甚至可以用来做排序.但是遇到对于高维矩阵的某一个维度取多个值的时候,单纯的使 ...

  4. Go Exec 僵尸与孤儿进程

    原文地址:Go Exec 僵尸与孤儿进程 最近,使用 golang 去管理本地应用的生命周期,期间有几个有趣的点,今天就一起看下. 场景一 我们来看看下面两个脚本会产生什么问题: 创建两个 shell ...

  5. [自动化]ansible-系统安全加固整改

    基线漏洞安全整改 修复环境:centos7及以上 安全基线的概念 安全基线是一个信息系统的最小安全保证,即该信息系统最基本需要满足的安全要求.信息 系统安全往往需要在安全付出成本与所能够承受的安全风险 ...

  6. Linux提权之信息收集

    1.操作系统版本 2.目标操作系统什么内核?多少位系统? 3.环境变量历史记录是否有利用? 4.运行了哪些服务和进程 top命令 5.安装了什么程序? 6.是否可以查看到root用户运行的进程 7.查 ...

  7. BGP协议测试—信而泰网络测试仪实操

    关键词  BGP; 协议仿真; 测试原理. 前言:当前信息化时代之下,数据传输已经成为了日常工作和生活必不可少的重要组成部分,网络服务的易得性和可靠性也因此得到广泛关注.这其中负责网络正常工作的诸多协 ...

  8. 金融行业BI可视化报表,直观体验数据的价值

    现在,数据已成为非常重要的资产.之前,人们只是把它当作一种附属品,由客户来办理业务,在系统中产生了这样的附属品.但如今,发现在客户办理业务这一信息中,蕴藏着一些客户的需求,积聚成千条这种信息,可以洞察 ...

  9. 【C# 异常处理】 开端

    异常概述 在使用计算机语言进行项目开发的过程中,即使程序员把代码写得尽善尽美,在系统的运行过程中仍然会遇到一些问题,因为很多问题不是靠代码能够避免的,比如:客户输入数据的格式,读取文件是否存在,网络是 ...

  10. UML 包图 详细介绍

      6.1 包图的概念 包是一种常规用途的组合机制.UML中的一个包直接对应于Java中的一个包,C#中的命名空间.在Java中,一个包可能含有其他包.类或者同时含有这两者.进行建模时,通常使用逻辑性 ...