当前位置: 首页 > article >正文

B站宋红康JAVA基础视频教程(chapter14数据结构与集合源码)

文章目录

      • 1.List实现类源码分析
        • 1.1 各个实现类的特点
        • 1.2.ArrayList源码分析
          • 1.2.1 jdk7版本
          • 1.2.2 jdk1.8版本
        • 1.3.Vector源码分析(jdk1.8为例)
        • 1.4.LinkedList源码分析(jdk1.8)
      • 2.Map实现类源码分析
        • 2.1各个实现类的特点
        • 2.2HashMap源码分析
        • 2.3 LinkedHashMap源码分析
        • 2.4 HashSet底层源码分析

1.List实现类源码分析

1.1 各个实现类的特点

1.ArrayList的特点:

实现List接口,存储有序的,可以重复的数据
底层使用Object数组
线程不安全的

2.Vector的特点

实现List接口,存储有序的,可以重复的数据
底层使用Object数组
线程安全的

3.LinkedList的特点

实现List接口,存储有序的,可以重复的数据
底层使用双向链表存储
线程不安全的

1.2.ArrayList源码分析
1.2.1 jdk7版本
// 底层初始化一个长度为10的数组
ArrayList<String> list = new ArrayList<>(); // Object[] elementData = new Object[10]; 
list.add("AA");  // elementData[0] = "AA"
list.add("BB"); // elementData[1] = "BB"

当要添加第11个元素的时候,底层的elementData数组已满,则需要扩容,默认扩容为原来长度的1.5倍,并将原有数组中的元素赋值到新数组中

1.2.2 jdk1.8版本
// 底层会初始化一个数组
ArrayList<String> list = new ArrayList<>(); // Object[] elementData = new Object[]{}; 
list.add("AA");  //首次添加元素时,会初始化数组elementData=new Object[10]; elementData[0] = "AA"
list.add("BB"); // elementData[1] = "BB"

当要添加第11个元素的时候,底层的elementData数组已满,则需要扩容,默认扩容为原来长度的1.5倍,并将原有数组中的元素赋值到新数组中
注意ArrayList也可以创建指定长度的数组

1.3.Vector源码分析(jdk1.8为例)
Vector v = new Vector(); // 底层初始化数组,长度为10 Object[] elementData = new Object[10];
v.add("AA"); elementData[0] = "AA"
v.add("BB"); elementData[1] = "BB"

当要添加第11个元素的时候,底层的elementData数组已满,则需要扩容,默认扩容为原来长度的2倍,并将原有数组中的元素赋值到新数组中

1.4.LinkedList源码分析(jdk1.8)
LinkedList<String> list = new LinkedList<>(); // 底层没干啥
list.add("AA"); // “AA”封装到一个Node对象1中,list的对象属性first,last都指向此Node对象1
list.add("BB"); // “BB”封装到一个Node对象2中,对象1和对象2构成一个双向链表,同时last指向Node对象2

因为LinkedList使用的是双向链表,不需要扩容

2.Map实现类源码分析

2.1各个实现类的特点

1.HashMap中元素的特点

所有的key不可重复,无序的。所有的key就构成一个set集合。
所有的value是可重复,无序的。所有的value构成一个Collection集合
一个key-value构成一个entry
HashMap的所有entry彼此之间是不可重复的,无序的,所有的entry构成一个Set集合

2.2HashMap源码分析
// 创建对象过程中,底层会初始化数组Entry[] table = new Entry[16]; 2^4=16
HashMap<String, Integer> map = new HashMap<>();
map.put("AA", 78) // "AA"和78封装到一个Entry对象中,考虑将此对象添加到table中

添加/修改的过程:(面试高频题
将(key1, value1)添加到当前map中

  • 首先,调用key1所在类的hashcode方法,计算key1对应的哈希值1,此哈希值1经过某种算法(hash())后,得到哈希值2。
    哈希值2再经过某种算法(indexFor())之后,就确定了(key1, value1)再数组table中的索引位置i
    1.1 如果此索引位置i的数组上没有元素,则(key1,value1)添加成功。—>情况1
    1.2 如果此索引位置i的数组上有元素(key2, value2),则需要继续比较key1,key2的哈希值2 —>哈希冲突
    • 如果key1的哈希值2和key2的哈希值不相同,则(key1,value1)添加成功 —>情况2
    • 如果key1的哈希值2和key2的哈希值相同,则需要继续比较key1和key2的equals()方法。调用key1所在类的equals()方法,将key2作为参数传递进去 —>情况3
    • 调用equals()方法,返回false:则(key1, value1)添加成功
    • 调用equals()方法,返回treu,则认为key1和key2是相同的。默认情况下value1替换value2

说明:
情况1:将(key1.value1)存放到数组的索引i位置
情况2,情况3:(key1,value1)和(ke2,value2)构成单向链表结构。(key1,value1)指向(key2,value2)

随着元素的不断添加,在满足如下的条件情况下,会考虑扩容
(size>=threshold) && (null != table[i])
当元素个数达到临界值(数组长度*加载因子),就考虑扩容。默认临界值16 * 0.75 = 12
默认扩容为原来的两倍
在这里插入图片描述

2.3 LinkedHashMap源码分析

1.LinkedHashMap和HashMap之间得关系

LinkedHashMap是HashMap得子类
LinkedHashMap在HashMap使用得数组+单向链表+红黑树得基础上,又增加了一对双向链表,记录添加得(key,value)先后顺序。便于遍历所有得key-value

2.4 HashSet底层源码分析

HashSet底层用的是HashMap
LinkedHashSet底层使用的是LinkedHashMap


http://www.kler.cn/a/304710.html

相关文章:

  • jmeter常用配置元件介绍总结之定时器
  • 深度学习代码笔记
  • 深入探讨 MySQL 配置与优化:从零到生产环境的最佳实践20241112
  • 金价大跌,特朗普胜选或成导火索
  • ubuntu cmake CPack将第三方库进行打包
  • OpenGL【C++】台灯
  • 图文检索(1):Rethinking Benchmarks for Cross-modal Image-text Retrieval
  • DORIS - DORIS之倒排索引
  • 【实践】应用访问Redis突然超时怎么处理?
  • FastAPI 应用安全加固:HTTPSRedirectMiddleware 中间件全解析
  • OpenStack × OceanBase: 打造高可用可扩展的基础设施平台
  • ARM驱动学习之4小结
  • Docker高级管理--Compose容器编排与私有仓库(Docker技术集群与应用)
  • 使用Spring Boot集成Nacos进行配置管理
  • rocky8安装docker步骤
  • Apple Watch Series 10 動手玩:更大、更輕、更薄
  • 华为VRP系统基本操作
  • php 之 php-fpm 和 nginx结合使用
  • 使用Rustup快速无缝升级Rust
  • Mac快速复制和删除命令
  • Gitlab实现多项目触发式自动CICD
  • 时序预测 | Matlab实现GA-CNN遗传算法优化卷积神经网络时间序列预测
  • Java许可政策再变,Oracle JDK 17 免费期将结束!
  • 7.测试用例设计方法 + Bug
  • linux安全软件Hydra使用教程
  • 速盾:cdn节点越多越好吗?