18_Java集合ArrayList
2022/6/8 1:20:09
本文主要是介绍18_Java集合ArrayList,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
ArrayList 集合可以理解为 存储引用类型元素 的数据容器,元素类型不限,但可以通过 指定类型参数 限制可以存储的数据类型。
常用方法
- 增添元素
// 在末尾添加元素 public boolean add(E e) // 在指定位置插入元素 public void add(int index, E element)
- 删除元素
// 删除指定元素,只删除第一个相同的元素 public boolean remove(Object o) // 删除指定索引的元素 public E remove(int index) // 删除所有元素 public void clear()
- 修改元素
// 修改指定索引的元素 public E set(int index, E e)
- 查找元素
// 顺序查找,返回元素索引位置 public int indexOf(Object o) // 倒序查找,返回元素索引位置 public int lastIndexOf(Object o) // 是否包含指定元素 public boolean contains(Object o)
- 访问元素
// 访问指定索引处的元素 public E get(int index)
- 获取元素个数
// 获取容器中的元素个数 public int size()
基本原理
transient Object[] elementData; // 存放元素 private int size; // 记录存放的元素个数 protected transient int modCount = 0; // 父类 AbstractList 中,记录修改次数
ArrayList 是基于数组实现的,Object 数组 elementData 存放元素,变量 size 记录实际存放的元素个数,modCount 记录修改次数,每次发生结构性变化的时候 modCount 都会增加。
- add 方法
private static final int DEFAULT_CAPACITY = 10; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureExplicitCapacity(int minCapacity) { modCount++; // modCount 表示内部的修改次数 // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
迭代遍历
- 普通循环遍历
可以使用 while、for 循环对 ArrayList 集合进行遍历。
- foreach 迭代遍历
ArrayList<Integer> arrayList = new ArrayList<>(); arrayList.add(1); arrayList.add(2); arrayList.add(3); for (Integer ele: arrayList) { System.out.println(ele); }
编译器会对 foreach 语法进行转换。
while(arrayList.hasNext()){ System.out.println(arrayList.next()); }
ArrayList 实现了 Iterable 接口,Iterable 表示可迭代,只要实现了 Iterable 接口,就可以使用 foreach 语法。
public interface Iterable<T> { Iterator<T> iterator(); }
iterator 方法返回一个实现了 Iterator 接口的对象。
public interface Iterator<E> { boolean hasNext(); // 判断是否还有元素可访问 E next(); // 返回下一个元素 default void remove() { // 删除最后返回的元素 throw new UnsupportedOperationException("remove"); } }
来看 ArrayList 中的 iterator:
public Iterator<E> iterator() { return new Itr(); }
// 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; // 每次发生结构性变化的时候 modCount 都会增加 Itr() {} 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]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
注意迭代中的删除:
/** * foreach 遍历时不能直接调用 remove 方法进行删除 * 因为 foreach 实际是调用 Iterator 的方法,迭代器遍历时会维护索引位置相关的数据 * 直接 remove 会导致结构变化,导致索引数据失效 */ for (Integer ele: arrayList) { if(ele == 2) arrayList.remove(ele); // 执行报错 System.out.println(ele); }
使用迭代器删除:
Iterator<Integer> it = arrayList.iterator(); while (it.hasNext()){ if(it.next() == 2) it.remove(); }
实现接口
- Collection
Collection 表示一个数据集合,数据没有位置或顺序的概念。
- List
List 表示有顺序或位置的数据集合,主要方法都与位置有关。
- RandomAccess
标记接口,RandomAccess 表示可以随机访问,数据在内存是连续存放的,根据索引值可以直接定位到具体的元素,访问效率很高。
主要特点
- 只能存放引用类型数据
- 底层结构是数组,增删慢,查询相对较快,数据在内存连续存放,可以根据索引随机快速访问
- 线程不安全
这篇关于18_Java集合ArrayList的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南