Java集合类之ArrayList
学习Java的集合类
(1)成员变量以及初始化
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private transient Object[] elementData;
private int size;
默认的大小为10。
EMPTY_ELEMENTDATA是用于无参初始化,即一个等于null的对象数组。
elemenData则用于有参初始化的变量,也是我们下面操作的主体对象。
下面看看有参初始化的源码:
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
此处初始化一个大小为initialCapacity的对象数组
由初始化的过程可以看出:ArrayList是基于动态数组实现的。
(2)常用操作
// Collection中定义的API
boolean add(E object)
boolean addAll(Collection<? extends E> collection)
void clear()
boolean contains(Object object)
boolean containsAll(Collection<?> collection)
boolean equals(Object object)
int hashCode()
boolean isEmpty()
Iterator<E> iterator()
boolean remove(Object object)
boolean removeAll(Collection<?> collection)
boolean retainAll(Collection<?> collection)
int size()
<T> T[] toArray(T[] array)
Object[] toArray()
// AbstractCollection中定义的API
void add(int location, E object)
boolean addAll(int location, Collection<? extends E> collection)
E get(int location)
int indexOf(Object object)
int lastIndexOf(Object object)
ListIterator<E> listIterator(int location)
ListIterator<E> listIterator()
E remove(int location)
E set(int location, E object)
List<E> subList(int start, int end)
// ArrayList新增的API
Object clone()
void ensureCapacity(int minimumCapacity)
void trimToSize()
void removeRange(int fromIndex, int toIndex)
Add方法用于添加一个元素到当前列表的末尾
AddRange方法用于添加一批元素到当前列表的末尾
Remove方法用于删除一个元素,通过元素本身的引用来删除
RemoveAt方法用于删除一个元素,通过索引值来删除
RemoveRange用于删除一批元素,通过指定开始的索引和删除的数量来删除
Insert用于添加一个元素到指定位置,列表后面的元素依次往后移动
InsertRange用于从指定位置开始添加一批元素,列表后面的元素依次往后移动
Clear方法用于清除现有所有的元素
Contains方法用来查找某个对象在不在列表之中
TrimSize用于将ArrayList固定到实际元素的大小,当动态数组元素确定不在添加的时候,可以调用这个方法来释放空余的内存。
ToArray方法把ArrayList的元素Copy到一个新的数组中。
此处我们特殊需要看一下indexof的源码:
public int indexOf(Object o) {
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;
}
return -1;
}
此处可以看出,indexof是通过for循环实现的,也就是说要遍历一遍对象数组,类似的contains方法也是通过for循环来判断元素是否包含在内。
所以这类方法的效率是极其低下的,不必自己写for循环来得快,如果需要频繁使用此类快速键值查找的功能,建议使用HashMap.
(3)大小的动态调整
从add()方法看起:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public void add(int index, E element) {
rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
add(int index, E element)
ensureCapacityInternal()函数会调用ensureExplicitCapacity()函数,检测后如果确定需要扩容,则调用grow()函数
/*
最大的容量。
一些虚拟机可能会在一个数组的头部有几位保留信息,所以是Integer.MAX_VALUE - 8
如果想创造大小超过这个极限值的ArrayList会报错:OutOfMemoryError
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/*
增长容量以保证可以容纳当前所有元素的最小长度要求。
@param minCapacity 当前的最小容量需求。
*/
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
分析最关键的grow()函数可知:
关键:newCapacity = oldCapacity + (oldCapacity >> 1);
即newCapacity是oldCapacity的3倍
接下检查此时的大小是否合理,是否小于最小界,大于最大界(最大界定义处有一个减8的操作,是用来适应不同的虚拟机规范,有的虚拟机在数组的头部留出几位来存储一些相关信息)
调整大小后通过复制操作来重造一个数组返回给elementData
(4)遍历方式
第一,随机访问,通过索引获取元素。ArrayList实现了RandomAccess接口。下面是get()方法源码
public E get(int index) {
rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset + index);
}
第二,for循环,以Integer元素为例
Integer value = null;
for (Integer integ:list) {
value = integ;
}
第三,通过迭代器(Iterator)去遍历,以Integer元素为例
Integer value = null;
Iterator iter = list.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}
这三种方法中,随机访问的访问最快,迭代器的方法最慢
(5)序列化
ArrayList实现了java.io.Serializable接口,可以进行序列化,源码如下
/**
* Save the state of the <tt>ArrayList</tt> instance to a stream (that
* is, serialize it).
*
* @serialData The length of the array backing the <tt>ArrayList</tt>
* instance is emitted (int), followed by all of its elements
* (each an <tt>Object</tt>) in the proper order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject(); // Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size); // Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
} if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
} /**
* Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
* deserialize it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA; // Read in size, and any hidden stuff
s.defaultReadObject(); // Read in capacity
s.readInt(); // ignored if (size > 0) {
// be like clone(), allocate array based upon size not capacity
ensureCapacityInternal(size); Object[] a = elementData;
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}
Java集合类之ArrayList的更多相关文章
- 【Java集合类】ArrayList详解 (JDK7)
相信对于使用过Java的人来说,ArrayList这个类大家一定不会陌生. 数据结构课上讲过, Array是数组,它能根据下标直接找到相应的地址,所以索引速度很快,但是唯一的缺点是不能动态改变数组的长 ...
- java集合类之ArrayList详解
一.ArrayList源码分析 1.全局变量 (1)默认容量(主要是通过无参构造函数创建ArrayList时第一次add执行扩容操作时指定的elementData的数组容量为10) private s ...
- Java集合类源码解析:ArrayList
目录 前言 源码解析 基本成员变量 添加元素 查询元素 修改元素 删除元素 为什么用 "transient" 修饰数组变量 总结 前言 今天学习一个Java集合类使用最多的类 Ar ...
- java集合类源码学习三——ArrayList
ArrayList无疑是java集合类中的一个巨头,而且或许是使用最多的集合类.ArrayList继承自AbstractList抽象类,实现了List<E>, RandomAccess, ...
- Java集合类--温习笔记
最近面试发现自己的知识框架有好多问题.明明脑子里知道这个知识点,流程原理也都明白,可就是说不好,不知道是自己表达技能没点,还是确实是自己基础有问题.不管了,再巩固下基础知识总是没错的,反正最近空闲时间 ...
- 做JavaWeb开发不知Java集合类不如归家种地
Java作为面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储.但是使用数组存储对象方面具有一些弊端,而Java 集合就像一种容器,可以动态地把多个对象的引用放入容 ...
- 【转载】Java集合类Array、List、Map区别和联系
Java集合类主要分为以下三类: 第一类:Array.Arrays第二类:Collection :List.Set第三类:Map :HashMap.HashTable 一.Array , Arrays ...
- 摘抄转载前辈们的Java集合类总结
本文摘自 Blue Sky:http://www.cnblogs.com/hubcarl JAVA 集合类介绍和使用 类关系示意图Iterable(接口) │ └--Collection (接口) ├ ...
- Java集合类: Set、List、Map、Queue使用场景梳理
本文主要关注Java编程中涉及到的各种集合类,以及它们的使用场景 相关学习资料 http://files.cnblogs.com/LittleHann/java%E9%9B%86%E5%90%88%E ...
随机推荐
- LAMP平台搭建菜鸟入门级实验
LAMP平台搭建(菜鸟入门级) mysql 安装: (1)二进制安装 二进制安装 ,执行解压配置即可.无须执行三布安装. (2)源码编译安装 安装准备工作: (1)查看系统配置:#uname -a/ ...
- iOS中如何让TextView和TextField控件支持return键收起输入法
TextView和TextField控件是iOS中负责接收用户输入的控件,那当用户输入完成时怎么收起面板呢? 1.TextView和TextField控件获得焦点之后的第一反应就是弹出输入法面板: 2 ...
- .NET微信通过授权获取用户的基本信息
一.填写授权回调页面的域名 二.引导用户到指定的授权页面 例如:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID& ...
- 用JavaScript动态加载CSS和JS文件
本文转载自:http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/11/14/2248451.html 今天项目中需要用到动态加载 CSS 文件 ...
- Hbase条件筛选
需求来自于,模糊查找当天的所有记录,并查找对应列的记录数 public static void main(String[] args) throws Exception{ //创建HBase连接 Co ...
- PLSQL 逻辑多线程机制
CREATE OR REPLACE PACKAGE jv_para_pkg IS PROCEDURE main(i_job_name VARCHAR2, i_job ...
- [转载] 【Shiro】Apache Shiro架构之实际运用(整合到Spring中)
写在前面:前面陆陆续续对Shiro的使用做了一些总结,如题,这篇博文主要是总结一下如何将Shiro运用到实际项目中,也就是将Shiro整到Spring中进行开发.后来想想既然要整,就索性把Spring ...
- maven3 手动安装本地jar到仓库
安装命令: mvn install:install-file -Dfile={Path/to/your/ojdbc.jar} -DgroupId=com.oracle -DartifactId=ojd ...
- QT学习之路--创建一个对话框
Q_OBJECT:这是一个宏,凡是定义信号槽的类都必须声明这个宏. 函数tr()全名是QObject::tr(),被他处理过的字符串可以使用工具提取出来翻译成其他语言,也就是做国际化使用. 对于QT学 ...
- POJ解题经验交流
感谢范意凯.陈申奥.庞可.杭业晟.王飞飏.周俊豪.沈逸轩等同学的收集整理. 题号:1003 Hangover求1/2+1/3+...1/n的和,问需多少项的和能超过给定的值 类似于Zerojudg ...