Saul's blog Saul's blog
首页
后端
分布式
前端
更多
分类
标签
归档
友情链接
关于
GitHub (opens new window)

Saul.J.Wu

立身之本,不在高低。
首页
后端
分布式
前端
更多
分类
标签
归档
友情链接
关于
GitHub (opens new window)
  • Java入门基础

  • Java核心基础

    • 多线程

    • Java常用类

    • 枚举类与注解

    • Java集合

      • Java集合框架概述
      • Collection
      • List
      • ArrayList
        • 前言
        • 概述
        • JDK7源码分析
          • 添加元素
        • JKD8源码分析
          • 添加元素
        • 小结
        • 面试题
      • LinkedList
      • Vector
      • Set
      • HashSet
      • LinkedHashSet
      • TreeSet
      • Map
      • HashMap
      • LinkedHashMap
      • TreeMap
      • Hashtable
      • Properties
      • Collections工具类
    • 数据结构与算法

    • 泛型

    • IO流

    • 网络编程

    • 反射

    • 函数式编程

  • 设计模式

  • Web开发

  • SpringBoot

  • 微服务

  • Elasticsearch

  • 运维

  • 后端
  • Java核心基础
  • Java集合
SaulJWu
2020-12-27

ArrayList

# 前言

Java 集合可分为Collection 和Map 两种体系:

  • Collection接口:单列数据,定义了存取一组对象的方法的集合
    • List:元素有序、可重复的集合
      • ArrayList、LinkedList、Vector
    • Set:元素无序、不可重复的集合
      • HashSet、LinkedHashSet、TreeSet
  • Map接口:双列数据,保存具有映射关系“key-value对”的集合,也称为键值对。
    • HashMap、LinkedHashMap、TreeMap、Hashtable、Properties

现在我们开始学习List接口的实现类ArrayList。

# 概述

  • ArrayList是List 接口的典型实现类、主要实现类
  • 本质上,ArrayList是对象引用的一个”变长”数组,Object[] elementData,也就是动态的数组。

image-20201224234807501

ArrayList的JDK1.8之前与之后的实现区别?

  • JDK1.7:ArrayList像饿汉式,直接创建一个初始容量为10的数组
  • JDK1.8:ArrayList像懒汉式,一开始创建一个长度为0的数组,当添加第一个元素时再创建一个始容量为10的数组

Arrays.asList(...) 方法返回的List 集合,既不是ArrayList实例,也不是Vector 实例。Arrays.asList(...) 返回值是一个固定长度的List 集合

image-20201224234939047

# JDK7源码分析

在jdk7时,空参实例化方式:

ArrayList list = new ArrayList();
1

空参实例化时,底层是创建了长度是10的Object[] elementData。

# 添加元素

添加元素时,在添加之前先确认容量是否够,不够就扩容,库容调用ensureCapacityInternal(size + 1)方法,size是原来的容量,调用grow方法,默认情况下,容量扩容为原来的1.5倍,特殊情况会将容量设置为要添加元素的容量,极端情况,容量设置为整型最大值,如果容量还不够就报超出内存异常OutOfmemoryError()。

扩容完以后,将原来数组中的元素拷贝过去。

结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int initialCapacity),直接设置容量空间,避免扩容,效率会更高。

# JKD8源码分析

先看空参构造器:

ArrayList list = new ArrayList();
1

空参实例化时,底层Object[] elementData初始化为{},并没有创建长度为10的数组,

# 添加元素

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
1
2
3
4
5

添加元素时,第一次调用时,底层才创建了长度为10的数组,集合的索引指向这个元素,后续的添加和库容操作与JDK7无异。

# 小结

jdk7中的ArrayList的对象的创建类似于单例的饿汉式,实例化时先创建数组,有元素进来集合时就用索引指向元素。

而JKD8中的ArrayList的对象的创建类似于单例的懒汉式,实例化时不创建数组,延迟了数组的创建,节省内存。等有元素进来集合时才创建数组,并将索引指向元素。

# 面试题

下面输出结果是?

@Test
public void test1() {
    List list = new ArrayList();
    list.add(1);
    list.add(2);
    list.add(3);
    updateList(list);
    System.out.println(list);
}

private static void updateList(List list) {
    list.remove(2);
}
1
2
3
4
5
6
7
8
9
10
11
12
13

输出结果:

[1, 2]
1

这道题考的是按索引删除还是对象删除。

这里remove是调用Object remove(int index)方法,而不是boolean remove(Object obj) 方法。

如果想要按Object删除,要传一个对象进去

list.remove(new Integer(2))
1
帮我改善此页面 (opens new window)
#ArrayList
上次更新: 2020/12/27, 05:12:33
List
LinkedList

← List LinkedList→

最近更新
01
zabbix学习笔记二
02-28
02
zabbix学习笔记一
02-10
03
Linux访问不了github
12-08
更多文章>
Theme by Vdoing | Copyright © 2020-2022 Saul.J.Wu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式