本文共 4073 字,大约阅读时间需要 13 分钟。
ArrayList底层采用数组来实现存储,具有查询效率高、增删效率低、线程不安全等特点。尽管如此,它在大多数实际应用场景中仍然是首选的集合数据结构。
ArrayList的源码定义如下:
package sxt.gaoqi.container;/** * 增加泛型 * 扩容 * get/set方法 * 索引越界RuntimeException * 增加remove */public class JsArrayList{ private Object[] elementData; private int size; private static final int DEFAULT_CAPACITY = 10; public JsArrayList() { elementData = new Object[DEFAULT_CAPACITY]; } public JsArrayList(int capacity) { if (capacity < 0) { throw new RuntimeException("容器的容量不能为负数: " + capacity); } else if (capacity == 0) { elementData = new Object[DEFAULT_CAPACITY]; } else { elementData = new Object[capacity]; } } public void add(E obj) { // 判断是否需要扩容 if (size == elementData.length) { // 扩容方式:新长度为当前长度的双倍加一 Object[] newArray = new Object[elementData.length + (elementData.length > 1 ? 1 : 0)]; System.arraycopy(elementData, 0, newArray, 0, elementData.length); elementData = newArray; } elementData[size++] = obj; } public E get(int index) { checkRange(index); return (E) elementData[index]; } public void set(E element, int index) { checkRange(index); elementData[index] = element; } public void checkRange(int index) { if (index < 0 || index >= size) { throw new RuntimeException("指针越界" + index); } } public void remove(E element) { // 逐一比较并删除第一个匹配的元素 for (int i = 0; i < size; i++) { if (element.equals(get(i))) { remove(i); } } } public void remove(int index) { // 移动元素位置并缩小数组范围 int moveLength = index < size - 1 ? size - index - 1 : 0; if (moveLength > 0) { System.arraycopy(elementData, index + 1, elementData, index, moveLength); } elementData[--size] = null; } public int size() { return size; } public boolean isEmpty() { return size == 0; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("["); for (int i = 0; i < size; i++) { sb.append(elementData[i] + ","); } sb.setCharAt(sb.length() - 1, ']'); return sb.toString(); } public static void main(String[] args) { JsArrayList s1 = new JsArrayList<>(); for (int i = 0; i < 40; i++) { s1.add("aa" + i); } System.out.println(s1); s1.set("森", 10); System.out.println(s1); System.out.println(s1.get(10)); // 测试get方法 s1.remove(2); // 测试remove方法 s1.remove("aa4"); System.out.println(s1); }}
查询效率高:由于数据存储在数组中,随机访问的时间复杂度为O(1),使得ArrayList的查询效率非常高。
增删效率低:插入和删除操作时,可能需要扩展数组,这导致在最坏情况下时间复杂度为O(n),不适合频繁的增删操作。
线程不安全:ArrayList非线程安全,可能会导致并发修改时的数据不一致。如果需要多线程环境下的安全性,需要额外采取同步措施。
在实际应用中,可以通过以下方式优化ArrayList的性能:
预设初始容量:如果对数据增量较小,建议预先设定一个合理的初始容量,减少频繁扩容带来的性能损失。
使用合适的数据结构:如果需要频繁增删操作且数据结构不经常改变,优先考虑使用 LinkedHashSet 或 HashSet等其他数据结构。
避免使用过度缩放:虽然 ArrayList 允许动态调整容量,但过度缩放会导致频繁的内存分配和数组复制操作,影响性能。
在使用 ArrayList 时,可以通过如下方式提高性能:
减少不必要的操作:避免在循环中频繁调用 add() 和 remove() 方法,尽量将这些操作放入批处理循环中。
设置合理的初始容量:如果数据源是固定大小,可以通过预先设定初始容量减少内 memory allocation 的开销。
垃圾回收优化:避免过度保留对应的内存,及时清除数组中不再使用的元素,可以通过调用 System.gc()
来帮助垃圾回收。
如果需要更高效的增删和线程安全,推荐使用ाहकstrcasecmp ConcurrentHashMap
或CopyOnWriteArrayList
,但这些数据结构的开销也需要权衡。
以下是一个使用 ArrayList 的实际应用示例:
import java.util.ArrayList;public class ArrayListExample { public static void main(String[] args) { ArrayListlist = new ArrayList<>(); list.add("Hello"); list.add("World"); System.out.println("ArrayList: " + list); // [Hello, World] list.remove(1); // 删除第二个元素 System.out.println("ArrayList: " + list); // [Hello] list.add("Test"); System.out.println("ArrayList: " + list); // [Hello, Test] }}
以上代码展示了一个简单的 ArrayList 使用示例,演示了如上提到的基本操作:add()
、remove()
和 toString()
方法的使用。
转载地址:http://aeavz.baihongyu.com/