ArrayList指南针

简介: 当添加第一个元素时,ArrayList会创建一个初始容量为10的数组,并将元素存储在数组的第一个位置。当继续添加元素时,ArrayList会检查当前数组是否已满。如果数组已满,它会创建一个新的容量更大的数组,并将原数组中的元素复制到新数组中。新数组的容量通常是原数组容量的1.5倍(在旧版本的Java中是1倍),这样可以避免每次添加元素都进行扩容操作,提高性能。扩容操作涉及数组的拷贝,因

ArrayList

一,介绍

ArrayList 是 Java 中最常用的动态数组实现之一。它继承自 AbstractList 类,并实现了 List 接口,可以存储任意类型的元素,并且大小可以根据需要自动调整。

下面是对 ArrayList 的介绍:

1. 动态数组:ArrayList 内部使用数组作为数据结构,可以动态地增加或减少元素。与传统的静态数组相比,ArrayList 提供了更方便的元素操作和动态调整容量的能力。

2. 随机访问:ArrayList 支持通过索引快速访问和修改元素。由于底层采用数组实现,因此可以通过索引直接定位到元素,具有很高的访问效率。

3. 自动扩容:当 ArrayList 中的元素个数超过当前容量时,它会自动进行扩容,以容纳更多的元素。扩容过程涉及创建新的数组并将原始元素复制到新数组中,所以可能会导致一定的性能开销。

4. 允许存储重复元素:ArrayList 允许存储重复的元素,即相同的元素可以出现多次。

5. 可变长度:ArrayList 的长度是可变的,可以根据需要添加或删除元素。添加元素时,ArrayList 会自动调整内部的容量,确保能够容纳新的元素。

6. 非线程安全:ArrayList 不是线程安全的,不适合在多线程环境下使用。如果需要在多线程环境下使用,可以考虑使用线程安全的 Vector 类或通过同步手段来确保线程安全。

总而言之,ArrayList 是一个常用的动态数组实现,提供了高效的随机访问和动态调整长度的能力。它适用于需要频繁对元素进行增删改查操作的场景,但在多线程环境下需要注意其线程安全性。

Java中的ArrayList是一种常用的集合类,它实现了List接口,可以动态地增加或减少元素。ArrayList基于数组实现,提供了一系列方法来对元素进行操作。

下面是一些ArrayList的特点和常用方法:

  1. 动态大小:ArrayList的大小是可变的,可以根据需要动态地添加或删除元素。
  2. 索引访问:可以使用索引来访问ArrayList中的元素,索引从0开始,类似于数组。
  3. 有序集合:ArrayList中的元素是有序的,可以按照插入顺序进行访问。
  4. 允许重复元素:ArrayList允许存储重复的元素。

下面是一些常用的ArrayList方法:

  • add(element) :将指定元素添加到ArrayList的末尾。
  • add(index, element):将指定元素插入到ArrayList的指定位置。
  • get(index):获取指定位置的元素。
  • set(index, element):将指定位置的元素替换为新的元素。
  • remove(index):删除指定位置的元素。
  • size():返回ArrayList中元素的个数。
  • isEmpty():检查ArrayList是否为空。
  • contains(element):检查ArrayList是否包含指定元素。
  • clear():清空ArrayList中的所有元素。

这只是ArrayList的一些基本介绍和常用方法,还有其他更多的方法可以用于操作和处理ArrayList。在实际开发中,ArrayList经常用于存储和操作一组数据。

二,ArrayList 扩展原理

ArrayList的扩展原理涉及到底层的数据结构和内部实现机制。在Java中,ArrayList是基于数组实现的动态数组。

当我们创建一个ArrayList对象时,它会在内部创建一个初始容量为10的数组,并将元素存储在这个数组中。如果我们不断向ArrayList中添加元素,当数组的容量不足以容纳新的元素时,ArrayList会自动进行扩容操作。

ArrayList的扩容机制如下:

  1. 当添加第一个元素时,ArrayList会创建一个初始容量为10的数组,并将元素存储在数组的第一个位置。
  2. 当继续添加元素时,ArrayList会检查当前数组是否已满。如果数组已满,它会创建一个新的容量更大的数组,并将原数组中的元素复制到新数组中。
  3. 新数组的容量通常是原数组容量的1.5倍(在旧版本的Java中是1倍),这样可以避免每次添加元素都进行扩容操作,提高性能。
  4. 扩容操作涉及数组的拷贝,因此它的时间复杂度是O(n),其中n是当前ArrayList中的元素个数。
  5. 当数组的元素个数达到当前数组长度的75%时,ArrayList会自动扩容。也就是说,如果当前数组长度为n,当元素个数达到n*0.75时,ArrayList会进行扩容操作。

需要注意的是,ArrayList的扩容操作可能会带来一些性能开销,因为它需要重新分配内存并复制元素。为了避免频繁的扩容操作,我们可以在创建ArrayList时指定一个较大的初始容量,以减少扩容的次数。

另外,ArrayList还提供了一些方法来手动控制容量的增长,例如ensureCapacity(int minCapacity)方法可以确保ArrayList的容量至少为指定值。这样可以在预知需要存储大量元素时,提前分配足够的容量,减少扩容的次数。

总结起来,ArrayList通过动态扩容的方式实现了数组的自动增长,使得我们可以方便地添加和删除元素,同时提供了高效的随机访问能力。

三,ArrayList方法原理

1.arrayList add(element)

ArrayList的add(element)方法用于将指定元素添加到ArrayList的末尾。下面是该方法的原理说明:

  1. 首先,ArrayList会检查当前数组的容量是否足够容纳新的元素。如果当前数组的容量不足,即已存储的元素个数等于数组的长度(即size()等于array.length),则需要进行扩容操作。
  2. 扩容操作会创建一个新的容量更大的数组,通常是原数组容量的1.5倍(在旧版本的Java中是1倍)。然后,将原数组中的元素复制到新数组中。
  3. 接下来,将要添加的元素放置在新数组的末尾位置,即array[size()] = element。
  4. 最后,更新ArrayList的内部状态,包括将数组引用指向新数组,更新元素个数等。

需要注意的是,ArrayList的扩容操作可能会带来一些性能开销,因为它需要重新分配内存并复制元素。为了避免频繁的扩容操作,我们可以在创建ArrayList时指定一个较大的初始容量,以减少扩容的次数。

另外,如果我们知道要添加的元素个数,可以使用ensureCapacity(int minCapacity)方法提前分配足够的容量,避免不必要的扩容操作。这样可以提高性能,尤其在需要添加大量元素时。

总结起来,add(element)方法的原理是通过扩容操作来确保容量足够,然后将元素放置在数组的末尾位置,并更新ArrayList的内部状态。

2.add(index, element)原理

ArrayList的add(index, element)方法用于将指定元素插入到ArrayList的指定位置。下面是该方法的原理说明:

  1. 首先,ArrayList会检查当前数组的容量是否足够容纳新的元素。如果当前数组的容量不足,即已存储的元素个数等于数组的长度(即size()等于array.length),则需要进行扩容操作。
  2. 扩容操作会创建一个新的容量更大的数组,通常是原数组容量的1.5倍(在旧版本的Java中是1倍)。然后,将原数组中的元素复制到新数组中。
  3. 接下来,为了在指定位置插入新元素,需要将插入位置之后的元素向后移动一位,空出插入位置。这是通过循环将数组中的元素从插入位置开始依次向后移动实现的。
  4. 在移动元素完成后,将要插入的元素放置在指定位置,即array[index] = element。
  5. 最后,更新ArrayList的内部状态,包括将数组引用指向新数组,更新元素个数等。

需要注意的是,插入元素的操作可能会导致后续元素的移动,因此在ArrayList中插入元素的时间复杂度是O(n),其中n是ArrayList中元素的个数。如果需要频繁在ArrayList的中间位置插入元素,可能会导致性能下降。在这种情况下,可以考虑使用LinkedList等其他数据结构,因为LinkedList在中间位置插入元素的时间复杂度是O(1)。

总结起来,add(index, element)方法的原理是通过扩容操作确保容量足够,然后将插入位置之后的元素向后移动一位,空出插入位置,并将元素放置在指定位置,最后更新ArrayList的内部状态。

3.get(index) 原理

ArrayList的get(index)方法用于获取ArrayList中指定位置的元素。下面是该方法的原理说明:

  1. 首先,get(index)方法会检查指定的索引是否在有效范围内,即索引值大于等于0且小于size()(即元素个数)。
  2. 如果索引值有效,则直接通过索引访问数组中对应位置的元素,即array[index]。
  3. 最后,返回获取到的元素值。需要注意的是,get(index)方法的时间复杂度是O(1),因为它通过索引直接访问数组中的元素,不需要遍历或移动其他元素。

然而,如果频繁对ArrayList进行插入、删除等操作,可能会导致索引位置的变化,进而影响到get(index)方法的性能。在这种情况下,如果需要频繁根据索引获取元素,考虑使用LinkedList等其他数据结构可能更合适,因为LinkedList在获取指定位置元素的时间复杂度是O(n),其中n是索引位置。总结起来,get(index)方法的原理是通过索引直接访问数组中对应位置的元素,并返回获取到的元素值。

4.set(index, element)原理

ArrayList的set(index, element)方法用于将指定位置的元素替换为新的元素。下面是该方法的原理说明:

  1. 首先,

set(index, element)方法会检查指定的索引是否在有效范围内,即索引值大于等于0且小于size()(即元素个数)。

  1. 如果索引值有效,则直接通过索引访问数组中对应位置的元素,即array[index]。
  2. 将该位置的元素替换为新的元素,即array[index] = element。
  3. 最后,返回被替换的旧元素值。需要注意的是,set(index, element)方法的时间复杂度是O(1),因为它通过索引直接访问数组中的元素,并进行替换操作。与get(index)方法类似,set(index, element)方法不需要遍历或移动其他元素。然而,与add(index, element)方法不同,set(index, element)方法不会导致数组容量的变化,也不会导致其他元素的移动。

总结起来,set(index, element)方法的原理是通过索引直接访问数组中对应位置的元素,并将该位置的元素替换为新的元素。

5.remove(index) 原理

ArrayList的remove(index)方法用于移除指定位置的元素。下面是该方法的原理说明:

  1. 首先,remove(index)方法会检查指定的索引是否在有效范围内,即索引值大于等于0且小于size()(即元素个数)。
  2. 如果索引值有效,则通过索引访问数组中对应位置的元素,即array[index]。
  3. 将要移除的元素保存起来,以便返回。
  4. 将索引位置之后的元素依次向前移动一位,填补被移除的位置。这可以通过将

array[i]的值设置为array[i+1]来实现,其中i从索引位置开始,直到size()-1。

  1. 将数组中最后一个元素置为null,以便释放对该对象的引用,帮助垃圾回收。
  2. 减少ArrayList的大小,即将size减1。
  3. 返回被移除的元素。

需要注意的是,remove(index)方法的时间复杂度是O(n),其中n是索引位置之后的元素个数。因为该方法需要移动索引位置之后的元素,以填补被移除的位置。如果需要频繁根据索引移除元素,考虑使用LinkedList等其他数据结构,因为LinkedList在移除指定位置元素的时间复杂度是O(1)。

总结起来,remove(index)方法的原理是通过索引访问数组中对应位置的元素,并将该位置之后的元素向前移动一位,然后减少ArrayList的大小,并返回被移除的元素。

6.size()原理

size()方法用于返回ArrayList中元素的个数。下面是该方法的原理说明:

  1. size()

方法直接返回ArrayList对象内部的一个整数变量,该变量记录了ArrayList中当前存储的元素个数。

  1. 当向ArrayList中添加或移除元素时,该整数变量会相应地进行增加或减少。
  2. 初始时,ArrayList的元素个数为0。
  3. 当调用

add(element)方法向ArrayList中添加一个元素时,会将元素存储在数组中的下一个可用位置,并将元素个数加1。

  1. 当调用

remove(index)方法移除一个元素时,会将指定位置的元素移除,并将元素个数减1。

  1. 当调用

clear()方法清空ArrayList中的所有元素时,将元素个数设置为0。

  1. size()

方法会直接返回记录的元素个数,不需要遍历整个数组。

需要注意的是,size()方法的时间复杂度是O(1),因为它只是返回一个已经记录的整数值,不需要遍历整个数组或进行其他复杂的操作。

总结起来,size()方法的原理是直接返回ArrayList对象内部记录的元素个数,该值会随着元素的添加和移除而相应地进行增加或减少。

7.isEmpty()原理

isEmpty()方法用于检查ArrayList是否为空,即判断ArrayList中是否没有任何元素。下面是该方法的原理说明:

  1. isEmpty()

方法通过检查ArrayList内部的元素个数来确定ArrayList是否为空。

  1. 当ArrayList的元素个数为0时,即没有任何元素存储在ArrayList中,

isEmpty()方法返回true表示ArrayList为空。

  1. 当ArrayList的元素个数大于0时,

isEmpty()方法返回false表示ArrayList不为空。

  1. isEmpty()

方法的实现通常是通过检查内部的元素个数是否为0来实现的,例如通过调用size()方法并判断返回值是否为0。

需要注意的是,isEmpty()方法的时间复杂度是O(1),因为它只是检查内部的元素个数是否为0,不需要遍历整个数组或进行其他复杂的操作。

总结起来,isEmpty()方法的原理是通过检查ArrayList内部的元素个数是否为0来确定ArrayList是否为空。

8.contains(element)原理

contains(element)方法用于检查ArrayList中是否包含特定元素。下面是该方法的原理说明:

  1. contains(element)

方法通过遍历ArrayList中的元素,逐个比较每个元素和指定的元素是否相等来确定是否包含该元素。

  1. 该方法从ArrayList的第一个元素开始,依次比较每个元素与指定元素是否相等。
  2. 如果找到与指定元素相等的元素,则返回

true表示ArrayList包含该元素。

  1. 如果遍历完整个ArrayList都没有找到与指定元素相等的元素,则返回

false表示ArrayList不包含该元素。

需要注意的是,contains(element)方法的时间复杂度取决于ArrayList中的元素个数和元素的位置。最坏情况下,需要遍历整个ArrayList才能确定是否包含指定元素,因此时间复杂度为O(n),其中n是ArrayList中的元素个数。

总结起来,contains(element)方法的原理是通过遍历ArrayList中的元素,逐个比较元素和指定元素是否相等来确定ArrayList是否包含该元素。

9.clear()原理

clear()方法用于清空ArrayList中的所有元素,即将ArrayList的大小设置为0,删除所有元素。下面是该方法的原理说明:

  1. clear()

方法通过将ArrayList的内部数组的引用设置为一个新的空数组来清空ArrayList的元素。

  1. 当调用

clear()方法时,ArrayList会创建一个新的空数组,并将内部的数组引用指向这个新数组。

  1. 由于原来的数组不再被引用,它将成为垃圾,由垃圾回收器进行回收。
  2. 清空ArrayList后,其

size()方法返回0,即ArrayList中没有任何元素。

需要注意的是,clear()方法的时间复杂度为O(1),因为它只是将内部的数组引用指向一个新的空数组,并不需要遍历整个数组或进行其他复杂的操作。

总结起来,clear()方法的原理是通过将ArrayList的内部数组引用指向一个新的空数组来清空ArrayList的元素。这样做可以快速且有效地清空ArrayList,使其不包含任何元素。

四,总结

       详细介绍了ArrayList的特点、扩展原理和常用方法,并且给出了每个方法的原理说明。对于初学者来说,这篇文章对于理解ArrayList的工作原理和使用方法非常有帮助。同时,文章还提到了一些注意事项,例如ArrayList的扩容操作可能会影响性能,因此在创建ArrayList时可以设置较大的初始容量,避免不必要的扩容操作。总之,这篇文章详细介绍了ArrayList的内部实现和使用方法,对于Java开发者来说是非常有价值的。

目录
相关文章
|
9天前
|
Java 编译器 UED
Arrays.asList() 数组转换成集合酿成的线上事故,差点要滚蛋了!
本文介绍了Java开发中使用`Arrays.asList()`方法将数组转换为集合时的一个常见陷阱。该方法返回的List是固定长度的,不支持添加或删除操作,直接使用可能导致线上故障。文章通过一次实际开发中的事故案例,分析了问题的原因,并提供了使用`java.util.ArrayList`进行封装的解决方案,以避免此类错误的发生。希望读者能从中吸取教训,提高代码的健壮性。
|
6月前
|
Java 开发者
揭秘!LinkedList是如何华丽变身成为Java队列之王的?
【6月更文挑战第18天】Java的`LinkedList`既是列表也是队列之星,实现`Queue`接口,支持FIFO操作。其内部的双向链表结构确保了添加/移除元素的高效性(O(1)),适合作为队列使用。它线程不安全,但可通过同步包装用于多线程环境。此外,`LinkedList`还能灵活变身栈或双端队列,提供多种数据结构功能。
62 11
|
6月前
|
Java 索引
那些年,我们追过的Java List——ArrayList与LinkedList的爱恨情仇
【6月更文挑战第17天】ArrayList与LinkedList,Java List接口的双子星,各有千秋。ArrayList基于数组,随机访问快速,但插入删除慢;LinkedList用链表实现,插入删除高效,但索引访问慢。两者在爱恨情仇中教会我们权衡选择,成为编程旅程中难忘的记忆。 ```
27 0
|
6月前
|
Java
JavaSE——集合框架二(2/6)-综合案例-斗地主游戏(做牌、洗牌、发牌、排序、看牌)
JavaSE——集合框架二(2/6)-综合案例-斗地主游戏(做牌、洗牌、发牌、排序、看牌)
27 0
|
存储 缓存 C++
【C++干货铺】list的使用 | 模拟实现
【C++干货铺】list的使用 | 模拟实现
|
算法 C++
[C++随笔录] list使用
[C++随笔录] list使用
|
缓存 Java 编译器
一文颠覆你对 ArrayList 和 LinkedList 的认知
在初学Java的时候我们经常能看到这么一句话:ArrayList增删慢查询快,LinkedList增删快查询慢。但随着学习的不断深入,我们会发现这句话并不对,初学时看到这句话主要还是为了新手友好。
250 0
一文颠覆你对 ArrayList 和 LinkedList 的认知
|
存储 小程序 Java
Java数据结构之基于ArrayList编写大众麻将和扑克牌洗牌小练习
本文讲解:Java数据结构之基于ArrayList编写大众麻将和扑克牌洗牌小练习