package com.test1;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set; public class SetTest {
public static void main(String[] args) {
/*
* Set<String> set = new HashSet<>();
* System.out.println(set.add("abc"));
* System.out.println(set.add("xyz"));
* System.out.println(set.add("abc"));
*
* for (Iterator<String> it = set.iterator(); it.hasNext();) {
* System.out.println(it.next()); }
*/
/*
* String a = "abc"; String b = "abc"; System.out.println(a.hashCode());
* System.out.println(b.hashCode());
*/
Set<People> set2 = new HashSet<>();
set2.add(new People("zhangsan"));
set2.add(new People("lisi"));
set2.add(new People("zhangsan"));
for (Iterator<People> it = set2.iterator(); it.hasNext();) {
System.out.println(it.next().getName());
}
}
} class People {
String name; public People(String name) {
this.name = name;
} public String getName() {
return this.name;
} @Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof People) {
People people = (People) obj;
if(this.name.equals(people.getName()));
return true;
}
return false;
}
@Override
public int hashCode() {
return this.name.hashCode();
}
}

我们来看HashSet的构造方法:

  /**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
}

竟然是new HashMap<>();

关于HashSet与HashMap之间的关系:

HashSet是由HashMap来实现的。HashSet里面的几乎所有的方法都是由HashMap实现的

这个HashMap的key就是放进HashSet中的对象,value就是一个Object类型的对象,当调用HashSet的add方法时,实际上是向HashMap中增加了一行(key-value对),该key就是向HashSet中增加的那个对象,该行的value就是一个Object类型的对象。HashMap底层采用数组维护(数组中每个元素都是一个Map.Entry对象),调用增加的那个对象的hashCode方法,得到一个hashCode值,然后根据该值计算出一个数组的下标索引(计算出数组中的一个位置),将准备添加到Map中的对象与该位置处的对象进行比较(equals方法),如果相同,那么就向该位置处的那个对象(Map.Entry类型)的value值替换掉,否则沿着该Entry链继续重复上述过程,如果链的最后依然没有找到相同的对象,那么这个时候就将该对象添加到数组中,将数组中该位置处的Entry对象链接到这个对象后面:对于HashSet与HashMap来说,这样做是为了提高查找的效率,使得查找时间不随着Set或Map的大小而改变。

查看add方法

    /**
* Adds the specified element to this set if it is not already present.
* More formally, adds the specified element <tt>e</tt> to this set if
* this set contains no element <tt>e2</tt> such that
* <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
* If this set already contains the element, the call leaves the set
* unchanged and returns <tt>false</tt>.
*
* @param e element to be added to this set
* @return <tt>true</tt> if this set did not already contain the specified
* element
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

HashSet源码分析2的更多相关文章

  1. HashSet源码分析

    在java集合中有一种集合Set(集),他有两个实现类,分别是HashSet,TreeSet.下面仔细分析HashSet源码. 看了HashSet的源码就会发现HashSet的底层实现是利用HashM ...

  2. 死磕 java集合之HashSet源码分析

    问题 (1)集合(Collection)和集合(Set)有什么区别? (2)HashSet怎么保证添加元素不重复? (3)HashSet是否允许null元素? (4)HashSet是有序的吗? (5) ...

  3. 【Java入门提高篇】Day26 Java容器类详解(八)HashSet源码分析

    前面花了好几篇的篇幅把HashMap里里外外说了个遍,大家可能对于源码分析篇已经讳莫如深了.别慌别慌,这一篇来说说集合框架里最偷懒的一个家伙——HashSet,为什么说它是最偷懒的呢,先留个悬念,看完 ...

  4. HashSet源码分析:JDK源码系列

    1.简介 继续分析源码,上一篇文章把HashMap的分析完毕.本文开始分析HashSet简单的介绍一下. HashSet是一个无重复元素集合,内部使用HashMap实现,所以HashMap的特征耶继承 ...

  5. java.util.HashSet源码分析

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

  6. JAVA的HashSet源码分析

    一.HashSet概述 HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持.它不保证set的迭代顺序:特别是它不保证该顺序恒久不变.此类允许使用null元素. 二.HashS ...

  7. Java集合之HashSet源码分析

    概述 HashSet是基于HashMap来实现的, 底层采用HashMap的key来保存数据, 借此实现元素不重复, 因此HashSet的实现比较简单, 基本上的都是直接调用底层HashMap的相关方 ...

  8. HashSet源码分析 jdk1.6

    Set的特点:Set元素无顺序,且元素不可以重复. 1.定义 public class HashSet<E> extends AbstractSet<E> implements ...

  9. HashSet源码分析1

    import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class SetTest { pu ...

随机推荐

  1. javascript动态创建div循环列表

    动态循环加载列表,实现vue中v-for的效果 效果图: 代码: var noApplicationRecord = document.getElementById('noApplicationRec ...

  2. wget安装更新

    #查看当前wget版本信息 wget -V #下载 wget https://ftp.gnu.org/gnu/wget/wget-1.19.tar.gz #解压 tar xvf wget-1.19.t ...

  3. 迅为IMX6UL开发板

    迅为iMX6UL开发板采用核心板加底板形式,核心板使用邮票孔方式连接,牢固耐用.处理器ARM®Cortex®-A7内核,运行速度高达528 MHz.512MDDR内存,8G EMMC存储,板截双网口, ...

  4. (转)hibernate-5.0.7+struts-2.3.24+spring-4.2.4三大框架整合

    http://blog.csdn.net/yerenyuan_pku/article/details/70040220 SSH框架整合思想 三大框架应用在JavaEE三层结构,每一层都用到了不同的框架 ...

  5. 前复权是从今天的价格倒推 后复权是从上市价格前推 不复权就是原始K线。

    前复权是从今天的价格倒推 后复权是从上市价格前推 不复权就是原始K线.

  6. linux crontab创建计划任务

    1.编辑计划任务 编辑crontab文件 crontab -e 2.查看计划任务日志 查看crontab日志 tail -100f /var/log/cron 3.创建计划任务格式 (1)基本格式 : ...

  7. wifi钓鱼之--Pumpkin

    无线钓鱼   前言:请准备一块rt3070的外接网卡 Pumpkin是一款无线安全检测工具WiFi-Pumpkin的使用,利用该工具可以伪造接入点完成中间人攻击,同时也支持一些其它的无线渗透功能.旨在 ...

  8. Java IO(四--字符流基本使用

    在上一节,介绍了字节流的基本使用,本节介绍一下字符流的使用 Reader: public abstract class Reader implements Readable, Closeable { ...

  9. android 获取application和activity下meta-data中的值

    meta-data在AndroidManifest中是以键值对的形式存在的,可以将meta-data放在application根节点下,也可以放在某个activity节点下.因为存放的位置不同,因此获 ...

  10. stark组件之处理函数动态url构造(五)

    在这个组件中有内置的4个处理函数,它们都有自己对应的url,那么它们的url是怎么构造的呢? ... urlpatterns = [ re_path('list/$', self.wrapper(se ...