java基础-集合底层原理分析

java集合框架主要包括两种类型的集合容器:

一、Collection

存储一个元素的。它又包含三个子类型:List、Set、Queue

List:可以存储重复的数据、有序的

List常用的类是ArrayList和LinkedList

ArrayList是基于数组存储数据,其原理是当调用add()方法,先计算容器的大小,重新new一个新的数组大小,并将当前的数组所有元素复制到这个新的数组中,然后将最新的值放入数组的最后一个

LinkedList是基于双向链表结构存储数据,,其原理是链表由每一个节点node构成,每一个节点包含前节点信息、业务数据息以及后节点 信息;包含两个指针,一个指针是指向下一个结点的,另一个指针当然就是指向上一个结点的。这样的链表就可以通过第一个结点找到最后一个结点,当然也可以通过最后一个结点找到第一个结点,所以它是双向的

Set:存储的数据不能重复,无序的

Set有三个比较常用的类是散列集HashSet、链式散列集LinkedHashSet和树形集TreeSet

HashSet实现原理:Set底层实际上是一个HashMap,由于HashMap的put()方法是一个键值对,当新放入HashMap的Entry中key 与集合中原有Entry的key相同(hashCode()返回值相等,通过equals比较也返回true),新添加的Entry的value会将覆盖原来Entry的value,但key不会有任何改变。因此如果向HashSet中添加一个已经存在的元素时,新添加的集合元素将不会被放入HashMap中,原来的元素也不会有任何改变,这也就满足了Set中元素不重复的特性。 

LinkedHashSet实现原理:LinkedHashSet底层实际上是一个LinkedHashMap 

Queue:是一种特殊的线性表,它只允许在对头进行删除操作,在对尾进行添加操作。采用“先进先出”的原则进行操作

add  增加一个元索                     如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove    移除并返回队列头部的元素    如果队列为空,则抛出一个NoSuchElementException异常
element   返回队列头部的元素             如果队列为空,则抛出一个NoSuchElementException异常
offer        添加一个元素并返回true       如果队列已满,则返回false
poll          移除并返问队列头部的元素    如果队列为空,则返回null
peek         返回队列头部的元素             如果队列为空,则返回null
put           添加一个元素                      如果队列满,则阻塞
take         移除并返回队列头部的元素     如果队列为空,则阻塞

二、Map

存储键值对映射;常用的有三个子类:HashMap、LinkedHashMap以及TreeMap

HashMap实现原理:是基于哈希表实现的,是一个“链表散列”的数据结构,即数组和链表的结合体。首先,HashMap类的属性中定义了Entry类型的数组。Entry类实现java.ultil.Map.Entry接口,同时每一对key和value是作为Entry类的属性被包装在Entry的类中。

hashmap实际上是一个数组+链表的数据结构,hashmap底层是一个数组结构,数组中每一项又是一个链表结构。链表是为了解决hash冲突。

如图所示,HashMap的数据结构:

java基础-集合底层原理分析_第1张图片

可以看出,HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。table数组的元素是Entry类型的。每个 Entry元素其实就是一个key-value对,并且它持有一个指向下一个 Entry元素的引用,这就说明table数组的每个Entry元素同时也作为某个Entry链表的首节点,指向了该链表的下一个Entry元素,这就是所谓的“链表散列”数据结构,即数组和链表的结合体。

关于hashCode作用:

在集合中,每次添加一个新的元素的时候都要判断该元素是否重复,判断一个元素是否重复采用的是Object.equal()方法,这就造成一个如果一个集合里面本来就有10000个元素,如果添加一个新的元素进去就要进行10000次的比对,这样性能非常低下。于是java就采用哈希表的原理,哈希算法也称为散列算法。当添加一个新的元素时,将对象使用hash算法获得hash值,然后将hash值和集合长度进行&操作,获得该元素在数组中所存放的索引。如果这个元素上没有元素就直接将该元素存放在这里。如果该元素上有值,就调用equal值进行比对,如果相同就不存入,如果不相同就表示发生冲突了,散列表对于冲突有具体的解决办法,但最终还会将新元素保存在适当的位置。

这样一来,实际调用equals方法比较的次数就大大降低了,几乎只需要一两次。

Java对象的eqauls方法和hashCode方法是这样规定的:
1、相等(相同)的对象必须具有相等的哈希码(或者散列码)。
2、如果两个对象的hashCode相同,它们并不一定相同。

LinkedHashMap:LinkedHashMap是HashMap的子类,实现结构和HashMap类似,只是HashMap中的链表是单向链表,而LinkedHashMap是双向链表,只是在在HashMap的基础上加上了排序实现。

TreeMap底层采用打的红黑树算法

你可能感兴趣的:(java基础)