目录
- 前言
- 一、常用List
- 1.1 List
- 1.1.1 特点
- 1.1.2 常用API
- 1.2 ArrayList
- 1.2.1 特点
- 1.2.2 使用
- 1.3 LinkedList
- 1.3.1 特点
- 1.3.2 使用
- 1.4 CopyOnWriteArrayList
- 1.4.1 特点
- 1.4.2 使用
- 1.5 Arrays.asList()
- 1.5.1 特点
- 1.5.2 使用
- 二、对比总结
前言
一、常用List
1.1 List
List是Java集合框架中的接口,表示有序的集合,可以包含重复元素。
public interface List<E> extends Collection<E> {
1.1.1 特点
特点:允许元素重复,有序集合,可以通过索引访问元素。
1.1.2 常用API
api | 作用描述 |
---|---|
boolean add(E element) | 将指定元素添加到列表的末尾。 |
void add(int index, E element) | 在指定位置插入元素。 |
E get(int index) | 返回指定位置的元素。 |
E remove(int index) | 移除指定位置的元素。 |
boolean remove(Object o) | 移除指定元素。 |
boolean contains(Object o) | 判断列表是否包含指定元素。 |
int size() | 返回列表中的元素个数。 |
boolean isEmpty() | 判断列表是否为空。 |
void clear() | 清空列表中的所有元素。 |
E set(int index, E element) | 将指定位置的元素替换为新元素。 |
1.2 ArrayList
ArrayList是基于数组实现的动态数组。
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
1.2.1 特点
ArrayList的特点:支持随机访问元素,插入和删除元素效率较低。
1.2.2 使用
public static void test1() {//使用ArrayList类创建列表List<Integer> numbers = new ArrayList<>();//将元素添加到列表numbers.add(1);numbers.add(2);numbers.add(3);System.out.println("List: " + numbers);//从列表中访问元素int number = numbers.get(2);System.out.println("访问元素: " + number);//从列表中删除元素int removedNumber = numbers.remove(1);System.out.println("删除元素: " + removedNumber);}
输出:
1.3 LinkedList
LinkedList是基于双向链表实现的列表。
public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable
1.3.1 特点
特点:适合插入和删除元素,但随机访问元素效率较低。
LinkedList与ArrayList的区别:
LinkedList和ArrayList都实现Collections框架的List接口。 但是,它们之间存在一些差异。
LinkedList | ArrayList |
---|---|
在单个位置存储3个值(上一个地址,数据和下一个地址) | 将单个值存储在单个位置 |
提供list的双链接列表实现 | 提供可调整大小的数组实现 |
每当添加元素时,上一个和下一个地址都会更改 | 每当添加元素时,该位置之后的所有元素都会移动 |
要访问元素,我们需要从头开始迭代到元素 | 可以使用索引随机访问元素。 |
1.3.2 使用
addFirst() - 将指定的元素添加到链接列表的开头
addLast() - 将指定的元素添加到链接列表的末尾
public static void test1() {Deque<String> animals = new LinkedList<>();//在LinkedList的开始处添加元素animals.addFirst("Cow");animals.addFirst("Dog");animals.addFirst("Cat");System.out.println("LinkedList: " + animals);//在LinkedList的末尾添加元素animals.addLast("Zebra");System.out.println("新的LinkedList: " + animals);}
输出:
1.4 CopyOnWriteArrayList
CopyOnWriteArrayList是线程安全的ArrayList,使用写时复制的机制。
public class CopyOnWriteArrayList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
1.4.1 特点
优点:适合多线程环境下遍历频繁、修改少的场景,支持并发读取,解决开发工作中的多线程并发问题
缺点:
- 内存占用问题:两个数组同时驻扎在内存中,如果实际应用中,数据比较多,而且比较大的情况下,占用内存会比较大,针对这个其实可以使用ConcurrentHashMap来代替。
- 数据一致性:CopyOnWriteArrayList容器只能保证数据的最终已执行,不能保证数据的实时一致性,所以如果希望写入的数据,马上能读取到,就不能使用CopyOnWriteArrayList。
CopyOnWriteArrayList详细内容查看如下文章:
CopyOnWriteArrayList详解及使用
1.4.2 使用
public class myCopyOnWriteArrayList {public static void main(String[] args) {startTest();}private static final Integer THREAD_POOL_MAX_SIZE = 10;// 不支持并发
// private static List<String> mList = new ArrayList<>();// 支持并发private static List<String> mList = new CopyOnWriteArrayList<>();private static void startTest() {// 初始化数据for (int i = 0; i < 10; i++) {mList.add("line:" + (i + 1) + "data");}System.out.println("------------初始化完成--------------------------");ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_MAX_SIZE);// 读写并发测试for (int i = 0; i < THREAD_POOL_MAX_SIZE; i++) {// 读任务立即执行executorService.execute(() -> {for (String item : mList) {System.out.println(Thread.currentThread().getName() + "数据:" + item);}});final int final1 = i + 10;// 写任务立即执行executorService.execute(() -> {mList.add("写线程添加数据" + final1 + "..............");});}}
}
1.5 Arrays.asList()
Arrays.asList():将数组转换为List的静态方法。
List< String> list = Arrays.asList(“a”,“b”,“c”);
注意:
(1)该方法适用于对象型数据的数组(String、Integer…)
(2)该方法不建议使用于基本数据类型的数组(byte,short,int,long,float,double,boolean)
(3)该方法将数组与List列表链接起来:当更新其一个时,另一个自动更新
(4)不支持add()、remove()、clear()等方法
(5)用此方法得到的List的长度是不可改变的
1.5.1 特点
特点:方便将数组转换为List,但返回的List不支持增删操作
。
1.5.2 使用
public static void test1(){//1、使用asList()的String数组,正常String[] strings = {"aa", "bb", "cc"};List<String> stringList = Arrays.asList(strings);System.out.print("1、使用asList()的String数组,正常: ");for(String str : stringList){System.out.print(str + " ");}System.out.println();//2、使用asList()的对象类型(Integer)数组,正常Integer[] integers = new Integer[] {1, 2, 3};List<Integer> integerList = Arrays.asList(integers);System.out.print("2、使用asList()的对象类型数组,正常: ");for(int i : integerList){System.out.print(i + " ");}System.out.println();//3、使用asList()的基本数据类型数组,出错int[] ints = new int[]{1, 2, 3};List intList = Arrays.asList(ints);System.out.print("3、使用asList()的基本数据类型数组,出错(将'ints'视为单个元素):");for(Object o : intList){System.out.print(o.toString());}System.out.println();System.out.print(" " + "要正确输出,需按如下方式遍历:");int[] ints1 = (int[]) intList.get(0);for(int i : ints1){System.out.print(i + " ");}System.out.println();//4、更新数组或List时,另一个将自动更新System.out.print("4、更新数组或List时,另一个将自动更新: ");integerList.set(0, 5);for(Object o : integerList){System.out.print(o + " ");}for(Object o : integers){System.out.print (o + " ");}System.out.println();//5、add() remove() 将报错System.out.print("5、add() remove() 将报错: ");
// integerList.remove(0);
// integerList.add(3, 4);
// integerList.clear();}
输出:
二、对比总结
list | 特点 | 适用场景 |
---|---|---|
ArrayList | 基于数组实现,支持动态扩容,随机访问元素效率高。 | 需要频繁随机访问元素,对插入和删除操作要求不是特别高的场景。 |
LinkedList | 基于双向链表实现,插入和删除元素效率高,但随机访问元素效率相对较低。 | 需要频繁插入和删除元素,而对随机访问元素要求不高的场景。 |
CopyOnWriteArrayList | 线程安全,使用写时复制的机制实现。 | 多线程环境下需要频繁遍历而很少修改List的场景。 |
Arrays.asList() | 将数组转换为List。 | 需要将数组转换为List的场景。 |
参考链接:
Java LinkedList(链表)
CopyOnWriteArrayList详解及使用
Arrays.asList() 详解