• 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相同。
  • 相关阅读:
    年末反思
    Flink运行时架构
    Phoenix 启动报错:Error: ERROR 726 (43M10): Inconsistent namespace mapping properties. Cannot initiate connection as SYSTEM:CATALOG is found but client does not have phoenix.schema.
    Clickhouse学习
    Flink简单认识
    IDEA无法pull代码到本地,Can't Update No tracked branch configured for branch master or the branch doesn't exist.
    第1章 计算机系统漫游
    简单的 Shell 脚本入门教程
    开源≠免费 常见开源协议介绍
    MySQL 视图
  • 原文地址:https://www.cnblogs.com/c2g5201314/p/13128714.html
Copyright © 2020-2023  润新知