Java 总结 数据底层原理 【包括 ArrayList、LinkedList、hash table、HashMap、Hashtable、ConcurrentHashMap、hash code、HashSet、LinkedHashMap、LinkedHashSet】

1.ArrayList

(1)底层是由动态数组实现的【使用了List接口】。
(2)动态数组是长度不固定,随着数据的增多而变长。
(3)如果不指定,默认长度为10,当添加的元素超过当前数组的长度时,会创建新的数组,新数组长度是当前数组的1.5倍,然后当前数组的元素复制到新的数组后,当前数组的内存被释放。
(4)存储和删除的效率比较低,但是查询的效率非常高。
(5)没有锁,因此是线程不安全的,因此是非同步的。

2.LinkedList

(1)底层是由双向链表的数据结构实现的【使用了List接口】,
因此存储和删除的效率非常高,但是查询需要从头按顺序找,因此效率比较低。
(2)即便使用了二分查找【分两半查找,先判断index是在链表的哪一半,然后再去对应区域查找,这样最多只要遍历链表的一半节点即可找到】,但速度远比arraylist慢得多
(3)没有锁,因此是线程不安全的,因此是非同步的。

3.hash table

(1)哈希表,也叫散列表,是根据关键码值直接访问的数据结构。
(2)通过把关键码值映射到表中一个位置来访问记录,以加快查找速度。
(3)那么这个映射函数叫做散列函数,存放记录的数组叫做散列表。

4.HashMap

(1)键值都允许为null,是哈希表的Map接口实现,没有锁,因此是线程不安全的,是非同步的。
(2)底层是使用动态数组【使用Node[] ,不使用Entry[]存储键值对】和单向链表 组合实现的,也就是说,底层是节点数组,每个数组元素内部装有单向链表,
当链表长度大于一定值时,链表会转换成红黑树【jdk1.8后才有红黑树】,这样可以减少链表查询时间。
(3)动态的节点数组在扩容时,会新建一个数组,并把当前数据元素赋值到新数组中,这个过程很耗性能。
(4)存入数据时【也就是要存入一个Node对象】,会根据key的hash算法来决定存在数组
【Node[]】中的哪个位置,在该位置上【也就是在这个数组元素上】,再根据equals方法来决定存储在该位置链表的哪个位置。
(5)读取数据时【也就是取出一个Node对象】,会根据key的hash算法来找到其在数组中的存储位置,然后使用equals方法,从该位置的链表中找到该Node。

5.Hashtable

(1)键值都不允许为null,是哈希表的Map接口实现,线程安全,因为使用了同步锁synchronized,因此每次线程操作表时,会加锁,其他线程需要等待。
(2)底层是使用动态数组【Entry[],即键值对对象数组】和单向链表 组合实现的【与HashMap类似】,
也就是说,底层是Entry数组,每个数组元素内部装有单向链表。
(3)【存储数据和读取数据与HashMap十分类似】
存入数据时【也就是要存入一个Entry对象】,会根据key的hash算法来决定存在数组
【Entry[]】中的哪个位置,在该位置上【也就是在这个数组元素上】,再根据equals方法来决定存储在该位置链表的哪个位置。
读取数据时【也就是取出一个Entry对象】,会根据key的hash算法来找到其在数组中的存储位置,然后使用equals方法,从该位置的链表中找到该Entry。
(4)总体来说,与HashMap十分相似,区别在于线程是否安全、键值是否允许为null、
底层数组类型具体是什么、链表是否会转换成红黑树。
(5)注意Hashtable与hash table 单词写法,两个不是一个东西。

6.ConcurrentHashMap

(1)是线程安全的,内部分多个段,每个段其实就是个小的Hashtable也就是说,
每次线程操作段都要加锁,但是不同段互不影响,因此,如果是多线程操作不同的段,
则允许并发操作,此外,允许并发查询同一个段的内容,查询不需要加锁,
如果是对段做写操作则会加锁,线程同步阻塞。
(2)因为段使用了Hashtable,因此底层数组类型也是Entry[],具体的底部存储和读取实现也是与Hashtable相同。

7.hash code

(1)译为 哈希值 ,
(2)对象  相等则  哈希值  一定相等, 
(3)但 哈希值 相等,对象 不一定相等。

8.HashSet

(1)意为哈希集合,HashSet实现 Set接口 。
(2)底层是使用HashMap来存储数据的,各个操作实际上是调用了HashMap的方法来完成,因此HashSet元素是无序的。
(3)存储在HashSet的元素,实际上,将会存在HashMap的key里面,而值为一个固定的值【是什么无关紧要,但是必须统一固定】,每次添加新元素时,
  将会调用HashMap的put()方法,既然值时固定的,那么如果key已经存在,则HashMap不会再新建重复的元素,这就是HashSet存储数据不可重复的原因。

9.LinkedHashMap

(1)继承于HashMap,因此有HashMap的特点,非同步、允许键值为null等。
(2)通过重写HashMap相关方法,重新定义了数组中保存的元素Entry,每个元素除了保存当前对象的引用外,还保存了其上一个元素before和下一个元素after的引用,从而在哈希表的基础上又构成了双向链接列表。

10.LinkedHashSet

(1)意为 线性哈希集合。
(2)LinkedHashSet底层使用LinkedHashMap来保存所有元素。
(3)继承了HashSet,其所有的方法操作上又与HashSet相同。
原文地址:https://www.cnblogs.com/c2g5201314/p/13128714.html