1. List接口和常用方法

1.1 List接口基本介绍

1、返回集合长度

int size()

2、添加元素

void add(Object ele), void add(int index, Object ele)

3、添加多个元素

boolean addAll(int index, Collection eles)

4、获取指定index位置的元素

Object get(int index)

5、返回obj在集合中首次出现的位置

int indexOf(Object obj)

6、返回obj在集合中末次出现的位置

int lastIndexOf(Object obj)

7、移除指定index位置的元素,并返回此元素

Object remove(int index)

8、设置指定index位置的元素为ele,相当于替换,索引必须存在

Object set(int index, Object ele)

9、返回从fromIndex到toIndex位置的子集合,前闭后开

List subList(int fromIndex, int toIndex)

1.2 List接口的三种遍历方式

2. ArrayList

2.1 注意事项

2.2 ArrayList的底层操作机制源码分析(重点)

使用无参构造器

  • 可以看出elementData一开始是个空数组



  • 执行list.add(i)时,会先把int类型的i转化为Integer类型

  • 然后执行add方法,首先确认数组大小够不够,然后再对数组元素赋值

  • 如何确认数组大小够不够呢

    • 当数组为空时

      • 先设置数组需要的最小长度minCapacity为10
      • 然后判断数组需要的最小长度是否大于数组长度,此时一定大于,因为数组长度为0
      • 大于则扩容
    • 当数组不为空时
      • 先计算数组所需要的最小长度,即索引的位置+1,minCapacity=size+1
      • 然后计算当前数组的长度elementData.length
      • 判断数组所需的最小长度是否大于当前数组长度,大于则扩容(即当索引+1超出数组长度时,扩容)
    • 其中modCount用来记录集合被修改的次数



  • 如何扩容呢-调用grow函数

    • 当第一次扩容,即数组为空时,elementData.length=0

      • 通过位运算计算得到的newCapacity还是0,所以需要加个判断条件,给newCapacity赋值为minCapacity
      • 然后使用Arrays的copyOf方法进行数组扩容
    • 当不是第一次扩容时
      • 根据位运算在原来数组长度上扩大1.5倍得到,向下取整,newCapacity
      • 然后使用Arrays的copyOf方法进行数组扩容

使用有参构造器

  • 首先创建一个指定大小elementData数组

  • 其它流程在无参构造器中以出现,不再重复

总结

  • 关键是维护一个elementData数组,当new一个对象时,

    • 使用无参构造时,它为空数组
    • 使用有参构造时,它的长度为传入的参数值,并且给elementData new一个长度为参数大小的数组
  • 当使用add方法时,首先会计算容器所需要的最小容量是多少,即minCapacity
    • 如果是空数组,设置最小容量为10
    • 如果不是,最小容量就是索引位置+1(size+1)
  • 然后判断这个最小容量是否大于数组长度
    • 如果大于,就说明要扩容了
    • 如果小于,什么也不干
  • 扩容时,扩容大小使用位操作计算,当前容量+右移一位,(右移一位会小一半),所以扩大1.5倍
    • 但是当容量为0时,0右移一位还是0,所以加了一个判断,给这个容量直接赋值为10

关键是维护一个elementData数组,如果是无参构造,一开始将elementData数组初始化为空数组,当执行添加操作时,需要第一次扩容到10,后面按1.5倍扩容;如果是有参构造,一开始将elementData的大小初始化为参数值,之后每次扩容按1.5倍扩,扩容是创建一个新数组,然后调用一个本地方法将原来数组的值复制到新数组

3. Vector

3.1 基本介绍

3.2 Vector与ArrayList的比较

3.3 源码分析

  • 首先通过构造方法设置数组初始容量,并创建一个指定长度的数组

    • 无参构造器默认设置初始容量为10

    • 有参构造器根据指定数值设置容量,扩容增量默认为0
    • 还可以自己设置扩容增量
  • 然后对int类型自动装箱

  • 接着执行add方法

    • 首先确认当前的容量大小是否需要扩容



    • 如果需要扩容,且设置了扩容增量capacityIncrement的话,就扩容这个值的大小,如果没设置扩容增量,就扩容原来的两倍

  • 最后将数据添加到Vector集合中

3.4 总结

  • 如果是无参构造,直接默认创建一个初始容量为10的数组,之后每次需要扩容时,扩大两倍
  • 如果是有参构造,创建初始容量为指定值的数组,如果设置了扩容增量,之后每次扩容时,扩容后的大小等于当前容量+扩容增量,如果没设置扩容增量,则扩容两倍。

4. LinkedList

基本介绍



源码分析

add()函数

  • 首先通过无参构造方法初始化属性



  • 对int类型自动装箱后,执行add方法

  • 其中最关键的方法是linkLast方法

    • 当linkList中没有元素时

      • 首先创建临时节点,使用l记录last的位置
      • 然后创建新节点,让它的pre指向临时节点、next指向null
      • 更新双指针的位置,将last和first都指向该新节点
    • 当linkList中有元素时
      • 首先创建临时节点,使用l记录last的位置
      • 然后创建新节点,让它的pre指向临时节点、next指向null
      • 然后让临时节点的next指针指向新节点
      • 大概思路是更新新节点和原来最后一个节点之间的pre和next指针指向

remove()函数

  • 删除节点默认删除第一个节点



  1. 首先它直接调用了removeFirst()方法



  2. 真正删除第一个节点的方法是unLinkFirst()

  • 首先使用临时变量保存原来first指向的节点 的元素值和next指针
  • 清空原来first指向的节点 的元素值和next指针
  • 改变first指针指向临时变量保存的next指针(即原来第二个节点)
    • 但next可能为null(即原list只有一个节点的情况)

      • 此时将last指针也指向null
    • 当next不为null
      • 将next指针(即新的第一个节点)的prev指向null
  • 此时已实现first指向原第二个节点,如果第二个节点为null,first和last都指向null
  • 最后返回删除的节点的元素值

总结:

  • 新增节点:先用临时变量记录最后一个节点,然后创建一个新节点,将新节点连接到原来链表上(新节点的pre指针指向临时节点,next指针指向null,最后临时节点的next指针指向新节点),更新last的位置,如果原来为空,还要将first也指向这个节点
  • 删除节点:先用临时节点保存第一个节点,然后清空第一个节点next指针和元素值,将firs指向第二个节点,如果这个节点为空,将last也指向它;
  • 总结:先用临时变量保存需要处理的节点,然后再处理该节点,特殊情况是只有一个节点或没有节点的时候,此时两个指针都要移动。

5. List集合选择

  • ArrayList可以通过索引直接定位
  • linkedlist通过遍历查找

    注意:线程都是不安全的

    补充:

    Alt+7:查看当前类的所有方法

Set接口



  • 常用方法和遍历方式

  • 存放顺序和取出顺序不一致,但是取出顺序是固定的

  • set接口对象不能通过索引获取,它没有get方法

HashSet



  • 注意:是当一条链表的个数达到8个,同时table元素达到64个,才会树化
  • 当一条链表达到8个了,但是元素少数64个,table会扩容

  • 扩容时,不是数组里的元素达到阈值才扩容,而是所有元素数量(包括链表上的)达到阈值就会扩容

HashSet的底层就是HashMap,只是在HashSet里,value是存放的一个常量对象,平时的操作只用key

当添加元素时,

Map接口

Node实现了Entry接口,Entry接口里有getKey和getValue方法,然后EntrySet集合里存放着Node类型的对象(多态)

遍历方式

  • 第一组:先取出所有的key,通过key取出对应的value

  • 第二组:把所有的value取出
  • 第三组:通过EntrySet 来获取 k-v

小结

HashMap底层

HashMap扩容机制

源码

  1. 执行构造器 new HashMap()

  2. 执行put,调用hash方法
  3. 执行putVal
  4. 关于转成红黑树

HashTable









集合选择

List、Set与 Map的更多相关文章

  1. mapreduce中一个map多个输入路径

    package duogemap; import java.io.IOException; import java.util.ArrayList; import java.util.List; imp ...

  2. .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法

    .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法 0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到 ...

  3. Java基础Map接口+Collections工具类

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  4. Java基础Map接口+Collections

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  5. 多用多学之Java中的Set,List,Map

            很长时间以来一直代码中用的比较多的数据列表主要是List,而且都是ArrayList,感觉有这个玩意就够了.ArrayList是用于实现动态数组的包装工具类,这样写代码的时候就可以拉进 ...

  6. Java版本:识别Json字符串并分隔成Map集合

    前言: 最近又看了点Java的知识,于是想着把CYQ.Data V5迁移到Java版本. 过程发现坑很多,理论上看大部分很相似,实践上代码写起来发现大部分都要重新思考方案. 遇到的C#转Java的一些 ...

  7. MapReduce剖析笔记之八: Map输出数据的处理类MapOutputBuffer分析

    在上一节我们分析了Child子进程启动,处理Map.Reduce任务的主要过程,但对于一些细节没有分析,这一节主要对MapOutputBuffer这个关键类进行分析. MapOutputBuffer顾 ...

  8. MapReduce剖析笔记之七:Child子进程处理Map和Reduce任务的主要流程

    在上一节我们分析了TaskTracker如何对JobTracker分配过来的任务进行初始化,并创建各类JVM启动所需的信息,最终创建JVM的整个过程,本节我们继续来看,JVM启动后,执行的是Child ...

  9. MapReduce剖析笔记之五:Map与Reduce任务分配过程

    在上一节分析了TaskTracker和JobTracker之间通过周期的心跳消息获取任务分配结果的过程.中间留了一个问题,就是任务到底是怎么分配的.任务的分配自然是由JobTracker做出来的,具体 ...

  10. MapReduce剖析笔记之三:Job的Map/Reduce Task初始化

    上一节分析了Job由JobClient提交到JobTracker的流程,利用RPC机制,JobTracker接收到Job ID和Job所在HDFS的目录,够早了JobInProgress对象,丢入队列 ...

随机推荐

  1. 暗黑2能用Java开发?还能生成APP?

    最近烧哥发现个宝藏项目,竟然用Java开发了暗黑2出来. 众所周知,暗黑2是暴雪开发的一款经典游戏,距今虽有20多年,仍然有很多粉丝. 粉丝延续热情的方式有很多,一种是做Mod,比如魔电,对怪物.技能 ...

  2. 使用SpringBoot+React搭建一个Excel报表平台

    摘要:本文由葡萄城技术团队于博客园原创并首发.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 Excel报表平台是一款功能强大.操作简单的系统平台,可 ...

  3. Oracle分区表设置详解

    Oracle分区表详解 Oracle建议单表超过2G就需要进行分表,一万数据大概3MB,单表最多分区为1024*1024-1个分区,我感觉够我们使用了哈 废话不多说,上示例,Oracle分表具体sql ...

  4. 【MAUI Blazor踩坑日记】2.关于Windows上的相机问题

    前言 本系列文章,默认你已经踏上了MAUI Blazor的贼船,并且对MAUI Blazor有了一些了解,知道MAUI是什么,知道Blazor是什么. 不会教你怎么写MAUI Blazor的项目,只是 ...

  5. 20.1K Star!Notion的开源替代方案:AFFiNE

    Notion这款笔记软件相信很多开发者都比较熟悉了,很多读者,包括我自己都用它来记录和管理自己的笔记.今天给大家推荐一个最近比较火的开源替代方案:AFFiNE.目前该开源项目已经斩获20.1K Sta ...

  6. pandas 删除重复项

    使用如下函数: drop_duplicates 具体示例如下: import pandas as pd # 建立一个dataframe数据 df = pd.DataFrame({'k1':['one' ...

  7. ACl与ACL实验

    ACl与ACL实验 ACL 1,ACL概述及 产生的背景 ACL: access list 访问控制列表 2,ACL应用 ACL两种应用: 应用在接口的ACL-----过滤数据包(原目ip地址,原目 ...

  8. SQL-去除最大值与最小值求均值的问题

    背景 今天有同事问我一道关于数据库SQL的面试题,我刚开始随便给了一个思路,后来思索发现这个思路有漏洞,于是总结下来,仅供参考. 问题: 薪水表中是员工薪水的基本信息,包括雇员编号,和薪水,查询除去最 ...

  9. JavaScript 基础(1) - 笔记

    1 JavaScript基础 1.1 JavaScript 是什么 1.JavaScript(是什么?) 是一种运行在客户端(浏览器)的编程语言,实现人机交互效果. 2.作用(做什么?) 网页特效(监 ...

  10. CAJViewer卡的解决办法

    在做毕业设计时,使用了CAJViewer7.2版本的阅读器,使用起来非常卡,翻页总是不流畅,体验感极差. 最后实在受不了了,去百度了一下,在贴吧中看到了疑似解决方案,尝试了一下,真的不卡了.所以特此写 ...