一.成员变量
// 在AbstractList里面定义的
protected transient int modCount = 0;
// 内部用数组实现
private transient Object[] elementData;
private int size;
二.构造函数
// 自己在写代码的时候为了严谨,最好是先判断参数抛出IllegalArgumentException
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "
+ initialCapacity);
this.elementData = new Object[initialCapacity];
}
// 初始化容量10
public ArrayList() {
this(10);
}
三.存数据
//增加数据
public boolean add(E e) {
//1.保证容量,size+1和容量比较,看是否有位置插入e
ensureCapacity(size + 1); // Increments modCount!!
//2.直接赋值
elementData[size++] = e;
return true;
}
//在指定位置增加数据
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ size);
//1.保证容量
ensureCapacity(size + 1); // Increments modCount!!
//2.向右移动当前位于该位置的元素(如果有)以及所有后续元素(将其索引加 1)。
System.arraycopy(elementData, index, elementData, index + 1, size
- index);
//3.将指定的元素插入此列表中的指定位置
elementData[index] = element;
size++;
}
// 检查容量,minCapacity=size+1
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
// 如果超过容量
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
// 新容量=(老容量 * 3)/2 + 1
// 如果老容量为10,则新容量为16
int newCapacity = (oldCapacity * 3) / 2 + 1;
//newCapacity < minCapacity会产生这样的情况?????
if (newCapacity < minCapacity)
newCapacity = minCapacity;
//复制原数组数据到大小为newCapacity的数组中
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
//替换数据
public E set(int index, E element) {
RangeCheck(index);
//保存index处旧值
E oldValue = (E) elementData[index];
//赋新值
elementData[index] = element;
return oldValue;
}
//下标志检查
private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
+ size);
}
四.取数据
public E get(int index) {
RangeCheck(index);
return (E) elementData[index];
}
// 返回第一次出现o的下标,用equals比较
// 如果不存在o,返回-1
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;
}
// 想想为什么不这么实现
// 上面的实现方式比较次数2+n,下面的比较次数2*n
public int indexOf(Object o) {
for (int i = 0; i < size; i++) {
if (o == null) {
if (elementData[i] == null)
return i;
} else {
if (o.equals(elementData[i]))
return i;
}
}
return -1;
}
// 从size-1往0遍历
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size - 1; i >= 0; i--)
if (elementData[i] == null)
return i;
} else {
for (int i = size - 1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
五.删数据
//移除index处的元素是List接口里新加的方法
//同Map一样,在插入元素的操作中会扩容,删除元素并不去减容
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
//需要移动的元素个数
int numMoved = size - index - 1;
if (numMoved > 0)
//数组内(间)元素移动,五个参数依次为
//src - 源数组。
//srcPos - 源数组中的起始位置。
//dest - 目标数组。
//destPos - 目标数据中的起始位置。
//length - 要复制的数组元素的数量。
System.arraycopy(elementData, index + 1, elementData, index,
numMoved);
//让GC回收因移动空出的数组最后一位
elementData[--size] = null;
return oldValue;
}
//remove某个元素是Collection接口里的方法
//同Map一样,在插入元素的操作中会扩容,删除元素并不去减容
//remove(int index)和remove(Object 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;
}
//把index后的元素移往前移一位
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index + 1, elementData, index,
numMoved);
//让GC回收因移动空出的数组最后一位
elementData[--size] = null;
}
六.List与Array
//ArrayList转换成数组
//将ArrayList内部的数组0到size-1位返回即可
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
//ArrayList转换成指定数组a
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
分享到:
相关推荐
Java并发容器CopyOnWriteArrayList实现原理及源码分析 Java并发容器CopyOnWriteArrayList是Java并发包中提供的一个并发容器,实现了线程安全且读操作无锁的ArrayList,写操作则通过创建底层数组的新副本来实现。...
ArrayList 源码分析: ArrayList 底层采用数组实现,所以它的操作基本上都是基于对数组的操作。ArrayList 提供了三个构造函数: 1. ArrayList():默认构造函数,提供初始容量为 10 的空列表。 2. ArrayList(int ...
Unsafe 详细解Java SPI 机制详解Java语法糖详解集合知识点/面试题总结:Java集合常见知识点&面试题总结(上)(必看)Java集合常见知识点&面试题总结(下)(必看)Java容器使用注意事项总结源码分析:ArrayList核心...
源码分析: ArrayList 核心源码+扩容机制分析 LinkedList 核心源码分析 HashMap 核心源码+底层数据结构分析 ConcurrentHashMap 核心源码+底层数据结构分析 LinkedHashMap 核心源码分析 CopyOnWriteArrayList 核心...
源码分析: ArrayList 源码+扩容机制分析 HashMap(JDK1.8)源码+底层数据结构分析 ConcurrentHashMap 源码+底层数据结构分析 IO IO 基础知识总结 IO 设计模式总结 IO 模型详解 并发 知识点/面试题总结 : (必看 ) ...
源码分析 : ArrayList 源码+扩容机制分析 HashMap(JDK1.8)源码+底层数据结构分析 ConcurrentHashMap 源码+底层数据结构分析 IO IO 基础知识总结 IO 设计模式总结 IO 模型详解 并发 知识点/面试题总结 : (必看 ) ...
《JUC并发编程与源码分析视频课》是一门深入探讨Java并发编程的课程,主要聚焦于Java Util Concurrency(JUC)库的使用和源码解析。JUC是Java平台提供的一组高级并发工具包,它极大地简化了多线程编程,并提供了更...
Vector与ArrayList类似,但它是一个古老的类,是线程安全的,而ArrayList不是。 Queue接口定义了先进先出的队列操作,LinkedList实现了Queue接口,因此可以作为一个队列来使用。除了基本的队列操作外,Java还提供了...
源码分析有助于理解其设计模式和事件驱动机制。 3. **EJB(Enterprise JavaBeans)**:在企业级应用中,EJB容器负责管理事务、安全性和资源,提供服务器端组件的生命周期管理。EJB有三种类型:session beans、...
2. **ArrayList与LinkedList的区别**:对比分析ArrayList和LinkedList在存储结构、空间效率、时间复杂度等方面的差异,学习如何根据需求选择合适的数据结构。 3. **源码阅读**:通过阅读ArrayList和LinkedList的...
ArrayList的源码分析可以帮助我们更好地了解ArrayList的实现机制。ArrayList的底层实现使用数组实现,数组的元素类型是Object[]。ArrayList的构造方法中使用了三种不同的数组实现:DEFAULTCAPACITY_EMPTY_...
总之,"java并发源码分析之实战编程"涵盖了许多关键知识点,从基本的线程操作到复杂的并发设计模式,都需要开发者深入学习和实践。通过研究源码,我们可以更深入地理解这些机制的工作原理,从而在实际开发中做出更优...
List、Set、Map三大接口以及其实现类(ArrayList、LinkedList、HashSet、TreeSet、HashMap、LinkedHashMap等)的源码分析能帮助我们更高效地利用数据结构,优化程序性能。 标签“系统开源”表明这个项目鼓励开放和...
源码分析 ArrayList 是一个基于动态数组实现的 List 实现类。它实现了 RandomAccess 接口,因此支持随机访问。ArrayList 的默认大小为 10,添加元素时使用 ensureCapacityInternal() 方法来保证容量足够,如果不够...
源码分析能揭示这些数据结构的工作方式,例如ArrayList的动态扩容策略,HashSet的哈希函数设计,以及HashMap的冲突解决方法。理解这些细节有助于我们在实际编程中选择合适的集合类型,提高数据操作效率。 并发编程...
本文将深入分析Java中的List接口及其常见的实现类,如ArrayList、LinkedList和Vector,探讨它们的效率差异和适用场景。 首先,List是Java集合框架中的一个重要接口,它扩展了Collection接口,并规定了元素的有序性...
3. **集合框架**:ArrayList、LinkedList、HashSet、HashMap等容器的使用,以及泛型的理解。 4. **IO流**:学习如何读写文件,理解字节流和字符流的区别,以及缓冲区的概念。 5. **多线程**:线程的创建、同步机制...
- **集合框架**:ArrayList、LinkedList、HashMap等容器的实现细节和性能对比。 - **异常处理**:理解Checked和Unchecked异常,以及如何优雅地处理异常。 - **多线程与并发**:线程的创建、同步机制...
通过分析ArrayList的源码,我们可以学习到如何创建一个类似的数据结构,这有助于我们提升对数组、扩容、索引操作等概念的理解。 首先,自定义的MyArrayList类需要一个存储元素的数组,这里选择的是`Object[] ...