ArrayList

本贴最后更新于 2551 天前,其中的信息可能已经物是人非

java.util.ArrayList

允许为空;
允许重复数据;
有序;
非线程安全。

public class ArrayList<E> extends AbstractList<E> implememts List<E>, RondomAccess, Cloneable, java.io.Serializable {
  private static final int DEFAULT_CAPACITY = 10;
  
  // ArrayList在序列化的时候会调用writeObject,直接将size和element写入ObjectOutputStream;反序列化时调用readObject,从ObjectInputStream获取size和element,再恢复到elementData。
  // 为什么不直接用elementData来序列化,而采用上诉的方式来实现序列化呢?原因在于elementData是一个缓存数组,它通常会预留一些容量,等容量不足时再扩充容量,那么有些空间可能就没有实际存储元素,采用上诉的方式来实现序列化时,就可以保证只序列化实际存储的那些元素,而不是整个数组,从而节省空间和时间。
  transient Object[] elementData; // 非私有简化嵌套类访问
  
  private int size; // 逻辑长度
  
  public  ArrayList() { 
	elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // 为什么这里选择空数组而不是初始化为容量为10的数组呢?其实是用了懒加载,第一次添加元素时会自动扩容为容量10
  }
  
  // 先把集合转化为数组,然后判断数组类型是否是Object[].class(如果不是的话,不属于此类及其子类但属于Object类或其子类的实例就添加不进去了),不是的话通过Arrays.copyOf()复制(copyOf底层靠System.copyArray()方法)
  public ArrayList(Collection<? extens E> c) {
	elementData = c.toArray(); // 用Arrays.copyOf()实现
	if ((size = elementData.length) != 0) { 
	  // c.toArray might (incorrectly) not return Object[] (see 6260652) 
	  if (elementData.getClass() != Object[].class) 
		elementData = Arrays.copyOf(elementData, size, Object[].class);
	} else { 
	  array.  this.elementData = EMPTY_ELEMENTDATA; 
	}
  }
  
  public Object[] toArray() {
	return Arrays.copyOf(elementData, size);
  }
  
  /*
  * 先判断是否是第一次添加元素,是的话懒加载默认容量10,添加元素
  * 否则断数组长度是否大于逻辑长度,是的话直接添加元素,不是的话进行数组扩容;
  * 将数组长度扩大为1.5倍,然后进一步判断;
  * 如果数组长度依然比请求的最小长度小,将数组直接扩容到请求的长度(这种情况发生在:一次性插入多个值,也就是调用addAll()方法)
  * 如果数组长度大于2\^31-9且小于等于2\^31-1(因为有一个符号位),返回2\^31-1。(2^31-1是因为size是int类型)
  */
  public boolean add(E e) {
	ensureCapacityInternal(size + 1);
	elementData[size++] = e;
	return true;
  }
  
  private  void  ensureCapacityInternal(int minCapacity) {
	// 第一次添加元素懒加载默认容量10
	if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 
	  minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 
	} 
  
	ensureExplicitCapacity(minCapacity); 
  }
  
  private  void  ensureExplicitCapacity(int minCapacity) { 
	modCount++; // 记录修改次数,modCount在AbstractList类中声明protected transient int modCount = 0;
  
  // 数组越界,需要进行容量扩展  
  if (minCapacity - elementData.length > 0) 
  grow(minCapacity); 
  } 
  
  /**
  * The maximum size of array to allocate.
  * Some VMs reserve some header words in an array.
  * Attempts to allocate larger arrays may result in
  * OutOfMemoryError: Requested array size exceeds VM limit
  * -8 是为了减少出错的几率
  */
  private  static  final  int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 
  
  private  void  grow(int minCapacity) {  
	int oldCapacity = elementData.length; 
	int newCapacity = oldCapacity + (oldCapacity >> 1);  // 相当于oldCapacity + (oldCapacity / 2)
	
	if (newCapacity - minCapacity < 0) 
	  newCapacity = minCapacity; 
	  
	if (newCapacity - MAX_ARRAY_SIZE > 0)
	  newCapacity = hugeCapacity(minCapacity); 
	  
	elementData = Arrays.copyOf(elementData, newCapacity);
  } 
  
  private  static  int  hugeCapacity(int minCapacity) { 
	if (minCapacity < 0) // overflow,因为0111 .... 1111 + x 只要 x 大于 1 就进位,符号位变为 1 ,为负数
	  throw  new OutOfMemoryError(); 
	  
	return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; 
  }
  
  public  void add(int  index, E element)
  
  public  boolean  addAll(Collection c)
  
  public E get(int  index)
  
  public  int  indexOf(Object o)
  
  public  int  lastIndexOf(Object o)
  
  public E remove(int  index)
  
  // 根据删除的对象是否为null进行区分,因为是null就不能调用equals方法了
  public  boolean remove(Object o)
  
  private  void fastRemove(int  index)
  
  // 要求集合c不能为null
  public  boolean  removeAll(Collection c)
  
  public  void  clear()

  public Iterator<E> iterator() {
	  return new Itr();
  }
  
  private class Itr implements Iterator<E> {
	  int cursor;       // index of next element to return
	  int lastRet = -1; // index of last element returned; -1 if no such
	  int expectedModCount = modCount;

	  public boolean hasNext() {
		  return cursor != size;
	  }

	  @SuppressWarnings("unchecked")
	  public E next() {
		  checkForComodification();
		  int i = cursor;
		  if (i >= size)
			  throw new NoSuchElementException();
		  Object[] elementData = ArrayList.this.elementData;
		  if (i >= elementData.length)
			  throw new ConcurrentModificationException();
		  cursor = i + 1;
		  return (E) elementData[lastRet = i];
	  }
	  
	 //检查modCount是否改变了,如果改变了,直接抛出异常  
	 final  void checkForComodification() { 
	   if (modCount != expectedModCount) 
		 throw  new ConcurrentModificationException(); 
	 }
  }
  
  // 双向移动
  public ListIterator listIterator(int  index)
  
  private  class ListItr extends Itr implements ListIterator<E>

Verctor:
1、线程安全;
2、Vector 可以指定增长因子,如果该增长因子指定了,那么扩容的时候会每次新的数组大小会在原数组的大小基础上加上增长因子;如果不指定增长因子,那么就给原数组大小*2。

int newCapacity = oldCapacity + ((capacityIncrement >  0  ) ? capacityIncrement : oldCapacity);

数组和 List 相互转化:
List strList = Arrays.asList(arr);
String[] arr = strList.toArray();

类.class
对象.getClass()

参考:
ArrayList 源码
http://blog.csdn.net/qq_19431333/article/details/54405686
http://blog.csdn.net/shijinupc/article/details/7827507

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 72 关注
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 26 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 664 关注
  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    26 引用 • 84 回帖
  • 微软

    微软是一家美国跨国科技公司,也是世界 PC 软件开发的先导,由比尔·盖茨与保罗·艾伦创办于 1975 年,公司总部设立在华盛顿州的雷德蒙德(Redmond,邻近西雅图)。以研发、制造、授权和提供广泛的电脑软件服务业务为主。

    8 引用 • 44 回帖
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 40 关注
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 364 关注
  • SOHO

    为成为自由职业者在家办公而努力吧!

    7 引用 • 55 回帖 • 18 关注
  • WebClipper

    Web Clipper 是一款浏览器剪藏扩展,它可以帮助你把网页内容剪藏到本地。

    3 引用 • 9 回帖
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    179 引用 • 407 回帖 • 488 关注
  • App

    App(应用程序,Application 的缩写)一般指手机软件。

    91 引用 • 384 回帖
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    36 引用 • 37 回帖 • 529 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 334 关注
  • CongSec

    本标签主要用于分享网络空间安全专业的学习笔记

    1 引用 • 1 回帖 • 9 关注
  • JSON

    JSON (JavaScript Object Notation)是一种轻量级的数据交换格式。易于人类阅读和编写。同时也易于机器解析和生成。

    52 引用 • 190 回帖
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 471 关注
  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    59 引用 • 29 回帖 • 4 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖 • 1 关注
  • 心情

    心是产生任何想法的源泉,心本体会陷入到对自己本体不能理解的状态中,因为心能产生任何想法,不能分出对错,不能分出自己。

    59 引用 • 369 回帖
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 654 关注
  • 电影

    这是一个不能说的秘密。

    120 引用 • 599 回帖
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 453 关注
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    139 引用 • 269 回帖 • 43 关注
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 536 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 1 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 154 关注