List、ArrayList、LinkList

本文详细介绍了Java中List接口的两种实现:ArrayList与LinkedList的特点及使用场景。对比了两种数据结构在增删查改操作上的效率差异,并提供了示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考以下内容

http://blog.youkuaiyun.com/vaniice/article/details/6102015
http://www.cnblogs.com/skywang12345/p/3308556.html

List

List包括List接口以及List接口的所有实现类。因为List接口实现了Collection接口,所以List接口拥有Collection接口提供的所有常用方法,又因为List是列表类型,所以List接口还提供了一些适合于自身的常用方法,如表所示。
List接口常用方法
注意:indexOf(Object obj)方法获得指定对象的最小的索引位置,和lastIndexOf(Object obj)方法而后者是获得指定对象的最大的索引位置
前提条件是指定的对象在List集合中具有重复的对象,否则如果在List集合中有且仅有一个指定的对象,则通过这两个方法获得的索引位置是相同的
注意subList(int fromIndex, int toIndex)方法截取现有List集合中的部分对象生成新的List集合时,新生成的集合中包含起始索引位置代表的对象,但是不包含终止索引位置代表的对象

List接口的常用实现类有ArrayList和LinkedList,在使用List集合时,通常情况下声明为List类型,实例化时根据实际情况的需要,实例化为ArrayList或LinkedList。
例如:

List<String> llist= new ArrayList<String>();// 利用ArrayList类实例化List集合
List<String> list = new LinkedList<String>();// 利用LinkedList类实例化List集合

ArrayList

概述:
ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长。ArrayList不是线程安全的。
ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了RandomAccess接口,支持快速随机访问,实际上就是通过下标序号进行快速访问,实现了Cloneable接口,能被克隆。

ArrayList构造函数
// 默认构造函数
ArrayList()

// capacity是ArrayList的默认容量大小。当由于增加数据导致容量不足时,容量会添加上一次容量大小的一半。
ArrayList(int capacity)

// 创建一个包含collection的ArrayList
ArrayList(Collection

// Collection中定义的API
boolean             add(E object)
boolean             addAll(Collection<? extends E> collection)
void                clear()
boolean             contains(Object object)
boolean             containsAll(Collection<?> collection)
boolean             equals(Object object)
int                 hashCode()
boolean             isEmpty()
Iterator<E>         iterator()
boolean             remove(Object object)
boolean             removeAll(Collection<?> collection)
boolean             retainAll(Collection<?> collection)
int                 size()
<T> T[]             toArray(T[] array)
Object[]            toArray()
// AbstractCollection中定义的API
void                add(int location, E object)
boolean             addAll(int location, Collection<? extends E> collection)
E                   get(int location)
int                 indexOf(Object object)
int                 lastIndexOf(Object object)
ListIterator<E>     listIterator(int location)
ListIterator<E>     listIterator()
E                   remove(int location)
E                   set(int location, E object)
List<E>             subList(int start, int end)
// ArrayList新增的API
Object               clone()
void                 ensureCapacity(int minimumCapacity)
void                 trimToSize()
void                 removeRange(int fromIndex, int toIndex)

程序例子:`

 1    import java.util.*;
 2 
 3 /*
 4  * @desc ArrayList常用API的测试程序
 5  * @author TiAmero 
 6  * @email TiAmero@163.com
 7  */
 8 public class ArrayListTest {
 9 
10     public static void main(String[] args) {
11         
12         // 创建ArrayList
13         ArrayList list = new ArrayList();
14 
15         // 将“”
16         list.add("1");
17         list.add("2");
18         list.add("3");
19         list.add("4");
20         // 将下面的元素添加到第1个位置
21         list.add(0, "5");
22 
23         // 获取第1个元素
24         System.out.println("the first element is: "+ list.get(0));
25         // 删除“3”
26         list.remove("3");
27         // 获取ArrayList的大小
28         System.out.println("Arraylist size=: "+ list.size());
29         // 判断list中是否包含"3"
30         System.out.println("ArrayList contains 3 is: "+ list.contains(3));
31         // 设置第2个元素为10
32         list.set(1, "10");
33 
34         // 通过Iterator遍历ArrayList
35         for(Iterator iter = list.iterator(); iter.hasNext(); ) {
36             System.out.println("next is: "+ iter.next());
37         }
38 
39         // 将ArrayList转换为数组
40         String[] arr = (String[])list.toArray(new String[0]);
41         for (String str:arr)
42             System.out.println("str: "+ str);
43 
44         // 清空ArrayList
45         list.clear();
46     }
47 } 

结果:

`the first element is: 5
Arraylist size=: 4
ArrayList contains 3 is: false
next is: 5
next is: 10
next is: 2
next is: 4
str: 5
str: 10
str: 2
str: 4

ArrayList遍历方式

ArrayList支持3种遍历方式

(01) 第一种,通过迭代器遍历。即通过Iterator去遍历。

Integer value = null;
Iterator iter = list.iterator();
while (iter.hasNext()) {
    value = (Integer)iter.next();
} 

(02) 第二种,随机访问,通过索引值去遍历。
由于ArrayList实现了RandomAccess接口,它支持通过索引值去随机访问元素。

Integer value = null;
int size = list.size();
for (int i=0; i<size; i++) {
    value = (Integer)list.get(i);        
} 

(03) 第三种,for循环遍历。如下:

Integer value = null;
for (Integer integ:list) {
    value = integ;

注:随机访问(即,通过索引序号访问)效率最高,而使用迭代器的效率最低!

概述:
  LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
LinkedList 是非同步的。

LinkedList构造函数
// 默认构造函数

LinkedList()

// 创建一个LinkedList,保护Collection中的全部元素。

LinkedList(Collection<? extends E> collection)

LinkedList的API

boolean       add(E object)
void          add(int location, E object)
boolean       addAll(Collection<? extends E> collection)
boolean       addAll(int location, Collection<? extends E> collection)
void          addFirst(E object)
void          addLast(E object)
void          clear()
Object        clone()
boolean       contains(Object object)
Iterator<E>   descendingIterator()
E             element()
E             get(int location)
E             getFirst()
E             getLast()
int           indexOf(Object object)
int           lastIndexOf(Object object)
ListIterator<E>     listIterator(int location)
boolean       offer(E o)
boolean       offerFirst(E e)
boolean       offerLast(E e)
E             peek()
E             peekFirst()
E             peekLast()
E             poll()
E             pollFirst()
E             pollLast()
E             pop()
void          push(E e)
E             remove()
E             remove(int location)
boolean       remove(Object object)
E             removeFirst()
boolean       removeFirstOccurrence(Object o)
E             removeLast()
boolean       removeLastOccurrence(Object o)
E             set(int location, E object)
int           size()
<T> T[]       toArray(T[] contents)
Object[]      toArray()

ArrayList与LinkList比较:
“ArrayList是基于数据实现的list,而LinkedList是基于链表实现的list。所以,ArrayList拥有着数组的特性,LinkedList拥有着链表的特性。

ArrayList:

  优点:适合随机读取的时候,读取速度快,可以一步get(index)。

  缺点:添加值很慢——一方面,添加数据在array中间的时候,需要移动后面的数;另一方面,当长度大于初始长度的时候,每添加一个数,都会需要扩容。

  LinkedList:双向链表
  优点:添加值很快——添加在list中间也只需要更改指针;长度不固定。
  实现栈和队列方面,LinkedList要优于ArrayList。
  ArrayList的增删比LinkedList的开销更大,因为除了有查找的时间复杂度外,还有增删的移动过程。

写在后面:东西写的不进人意,很多遗漏,谬误。边学边改进。

### 数据结构区别 ArrayList 是基于动态数组实现的线性数据结构,其内部维护一个连续的数组来存储元素。由于数组是连续内存空间,因此支持快速随机访问,并且在末尾插入或删除元素的时间复杂度为 O(1)(除非需要扩容或缩容)[^5]。 LinkedList 是基于双向链表实现的线性数据结构,每个节点包含前驱指针、后继指针数据域。它不支持高效的随机访问,查找元素时必须从头或尾开始遍历,因此访问时间复杂度为 O(n)。但在头部或尾部进行插入或删除操作时,时间复杂度为 O(1),而中间位置的操作则需要遍历到目标位置,平均时间复杂度为 O(n)[^3]。 ### 时间复杂度比较 | 操作类型 | ArrayList | LinkedList | |------------------|------------------------------------|------------------------------------| | 随机访问 | O(1)(通过索引直接定位) [^5] | O(n)(需遍历链表) [^4] | | 末尾插入/删除 | 均摊 O(1)(可能触发扩容/缩容) [^5]| O(1)(直接修改指针) [^3] | | 中间插入/删除 | O(n)(需移动元素) [^5] | O(n)(需遍历至指定位置) [^3] | | 头部插入/删除 | O(n)(需整体后移) [^5] | O(1)(直接修改头节点) [^3] | ### 应用场景对比 #### ArrayList 的适用场景 - **频繁的随机访问**:由于支持通过索引快速访问元素,适合用于读取密集型操作。 - **尾部操作为主**:当主要操作集中在列表末尾(如栈结构或队列的入队出队)时,性能较好。 - **内存连续性要求较高**:ArrayList 内部使用数组,元素在内存中是连续存放的,有利于缓存局部性优化[^5]。 #### LinkedList 的适用场景 - **频繁的头部或中间插入/删除操作**:尤其适用于需要频繁在头部或已知位置附近进行增删操作的场景。 - **作为双端队列使用**:LinkedList 实现了 Deque 接口,可以高效地作为队列或双端队列使用。 - **不依赖随机访问的场景**:如果程序逻辑不需要频繁根据索引获取元素,则可考虑使用 LinkedList [^3]。 ### 示例代码:不同操作下的性能差异 ```java import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class ListPerformanceTest { public static void main(String[] args) { int size = 100000; // 测试在尾部添加 testAddToTail(new ArrayList<>(), "ArrayList (tail)"); testAddToTail(new LinkedList<>(), "LinkedList (tail)"); // 测试在中间插入 testInsertMiddle(new ArrayList<>(), "ArrayList (middle)"); testInsertMiddle(new LinkedList<>(), "LinkedList (middle)"); // 测试随机访问 testRandomAccess(new ArrayList<>(), "ArrayList (random access)"); testRandomAccess(new LinkedList<>(), "LinkedList (random access)"); } private static void testAddToTail(List<Integer> list, String name) { long start = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { list.add(i); } long end = System.currentTimeMillis(); System.out.println(name + ": Add to tail took " + (end - start) + " ms"); } private static void testInsertMiddle(List<Integer> list, String name) { for (int i = 0; i < 10000; i++) { list.add(i); } long start = System.currentTimeMillis(); for (int i = 0; i < 1000; i++) { list.add(5000, i); } long end = System.currentTimeMillis(); System.out.println(name + ": Insert in middle took " + (end - start) + " ms"); } private static void testRandomAccess(List<Integer> list, String name) { for (int i = 0; i < 10000; i++) { list.add(i); } long start = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { int value = list.get(5000); // 访问中间元素 } long end = System.currentTimeMillis(); System.out.println(name + ": Random access took " + (end - start) + " ms"); } } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值