千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > List集合有哪些特性?

List集合有哪些特性?

来源:千锋教育
发布人:zyh
时间: 2023-06-12 16:44:00 1686559440

  全文大约【5800】字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图视频,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考......

List集合有哪些特性

  一. List集合简介

  1.概述

  List本身是一个接口,该接口继承自Collection接口,它有两个常用的实现子类ArrayList和LinkedList。从功能特性上来看,List是有序、可重复的单列集合,集合中的每个元素都有对应的顺序索引,我们可以通过该索引来访问指定位置上的集合元素。默认情况下,List会按元素的添加顺序给元素设置索引,第一个添加到List集合中的元素索引为0,第二个为1,后面依此类推。所以List的行为和数组几乎完全相同,它们都是有序的存储结构。另外List集合中允许有重复的元素,甚至可以有多个null值。

  但是如果我们是使用数组来添加和删除元素,就会非常的不方便。比如从一个已有的数组{'A', 'B', 'C', 'D', 'E'}中删除索引为2的元素,这个“删除”操作实际上是把'C'后面的元素依次往前挪一个位置;而“添加”操作实际上是把指定位置以后的元素依次向后挪一个位置,腾出位置给新加入的元素。针对这两种操作,使用数组实现起来都会非常麻2. 类关系

  我们来看看List接口的类关系,如下图所示:烦。所以在实际应用中,我们增删元素时,一般都是使用有序列表(如ArrayList),而不是使用数组。

  2.类关系

  我们来看看List接口的类关系,如下图所示:

1684745831000.image

  从这个类关系中我们可以看到,List接口继承了Collection接口,并且有ArrayList、LinkedList、Vector等子类,其中Vector现在已经不太常用了,所以我们重点掌握ArrayList和LinkedList就行。

  3. 常用API方法

  在List接口中定义了子类的一些通用方法,如下所示:

  ● boolean add(E e):在集合末尾添加一个数据元素;

  ● boolean add(int index, E e):在集合的指定索引出添加一个数据元素;

  ● E remove(int index):删除集合中指定索引的元素;

  ● boolean remove(Object e):删除集合中的某个元素;

  ● E get(int index):获取集合中指定索引出的元素;

  ● int size():获取集合的大小(包含元素的个数)。

  以上这些方法,就是我们在开发时比较常用的几个方法,大家需要记住哦。

  4. List对象创建方式

  List作为一个接口,我们通常不能直接new List来创建其对象,在Java中给我们提供了如下两种创建List对象的方式:

  ● 通过多态方式创建:new List的某个子类,比如new ArrayList()等;

  ● 通过List.of()方法创建:of()方法可以根据给定的数据元素快速创建出List对象,但该方法不接受null值,如果传入null会抛出NullPointerException异常。  

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Demo01 {
public static void main(String[] args) {
//创建List对象方式一:
List<String> list1=new ArrayList<>();

List<String> list2=new LinkedList<>();

//创建List对象方式二:
List<Integer> list3 = List.of(1,3,5,7,9);

//该方式不能传入null参数,否则会产生NullPointerException异常
//List<Integer> list4 = List.of(1,3,5,7,9,null);
}
}

  5.List集合遍历方式

  很多时候,我们都会对集合进行遍历操作,也就是要把集合中的每个元素挨个的取出来,以下是几种常用的集合遍历方式:

  ● 普通for循环配合get(索引值)方法进行遍历:这种遍历方式实现起来代码较为复杂,且get(int)取值方法只对ArrayList比较高效,但对LinkedList效率较低,索引越大时访问速度越慢。

  ● 增强for循环进行遍历:我们也可以使用增强for循环进行遍历,该方式比普通for循环实现起来更为简洁。

  ● 使用Iterator迭代器进行集合遍历:不同的List对象调用iterator()方法时,会返回不同实现的Iterator对象,该Iterator对象对集合总是具有最高的访问效率。  

import java.util.Iterator;
import java.util.List;

public class Demo02 {
public static void main(String[] args) {
//List遍历方式一,普通for循环:
List<String> list = List.of("java", "大数据", "壹小编");
for(int i=0;i<list.size();i++) {
System.out.println("遍历方式一,值="+list.get(i));
}

//List遍历方式二,迭代器:
Iterator<String> it = list.iterator();
while(it.hasNext()){
//取出下一个值
String value = it.next();
System.out.println("遍历方式二,值="+value);
}

//List遍历方式三,增强for循环:内部会自动使用Iterator
for(String item:list) {
System.out.println("遍历方式三,item="+item);
}
}
}

  上面提到的Iterator对象,有两个常用方法,如下所示:

  ● boolean hasNext():该方法用于判断集合中是否还有下一个元素;

  ● E next():该方法用于返回集合的下一个元素。

  虽然使用Iterator遍历List集合的代码,看起来比使用索引较复杂,但Iterator遍历List集合的效率却是最高效的方式。

  另外只要是实现了Iterable接口的集合类,我们都可以直接使用for each增强循环来遍历。在增强for循环中,Java编译器会自动把for each循环变成基于Iterator方式的遍历方式。

  6. List与数组的转换方式

  其实List与Array数组在很多地方都是比较相似的,比如都可以根据索引对数据元素进行遍历取值等操作。因为存在着这种相似之处,所以在List和数组之间是可以互相转换的,即List集合可以转成数组,数组也可以转成List集合。

  6.1 List转数组

  一般情况下,List转数组有如下几种方式:

  ● toArray()方法:该方法会返回一个Object[]数组,但该方法会丢失类型信息,在实际开发时较少使用;

  ● toArray(T[])方法:传入一个与集合的数据元素类型相同的Array,List会自动把元素复制到传入的Array中;

  ● T[] toArray(IntFunction generator)方法:函数式写法,这是Java中的新特性,后面小编会单独讲解。 

import java.util.List;

public class Demo03 {
public static void main(String[] args) {
List<String> list = List.of("java", "大数据", "壹小编");

// List转数组方式一:返回一个Object[]数组
Object[] array = list.toArray();
for (Object val : array) {
System.out.println("方式一,value="+val);
}

// List转数组方式二,给toArray(T[])传入与数组元素类型相同的Array,如果数组类型与集合数据元素类型不匹配则会产生如下异常:
// java.lang.ArrayStoreException: arraycopy: element type mismatch:
//can not cast one of the elements of java.lang.Object[] to the type of the destination array, java.lang.Integer
String[] array2 = list.toArray(new String[list.size()]);
for (String val : array2) {
System.out.println("方式二,value="+val);
}

// List转数组方式三:返回一个String[]数组
String[] array3 = list.toArray(String[]::new);
for (String val : array3) {
System.out.println("方式二,value="+val);
}
}
}

  在本案例中,第一种实现方式是调用toArray()方法直接返回一个Object[]数组,但这种方法会丢失类型信息,所以开发是很少使用。

  第二种方式要给toArray(T[])方法传入一个与集合数据元素类型相同的Array,List内部会自动把元素复制到传入的Array数组中。如果Array类型与集合的数据元素类型不匹配,就会产生”java.lang.ArrayStoreException: arraycopy: element type mismatch: can not cast one of the elements of java.lang.Object[] to the type of the destination array......“异常。

  第三种方式是通过List接口定义的T[] toArray(IntFunction generator)方法,这是一种函数式写法,小编以后再单独给大家讲解。

  6.2 数组转List

  反过来,数组也可以转为List集合,一般的方式如下:

  ● List.of(T...)方法:该方法会返回一个只读的List集合,如果我们对只读List调用add()、remove()方法会抛出UnsupportedOperationException异常。其中的T是泛型参数,代表要转成List集合的数组;

  ● Arrays.asList(T...)方法:该方法也会返回一个List集合,但它返回的List不一定就是ArrayList或者LinkedList,因为List只是一个接口。 

import java.util.Arrays;
import java.util.List;

public class Demo04 {
public static void main(String[] args) {
// 数组转List的方式一:List.of()返回一个只读的集合,不能进行add/remove等修改操作。
List<Integer> values = List.of(1,8,222,10,5);
for (Integer val : values) {
System.out.println("方式一,value="+val);

//该集合是一种只读的集合,不能在遍历时进行增删改等更新操作,只能进行读取操作,
//否则会产生java.lang.UnsupportedOperationException异常
//values.remove(0);
}

// 数组转List的方式二:Arrays.asList()返回一个只读的集合,不能进行add/remove等修改操作。
List<String> items = Arrays.asList("java","壹小编","元宇宙");
for (String item : items) {
System.out.println("方式二,value="+item);

//不可以进行增删改操作
//items.add("sss");
//items.remove(0);
}
}
}

  在本案例中,无论我们是通过List.of()方法,还是通过Arrays.asList()方法,都只会返回一个只读的集合。这种集合在遍历时不能进行增删改等更新操作,只能进行读取操作,否则会产生java.lang.UnsupportedOperationException异常。

  二. ArrayList集合

  1.简介

  ArrayList是一个数组队列,位于java.util包中,它继承自AbstractList,并实现了List接口。其底层是一个可以动态修改的数组,该数组与普通数组的区别,在于它没有固定的大小限制,我们可以对其动态地进行元素的添加或删除。

1684746655246.image

  存储在集合内的数据被称为”元素“,我们可以利用索引来访问集合中的每个元素。为了方便我们操作这些元素,ArrayList给我们提供了相关的添加、删除、修改、遍历等功能。

  因为ArrayList的底层是一个动态数组,所以该集合适合对元素进行快速的随机访问(遍历查询),另外尾部成员的增加和删除操作速度也较快,但是其他位置上元素的插入与删除速度相对较慢。基于这种特性,所以ArrayList具有查询快,增删慢的特点。

  2.常用方法

  ArrayList给我们提供了如下这些方法,我们可以先来了解一下:

1684746916697.image

  接下来小编就挑选几个常用的方法,通过几个案例来给大家讲解一下ArrayList的用法。

  3.添加元素

  ArrayList给我们提供了多个与添加相关的方法,比如add()和addAll()方法,可以将元素添加到集合中。另外如果我们要计算ArrayList中元素的数量,可以使用size()方法。 

import java.util.ArrayList;

public class Demo05 {
public static void main(String[] args) {
//创建ArrayList集合,<String>中的是泛型,后面我们会专门讲解泛型
ArrayList<String> names = new ArrayList<String>();
//一个一个地添加元素
names.add("java");
names.add("数学");

//遍历集合
for (String name : names) {
System.out.println("name="+name+",size="+names.size());
}

ArrayList<String> names2 = new ArrayList<String>();
names2.add();
//在A集合中追加B集合
names2.addAll(names);

//遍历集合
for (String name : names2) {
System.out.println("name="+name);
}
}
}

  在上面的代码中,这部分是泛型,小编会在后面给大家专门讲解,敬请期待哦。

  4. 遍历元素

  我们对ArrayList中元素进行遍历的方式,其实与List的遍历是一样的,我们可以使用普通for循环、增强for循环、Iterator迭代器等方式对集合进行遍历,这里我们就不再单独展示其用法了。

  5. 修改元素

  我们使用add()方法将元素添加到集合中之后,如果想对集合中的元素进行修改,可以使用set()方法。 

import java.util.ArrayList;

public class Demo06 {
public static void main(String[] args) {
//创建ArrayList集合,<String>中的是泛型,后面我们会专门讲解泛型
ArrayList<String> names = new ArrayList<String>();
//一个一个地添加元素
names.add("java");
names.add("数学");

//修改集合中的元素:第一个参数是集合中的索引,第二个是要修改的值
names.set(1, "Android");
names.set(2, "iOS");

//遍历集合
for (String name : names) {
System.out.println("name="+name);
}
}
}

  6.删除元素

  如果我们要删除ArrayList中的元素,可以使用remove()、removeAll()等方法。 

import java.util.ArrayList;

public class Demo07 {
public static void main(String[] args) {
//创建ArrayList集合,<String>中的是泛型,后面我们会专门讲解泛型
ArrayList<String> names = new ArrayList<String>();
//一个一个地添加元素
names.add("java");
names.add("数学");

//删除集合中指定位置上的某个元素
names.remove(0);
//删除集合中的某个指定元素
names.remove("java");

//遍历集合
for (String name : names) {
System.out.println("name="+name);
}

ArrayList<String> names2 = new ArrayList<String>();
names2.add("语文");
names2.add("英语");
names2.add("数学");
//删除本集合中的另一个集合
names2.removeAll(names);
//遍历集合
for (String name : names2) {
System.out.println("name2="+name);
}
}
}

  7.集合排序

  我们可以使用Collections.sort()方法对集合进行升序排列。 

import java.util.ArrayList;
import java.util.Collections;

public class Demo08 {

public static void main(String[] args) {
//创建ArrayList集合
ArrayList<Integer> nums = new ArrayList<>();
//一个一个地添加元素
nums.add(100);
nums.add(85);
nums.add(120);
nums.add(55);

//对集合进行排序,默认是升序排列
Collections.sort(nums);

//遍历集合
for (Integer num : nums) {
System.out.println("num="+num);
}
}
}

  三. LinkedList集合

  1.简介

  LinkedList采用链表结构来保存数据,所以是一种链表集合,类似于ArrayList,也是List的一个子类,位于java.util包中。它的底层是基于线性链表这种常见的数据结构,但并没有按线性的顺序存储数据,而是在每个节点中都存储了下一个节点的地址。

1684747291514.image

  LinkedList的优点是便于向集合中插入或删除元素,尤其是需要频繁地向集合中插入和删除元素时,使用LinkedList类比ArrayList的效率更高。但LinkedList随机访问元素的速度则相对较慢,即检索集合中特定索引位置上的元素速度较慢。

  2. LinkedList类关系

  LinkedList直接继承自AbstractSequentialList,并实现了List、Deque、Cloneable、Serializable等多个接口。通过实现List接口,具备了列表操作的能力;通过实现Cloneable接口,具备了克隆的能力;通过实现Queue和Deque接口,可以作为队列使用;通过实现Serializable接口,可以具备序列化能力。LinkedList类结构关系如下图所示:

1684747443690.image

  3. LinkedList与ArrayList对比

  与ArrayList相比,LinkedList进行添加和删除的操作效率更高,但查找和修改的操作效率较低。基于这种特性,我们可以在以下情况中使用ArrayList:

  ● 需要经常访问获取列表中的某个元素;

  ● 只需要在列表的末尾进行添加和删除某个元素。

  当遇到如下情况时,可以考虑使用LinkedList:

  ● 需要经常通过循环迭代来访问列表中的某些元素;

  ● 需要经常在列表的开头、中间、末尾等位置进行元素的添加和删除操作。

  4. 常用方法

  LinkedList中的很多方法其实都来自于List接口,所以它的很多方法与ArrayList是一样的。但由于其自身特点,也具有一些特有的常用方法,这里小编只列出LinkedList特有的常用方法,如下表所示:

1684747481458.image

  对这些方法进行基本的了解之后,接下来我们选择几个核心方法来来看看具体该怎么使用。

  5. 添加/删除元素

  我们可以通过addFirst()和addLast()方法,分别在链表的开头和结尾添加一个元素。当我们要频繁地在一个列表的开头和结尾进行元素添加、删除时,使用LinkedList要比ArrayList的效率更高。 

import java.util.LinkedList;

public class Demo09 {

public static void main(String[] args) {
// 创建LinkedList集合
LinkedList<String> names = new LinkedList<String>();
// 一个一个地添加元素
names.add("java");
names.add("数学");

//在链表的开头添加元素
names.addFirst("");

//在链表的结尾添加元素
names.addLast("历史");

// 遍历集合
for (String name : names) {
System.out.println("name=" + name);
}

//移除链表开头的元素
names.removeFirst();
//移除链表结尾的元素
names.removeLast();
}
}

  6.迭代获取元素

  我们可以通过getFirst()、getLast()等方法获取到集合中的第一个、最后一个元素。 

import java.util.LinkedList;

public class Demo10 {
public static void main(String[] args) {
// 创建LinkedList集合
LinkedList<String> names = new LinkedList<String>();
// 一个一个地添加元素
names.add("java");
names.add("数学");

System.out.println("first=" + names.getFirst());
System.out.println("last=" + names.getLast());

// 迭代遍历集合
for (String name : names) {
System.out.println("name=" + name);
}
}
}

  四. 结语

  至此,小编就把List集合给大家讲解完毕了,最后我们再来看看本文的重点吧:

  ● List是按索引顺序访问的、长度可变的有序列表;

  ● 一般开发时,ArrayList比LinkedList的使用更频繁;

  ● List和Array可以相互转换;

  ● 集合遍历时有多种方式,增强for循环和Iterator迭代器的效率更高;

  ● ArrayList与LinkedList都是List接口的实现类,都实现了List中所有未实现的方法,但实现的方式有所不同;

  ● ArrayList底层的数据结构基于动态数组,访问元素速度快于LinkedList,在快速访问数据时ArrayList的执行效率比较高;

  ● LinkedList底层的数据结构基于链表,占用的内存空间较大,但批量插入或删除数据时快于ArrayList。当频繁向集合中插入和删除元素时,使用LinkedList比ArrayList的效率更高。

tags: List集合
声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT