Set接口:
Set接口存储一组唯一,无序的对象
父类引用子类对象: Set set=new HashSet(); HashSet是Set接口常用的实现类
实现类HashSet:作为Set接口的主要实现类;编程不安全;可以存储null值
Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法
add(Object e)
remove(Object obj)
contains(Object obj)
size()
要求:向Set中添加的数据,其所在的类一定要重写hashCode()和equals()
重写的hashCode()和equals()尽可能保持一致性,相等的对象必须具有相等的散列码
以HashSet为例
1.无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加
而是根据数据的哈希值决定
2.不可重复性:保证添加的元素按照equals()判断,不能返回true。即:相同的元素只能添加一个
添加元素的过程:
底层使用HashMap来保存HashSet中所有元素
定义一个虚拟的Object对象作为HashMap的value,将此对象定义为static final
我们向HashSet中添加元素a,首先调用元素a所在类的hashcode()方法,计算元素a的哈希值,
接着此哈希值通过某种算法计算出在HashSet底层数组中的存放位置(索引位置),判断数组中此位置中是否已经有此元素:
如果此位置上没有其他元素,则元素a添加成功 >> 情况1
如果此位置上有其他元素b(或者以链表形式存在的多个元素),则比较元素a和这些元素的hash值
如果哈希值不相同,则元素a添加成功 >> 情况2
如果哈希值相同,进而调用元素a所在类的equals()方法:
equals()返回true,元素a添加失败
equals()返回false,则元素a添加成功 >> 情况3
对于添加成功的情况2和情况3而言,元素a与已经存在指定索引位置上数据以链表的方式存储
7:元素a放在数组中,指向原来的元素
8 :原来的元素在数组中,指向元素a
(七上八下)
HashSet底层:数组+链表的结构
S2=S1 指向同一个对象
代码结果为:2
Set存放对象为引用,S1、S2指向的是同一个对象,值为1.
当加S3之后,值为2
Set接口采用对象的 equals()方法比较两个对象是否相等,判断加入对象是否存在,值为1
Map
使用Map存取数据
双列集合,用来存储一对具有映射关系“key-value”的数据 高中函数:y=f(x)
以HashMap为例
Map中的key:无序的、不可重复的,使用set存储所有的key
>>key所在类要重写equals()和hashCode()
Map中的Values:无序的、可重复的,使用Collection存储所有的value
>>values所在类要重写equals()
一个键值对:key-value构成一个Entry对象
Map中的entry:无序的、不可重复的,使用Set存储所有的entry
HashMap底层实现原理(以7为例)
HashMap map=new HashMap(); //实例化后,底层创建了长度为16的一位数组Entry[] table
map.put(key1,value1);
经过多次put
首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。
如果此位置上的位置为空,此时的key1-value1添加成功
如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或者多个数据的哈希值:
如果key1的哈希值与已经存在的哈希值都不相同,此时key1-value1添加成功 >> 情况2
如果key1的哈希值和已经存在的某一个数据的哈希值相同,继续比较:调用key1所在类的equals()
如果equals()返回false,此时key1-value1添加成功 >> 情况3
如果equals()返回true,使用value替换value2
对于添加成功的情况2和情况3而言,此时key1-value1和原来的数据以链表的形式存储
在不断添加的过程当中,会涉及扩容问题,当超出临界值12(且要存放的位置非空)时,扩容。默认的扩容方式:扩容到原来容量的2倍,并将原来的数据复制过来
8和7相比:
new HashMap()时,底层没有创建一个长度为16的数组
底层是的数组:Node[],而不是Entry[]
第一次调用.put()时,底层才创建了长度为16的数组
7的底层结构:数组+链表。8中的底层结构:数组+链表+红黑树
当数组的某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组的长度>64时
此时此索引位置上的所有数据改为红黑数存储
Map常用方法:
put(增加) remove(删除) get(查) putAll(put另外一个Map)
遍历方法: kyeset() entrySet() value()
本文详细介绍了Java集合框架中的Set接口,特别是HashSet的实现原理。Set接口存储唯一、无序的对象,其父类引用子类对象时,要求重写hashCode()和equals()方法以确保一致性。HashSet的内部结构是数组+链表,插入元素时依据哈希值决定位置,并可能形成链表。同时,文章还探讨了Map接口的实现,以HashMap为例,解释了键值对的存储方式,包括哈希表的构造、扩容机制以及红黑树的应用。Map中的key需要重写hashCode()和equals(),value则需重写equals()。

2611

被折叠的 条评论
为什么被折叠?



