java集合框架介绍,Set、Map,详细

本文详细介绍了Java集合框架中的Set接口,特别是HashSet的实现原理。Set接口存储唯一、无序的对象,其父类引用子类对象时,要求重写hashCode()和equals()方法以确保一致性。HashSet的内部结构是数组+链表,插入元素时依据哈希值决定位置,并可能形成链表。同时,文章还探讨了Map接口的实现,以HashMap为例,解释了键值对的存储方式,包括哈希表的构造、扩容机制以及红黑树的应用。Map中的key需要重写hashCode()和equals(),value则需重写equals()。

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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值