博客
关于我
手工实现ArrayList
阅读量:570 次
发布时间:2019-03-11

本文共 4073 字,大约阅读时间需要 13 分钟。

ArrayList底层JDK源码解读

ArrayList底层采用数组来实现存储,具有查询效率高、增删效率低、线程不安全等特点。尽管如此,它在大多数实际应用场景中仍然是首选的集合数据结构。

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); }}

ArrayList的特点及适用场景

  • 查询效率高:由于数据存储在数组中,随机访问的时间复杂度为O(1),使得ArrayList的查询效率非常高。

  • 增删效率低:插入和删除操作时,可能需要扩展数组,这导致在最坏情况下时间复杂度为O(n),不适合频繁的增删操作。

  • 线程不安全:ArrayList非线程安全,可能会导致并发修改时的数据不一致。如果需要多线程环境下的安全性,需要额外采取同步措施。

  • 实际应用中的优化建议

    在实际应用中,可以通过以下方式优化ArrayList的性能:

  • 预设初始容量:如果对数据增量较小,建议预先设定一个合理的初始容量,减少频繁扩容带来的性能损失。

  • 使用合适的数据结构:如果需要频繁增删操作且数据结构不经常改变,优先考虑使用 LinkedHashSet 或 HashSet等其他数据结构。

  • 避免使用过度缩放:虽然 ArrayList 允许动态调整容量,但过度缩放会导致频繁的内存分配和数组复制操作,影响性能。

  • 最佳实践

    在使用 ArrayList 时,可以通过如下方式提高性能:

  • 减少不必要的操作:避免在循环中频繁调用 add() 和 remove() 方法,尽量将这些操作放入批处理循环中。

  • 设置合理的初始容量:如果数据源是固定大小,可以通过预先设定初始容量减少内 memory allocation 的开销。

  • 垃圾回收优化:避免过度保留对应的内存,及时清除数组中不再使用的元素,可以通过调用 System.gc() 来帮助垃圾回收。

  • 如果需要更高效的增删和线程安全,推荐使用ाहकstrcasecmp ConcurrentHashMapCopyOnWriteArrayList,但这些数据结构的开销也需要权衡。

    代码示例

    以下是一个使用 ArrayList 的实际应用示例:

    import java.util.ArrayList;public class ArrayListExample {    public static void main(String[] args) {        ArrayList
    list = 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/

    你可能感兴趣的文章
    redis持久化分析
    查看>>
    复杂指针解析
    查看>>
    打开word时424错误
    查看>>
    如何添加开机自启项
    查看>>
    ❤️一个18k运维项目经验这样做的,offer到碗里来❤️
    查看>>
    关于宝塔面板安装的mysql用Navicat连接出现2003的错误解决
    查看>>
    Windows2016 FTP用户隔离
    查看>>
    js传入参数是中文的时候出现 “******”未定义错误
    查看>>
    responded with a status of 404 ()
    查看>>
    吴恩达机器学习课程笔记(英文授课) Lv.1 新手村(回归)
    查看>>
    pair的用法
    查看>>
    SQL基本操作命令
    查看>>
    强制类型转换原理
    查看>>
    伪类选择器
    查看>>
    两正态总体参数的检验
    查看>>
    C# WinForm程序退出的方法
    查看>>
    ubuntu安装gem和fastlane
    查看>>
    ViroMedia集成android报错Lcom/facebook/react/bridge/WritableMap
    查看>>
    onFailure unexpected end of stream
    查看>>
    android 集成weex
    查看>>