【Java集合-3】ArrayList简析(1)

    • 1.1 ArrayList简介

    • ArrayList继承关系

    • 1.2 ArrayList数据结构

    • 1.3 ArrayList构造函数

    • 1.4 ArrayList的API

  • 2 ArrayList常用操作

    • 2.1 ArrayList遍历

    • 2.2 ArrayList排序

    • 2.3 ArrayList删除元素

  • 3 ArrayList部分方法源码(基于JDK1.8)

    • 3.1 get(int index)

    • 3.2 add(E e)

    • 3.3 remove(Object o)

    • 3.4 addAll(Collection<? extends E> c)

在前面的集合框架那一章中,简单总结了Java集合的架构,List是Collection下的一大分支,而ArrayList又是List中最为常用的。本章将对ArrayList做一个总结,以供将来回顾之用。

1 ArrayList说明

=======================================================================

1.1 ArrayList简介


ArrayList是一个数组队列,相当于动态数组。与Java中的数组相比,它的容量能动态增长。

  1. ArrayList 是一个数组队列,继承了AbstractList,实现了List,提供了元素添加、删除、修改、遍历等功能。

  2. ArrayList 实现了RandmoAccess接口,即提供了随机访问功能(通过元素序号快速获取元素,即所谓的快速访问)。

  3. ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。

  4. ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。

  5. ArrayList 线程不安全,在多线程中可以选择CopyOnWriteArrayList。

ArrayList继承关系


在这里插入图片描述

1.2 ArrayList数据结构


ArrayList的成员变量:


//初始化默认容量

private static final int DEFAULT_CAPACITY = 10;

// 空对象数组

private static final Object[] EMPTY_ELEMENTDATA = {};

// 默认容量的空对象数组

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

// 实际存储对象的数组

transient Object[] elementData;

// 存储的数量

private int size;

// 数组能申请的最大数量

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;



成员变量中的elementData 和 size 是两个比较重要的参数:

  1. elementData 是"Object[]类型的数组",它保存了添加到ArrayList中的元素。实际上,elementData是个动态数组,我们能通过构造函数 ArrayList(int initialCapacity)来执行它的初始容量为initialCapacity;如果通过不含参数的构造函数ArrayList()来创建ArrayList,则elementData的容量默认是10。elementData数组的大小会根据ArrayList容量的增长而动态的增长,具体的增长方式,请参考源码分析中的ensureCapacity()函数。

  2. size 则是动态数组的实际大小。

1.3 ArrayList构造函数


ArrayList提供了三个构造函数:


// 默认构造函数

public ArrayList()



// capacity:ArrayList的默认容量大小。增加数据导致容量不足时,ArrayList会扩容,增加上一次容量大小的一半。

public ArrayList(int capacity) {

	// 当 initialCapacity > 0 时,初始化对应大小的数组

  	if (initialCapacity > 0) {

    	this.elementData = new Object[initialCapacity];

  	// 为 0 时,用指向EMPTY_ELEMENTDATA

  	} else if (initialCapacity == 0) {

    	this.elementData = EMPTY_ELEMENTDATA;

  	} else {

    	throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);

  	}

}



// 创建一个包含collection的ArrayList

public ArrayList(Collection<? extends E> collection) {

	elementData = c.toArray();

 	if ((size = elementData.length) != 0) {

    // c.toArray不返回Object[]的时候,则进行数组拷贝

    	if (elementData.getClass() != Object[].class)

      		elementData = Arrays.copyOf(elementData, size, Object[].class);

  	} else {

    // 如果为空,则指向EMPTY_ELEMENTDATA

    	this.elementData = EMPTY_ELEMENTDATA;

  	}

}



1.4 ArrayList的API


| 返回值 | 方法 | 描述 |

| — | — | — |

| boolean | add(E e) | 将指定的元素添加到此列表的尾部。 |

| void | add(int index, E element) | 将指定的元素插入此列表中的指定位置。 |

| boolean | addAll(Collection<? extends E> c) | 按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。 |

| boolean | addAll(int index, Collection<? extends E> c) | 从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。 |

| void | clear() | 移除此列表中的所有元素。 |

| Object | clone() | 返回此 ArrayList 实例的浅表副本。 |

| boolean | contains(Object o) | 如果此列表中包含指定的元素,则返回 true。 |

| void | ensureCapacity(int minCapacity) | 如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。 |

| E | get(int index) | 返回此列表中指定位置上的元素。 |

| int | indexOf(Object o) | 返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。 |

| boolean | isEmpty() | 如果此列表中没有元素,则返回 true |

| int | lastIndexOf(Object o) | 返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。 |

| E | remove(int index) | 移除此列表中指定位置上的元素。 |

| boolean | remove(Object o) | 移除此列表中首次出现的指定元素(如果存在) |

| protected void | removeRange(int fromIndex, int toIndex) | 移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。 |

| E | set(int index, E element) | 用指定的元素替代此列表中指定位置上的元素。 |

| int | size() | 返回此列表中的元素数。 |

| Object[] | toArray() | 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。 |

| T[] | toArray(T[] a) | 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。 |

| void | trimToSize() | 将此 ArrayList 实例的容量调整为列表的当前大小。 |

2 ArrayList常用操作

=========================================================================

2.1 ArrayList遍历


ArrayList支持三种遍历方式:迭代器遍历、随机访问遍历、增强for遍历


public static void main(String[] args) {

	List<Integer> list = Arrays.asList(1, 7, 5, 3, 8, 2);

	// 迭代器遍历

	Iterator<Integer> it = list.iterator();

	while (it.hasNext()) {

		int value = (int) it.next();

		System.out.println(value + " ");

	}

	

	// 随机访问遍历

	for (int i = 0; i < list.size(); i++) {

		int value = list.get(i);

		System.out.println(value + " ");

	}



	// 增强for遍历

	for (int value : list) {

		System.out.print(value + " ");

	}

}	



2.2 ArrayList排序


ArrayList集合排序依赖于Collections.sort(),其默认是按升序排序的,如果想要降序排列,需重写Collections.sort()方法。


public static void main(String[] args) {

	List<Integer> list = Arrays.asList(1, 7, 5, 3, 8, 2);

	

	// 按照字典顺序排序

	Collections.sort(list);

	System.out.println("默认排序:" + list);



	// 自定义排序

	Collections.sort(list, new Comparator<Integer>() {

		@Override

		public int compare(Integer o1, Integer o2) {

			int i = o1.compareTo(o2);

			// int、double型,可以直接用o1 > o2做if的判断条件,String类型只能用compareTo方法

			if (i > 0) 

				return -1;

			return 1;

		}

	});

	System.out.println("自定义排序:" + list);

}



运行结果:


默认排序:[1, 2, 3, 5, 7, 8]

自定义排序:[8, 7, 5, 3, 2, 1]



2.3 ArrayList删除元素


现在有 [a,a,b,c,e,a,d] 这么一个ArrayList集合,删除该集合中的所有的"a"。也许有人觉得很简单,并给出下面代码:


public static void main(String[] args) {

	List<String> list = new ArrayList<>();

	list.add("a");

	list.add("a");

	list.add("d");

	list.add("c");

	list.add("a");

	list.add("e");

	list.add("m");



	// 错误的删除方法:

	for (int i = 0; i < list.size(); i++) {

		String value = list.get(i);

		if (value.equals("a"))

			list.remove(i);

	}

	System.out.println(list);

}



运行结果:


[a, d, c, e, m]



可以看到,当有连续两个以上a元素时,最终会保留一个。原因是,删除元素后,ArrayList集合的索引重新排列,删除元素后面的元素索引全部向前移动一位,本例中,删除第一个a后,第二个a的索引就由1变成了0,而for循环已经运行过0了,导致第二个a未被删除。

正确的做法是倒序遍历删除:


for (int i = list.size()-1; i >= 0; i--) {

	String value = list.get(i);

	if (value.equals("a"))

		list.remove(i);

}



最后

即使是面试跳槽,那也是一个学习的过程。只有全面的复习,才能让我们更好的充实自己,武装自己,为自己的面试之路不再坎坷!今天就给大家分享一个Github上全面的Java面试题大全,就是这份面试大全助我拿下大厂Offer,月薪提至30K!

我也是第一时间分享出来给大家,希望可以帮助大家都能去往自己心仪的大厂!为金三银四做准备!
一共有20个知识点专题,分别是:

Dubbo面试专题

JVM面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Java并发面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Kafka面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

MongDB面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

MyBatis面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

MySQL面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Netty面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

RabbitMQ面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Redis面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Spring Cloud面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

SpringBoot面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

zookeeper面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

常见面试算法题汇总专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

计算机网络基础专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

设计模式专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

[外链图片转存中…(img-ZcugI4xQ-1714512029493)]

RabbitMQ面试专题

[外链图片转存中…(img-Ubymp64w-1714512029494)]

Redis面试专题

[外链图片转存中…(img-PTaxIigi-1714512029494)]

Spring Cloud面试专题

[外链图片转存中…(img-dTRSbgap-1714512029494)]

SpringBoot面试专题

[外链图片转存中…(img-WMfXO4oA-1714512029495)]

zookeeper面试专题

[外链图片转存中…(img-4Al56ELN-1714512029495)]

常见面试算法题汇总专题

[外链图片转存中…(img-w5KBD9XN-1714512029495)]

计算机网络基础专题

[外链图片转存中…(img-lt3rMaNg-1714512029496)]

设计模式专题

[外链图片转存中…(img-ORtl9sxN-1714512029496)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值