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-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了
- 2024-05-09Google Chrome驱动程序 124.0.6367.62(正式版本)去哪下载?
- 2024-05-09有没有大佬知道这种数据应该怎么抓取呀?
- 2024-05-09这种运行结果里的10.100000001,怎么能最快改成10.1?
- 2024-05-09企业src漏洞挖掘-有意思的命令执行
- 2024-05-08阿里云域名注册流程,分享给第一次购买域名的新手站长!