ArrayList简介

  ArrayLIst是动态数组,用MSDN的说法就是Array的复杂版本,它提供了动态的增加和减少元素,实现了Collection和List接口,可以灵活的设置数组的大小,要注意ArrayLIst并不是线程安全的。因此一般建议在单线程中使用Arraylist数组

ArrayList的继承关系

  

public class Arraylist
extends AbstractList<E>
implement List<E>,RandomAccess,Cloneable,Serializable

  

ArrayList的方法使用和源码解析

  ①构造方法

  

//1-----------------------
public ArrayList() {
this(10);
//调用ArrayList(10) 默认初始化一个大小为10的object数组。
} //2-------------------------
public ArrayList(int initialCapacity) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//如果用户初始化大小小于0抛异常,否则新建一个用户初始值大小的object数组。
this.elementData = new Object[initialCapacity];
} //3--------------------------
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
// 当c.toArray返回的不是object类型的数组时,进行下面转化。
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}

  由上面三种构造方法可知,默认情况下使用ArrayList会生成一个大小为10的Object类型的数组。也可以调用ArrayList(int initialCapacity) 来初始化Object数组的大小。并且用户可以往ArrayList中传入一个容器只要这个容器是Collection类型的。调用ArrayList(Collection<? extends E> c)接口的时候会将容器数组化处理并将这个数组值赋给Object数组。

  实例:

  

public static void main(String[] args) {
ArrayList<Integer> list_2=new ArrayList<Integer>(20);
//list_2中添加元素
for(int i=0;i<10;i++)
list_2.add(i); ArrayList<Integer> list_3=new ArrayList<Integer>(list_2);
//输出list_2中元素
for(Integer a:list_2)
System.out.print(a+" ");
//输出list_3中元素
for(Integer a:list_3)
System.out.print(a+" ");
}
//输出
/*
list_2 : 0 1 2 3 4 5 6 7 8 9
-----------------------
list_3 : 0 1 2 3 4 5 6 7 8 9
*/

  ②indexOf(Object o)方法

  功能:查找某个元素在ArrayList中第一次出现的位置。

  

public int indexOf(Object o) {
//ArrayList中的元素可以为null,如果为null返回null的下标
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i; } else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
//如果没有找到对应的元素返回-1。
return -1;
}

  对于indexof方法做几点说明:ArrayList中可以存放null元素,indexof是返回elementData数组中值相同的首个元素的下标,indexof中比较方法是equals而equals是比较元素的值,因此必须对null单独查找。如果未找到该元素则返回-1 。

  实例

  

public static void main(String[] args) {

        ArrayList<Integer> list=new ArrayList<Integer>();

        list.add(1);
list.add(2);
list.add(null);
list.add(2);
list.add(3); System.out.println("null: "+list.indexOf(null));
System.out.println("-------------------------");
System.out.println("2: "+list.indexOf(2));
System.out.println("-------------------------");
System.out.println("4: "+list.indexOf(4));
}
//输出
/*
null: 2
-------------------------
2: 1
-------------------------
4: -1
*/

  ③lastIndexOf(Object o)方法

  功能:查找某个元素在ArrayList中最后出现的位置。

  

public int lastIndexOf(Object o) {
if (o == null) {
//如果o为null从后往前找到第一个为null的下标
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
//从后往前找到第一个值为o的下标
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}

  上面代码做几点说明:lastIndexOf(Object o)在ArrayList中从后往前找到第一个跟要查找值相同的元素的下标,因为是按值查找所以对于 null 要单独查找。如果未找到则返回-1

  ④get(int index)方法

  功能:返回ArrayList中指定下标为index的元素。

  

public E get(int index) {
//检查index的值是否大于ArrayList的大小
rangeCheck(index);
//返回index下标的元素
return elementData(index);
} E elementData(int index) {
return (E) elementData[index];
}
//这里值检查index >= size的情况,因为index<0时会自动抛出异常,所以并未检查index<0的情况。
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

  对上面代码做几点说明:上面代码中只检查了index>=size的情况,在index<0的情况下也会抛出异常,只是这个异常是由系统抛出的。index>=size要检查的原因是有可能数组的大小大于index,然而有效里面的元素<index这时不抛异常就会返回无效值。举个例子ArrayList的初始化大小为10,现在往里面放5个元素,如果index>=5时,应该要抛出异常,而不是返回 null。因为null 是可以主动放在ArrayList中的。

  ⑤set(int index, E element)方法

  功能:将element放到ArrayList下标为index的位置,如果index<0或index>=size 抛异常,set(int index, E element)只能覆盖ArrayList中原来的元素,返回值为被覆盖的元素。

  

//1
public E set(int index, E element) {
//检查index是否小于size,如果不是抛异常
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
//覆盖ArrayList中index上的元素。
return oldValue;
//返回被覆盖的元素。
}
//2
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

  ⑥add(E e)方法 
  功能:往ArrayList中添加元素。

  

/1-----------------------
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 加入元素前检查数组的容量是否足够
elementData[size++] = e;
return true;
}
//2-----------------------
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// 如果添加元素后大于当前数组的长度,则进行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//3-----------------------
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//将数组的长度增加原来数组的一半。
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果扩充一半后仍然不够,则 newCapacity = minCapacity;minCapacity实际元素的个数。
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//数组最大位2^32
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

  add方法比较复杂,涉及到扩充数组容量的问题。其中要弄清楚size和elementData.length的区别,size指的是数组中存放元素的个数,elementData.length表示数组的长度,当new一个ArrayList系统默认产生一个长度为10的elementData数组,elementData.length=10,但是由于elementData中还未放任何元素所有size=0。如果加入元素后数组大小不够会先进行扩容,每次扩容都将数组大小增大一半比如数组大小为10一次扩容后的大小为10+5=10;ArrayList的最大长度为 2^32 .

  ⑦add(int index, E element)方法 
  功能:往ArrayList指定index上添加元素,添加元素后ArrayList的大小增1。index及以后的元素都会向后移一位

  

//1-------------------------
public void add(int index, E element) {
rangeCheckForAdd(index);
//检查index的值是否在0到size之间,可以为size。
ensureCapacityInternal(size + 1); // 看elementData的长度是否足够,不够扩容
//将elementData从index开始后面的元素往后移一位。
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
//2-------------------------
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//3-------------------------
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}

  add(int index, E element)往指定index中加入元素,加入元素之前先检查数组的大小,如果小了在原来基础上增大一半,将ArrayList只能怪index及以后的元素往后移一位,将element放到index位置。

  ⑧remove(int index)方法 
  功能:删除ArrayList指定位置的元素。

  

public E remove(int index) {
rangeCheck(index);
//如果index>=size抛出异常
modCount++;
E oldValue = elementData(index);
//获取删除元素的值
int numMoved = size - index - 1;
//将index后面所有的元素往前移一位。
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
//返回要删除的原数。
return oldValue;
}

  ⑨remove(Object o)方法

  功能:删除ArrayList中值为o的元素

  

public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}

  

深入理解java集合框架之---------Arraylist集合的更多相关文章

  1. 深入理解java集合框架之---------Arraylist集合 -----添加方法

    Arraylist集合 -----添加方法 1.add(E e) 向集合中添加元素 /** * 检查数组容量是否够用 * @param minCapacity */ public void ensur ...

  2. 深入理解java集合框架之---------Arraylist集合 -----构造函数

    ArrayList有三个构造方法 ArrayList有三个常量 1.private transient Object[] elementData (数组); 2.private int size (元 ...

  3. Java集合框架之ArrayList浅析

    Java集合框架之ArrayList浅析 一.ArrayList综述: 位于java.util包下的ArrayList是java集合框架的重要成员,它就是传说中的动态数组,用MSDN中的说法,就是Ar ...

  4. 牛客网Java刷题知识点之Java 集合框架的构成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection(List和Set)、集合框架中的Map集合

    不多说,直接上干货! 集合框架中包含了大量集合接口.这些接口的实现类和操作它们的算法. 集合容器因为内部的数据结构不同,有多种具体容器. 不断的向上抽取,就形成了集合框架. Map是一次添加一对元素. ...

  5. Java集合框架概述和集合的遍历

    第三阶段 JAVA常见对象的学习 集合框架概述和集合的遍历 (一) 集合框架的概述 (1) 集合的由来 如果一个程序只包含固定数量的且其生命周期都是已知的对象,那么这是一个非常简单的程序. 通常,程序 ...

  6. Java 基础 引用数据类型 ArrayList集合

    引用数据类型(类) 分类 提到引用数据类型(类),其实我们对它并不陌生,如使用过的Scanner类.Random类. 我们可以把类的类型为两种: 第一种,Java为我们提供好的类,如Scanner类, ...

  7. 第14章 集合框架(1)-List集合的各种类

    1.概述 1.1.Java集合框架的由来 1.2.什么是集合框架? 1.3.为什么需要集合框架 1.4.常用的框架接口规范 2.Vector类 2.1.存储原理 2.2.构造方法 2.3.常用方法 3 ...

  8. 深入理解Java并发框架AQS系列(一):线程

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.概述 1.1.前言 重剑无锋,大巧不工 读j.u.c包下的源码,永远无法绕开的经典 ...

  9. 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.AQS框架简介 AQS诞生于Jdk1.5,在当时低效且功能单一的synchroni ...

随机推荐

  1. TSQL--集合处理

    UNION ALL 返回两个结果集中所有的行,返回结果集中会存在重复行 UNION 返回两个结果集中去重的行,返回结果集中无重复行 INTERSECT 返回两个结果集都有的行,返回结果集中无重复行 E ...

  2. 构建命令maven install 打包不是最新的代码

    问题: 之前一直用的是mvn install 命令来构建项目,但是最近发现最新的代码没有在war包中.之前看的说 mvn install 命令会执行之前的所有阶段,会被编译,测试,打包. 经查最后采用 ...

  3. myeclipse过期以后提示过期以后怎么办?!

    昨天电脑上装的myeclipse到期了,不能进到工作空间里边,只有激活和退出选项,在网上百度了一下,有很多破解工具, 1.刚开始直接使用工具破解,没有成功,总是提示要么激活,要么退出 2.继续想办法, ...

  4. iOS 添加字体

    1. 将字体(ttf 文件)导入项目. 2. 在项目plist 文件里的 Fonts provided by application 添加新导入的字体. 3. 代码中的调用 [aLabel setFo ...

  5. python---基本数据类型 dict(字典)

    1. 什么是字典 字典是python中唯一的映射类型, 由{ } 括起来的键值对组成,在dict中key是唯一的.字典是以key:value的形式来保存数据, 字典存储数据的时候是用的hash值来存储 ...

  6. PHP header函数设置http报文头示例详解以及解决http返回头中content-length与Transfer-Encoding: chunked的问题

    最近在服务器上,多媒体与设备(摄像头)对接的时候,总是发生错误导致设备崩溃,抓包发现响应头不对,没有返回length,使得摄像头立即崩溃.找了一下资料,改了一下响应头就好了. //定义编码 heade ...

  7. 报错:'utf-8' codec can't decode byte 0xb0 in position 0: invalid start byte

    pandas的read_csv读取一个csv表格,报错. 解决方法:用editplus打开表格,改变编码格式为utf-8,保存,重新读取,通过.

  8. Problem D: GJJ的日常之暴富梦(水题)

    Contest - 河南省多校连萌(四) Problem D: GJJ的日常之暴富梦 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 693  Solve ...

  9. ElasticSearch.net NEST批量创建修改删除索引完整示例

    本示例采用Elasticsearch+Nest 网上查了很多资料,发现用C#调用Elasticsearch搜索引擎的功能代码很分散,功能不完整,多半是非常简单的操作,没有成型的应用示例.比如新增或修改 ...

  10. 高可用群集HA介绍与LVS+keepalived高可用群集

    一.Keepalived介绍 通常使用keepalived技术配合LVS对director和存储进行双机热备,防止单点故障,keepalived专为LVS和HA设计的一款健康检查工具,但演变为后来不仅 ...