另外只要是实现了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
import java.util.List;
public class Demo03 {
public static void main(String[] args) {
List
// 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
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
for (Integer val : values) {
System.out.println("方式一,value="+val);
//该集合是一种只读的集合,不能在遍历时进行增删改等更新操作,只能进行读取操作,
//否则会产生java.lang.UnsupportedOperationException异常
//values.remove(0);
}
// 数组转List的方式二:Arrays.asList()返回一个只读的集合,不能进行add/remove等修改操作。
List
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接口。其底层是一个可以动态修改的数组,该数组与普通数组的区别,在于它没有固定的大小限制,我们可以对其动态地进行元素的添加或删除
存储在集合内的数据被称为”元素“,我们可以利用索引来访问集合中的每个元素。为了方便我们操作这些元素,ArrayList给我们提供了相关的添加、删除、修改、遍历等功能。
因为ArrayList的底层是一个动态数组,所以该集合适合对元素进行快速的随机访问(遍历查询),另外尾部成员的增加和删除操作速度也较快,但是其他位置上元素的插入与删除速度相对较慢。基于这种特性,所以ArrayList具有查询快,增删慢的特点。
2. 常用方法
ArrayList给我们提供了如下这些方法,我们可以先来了解一下:
方法描述add()将数据元素插入到ArrayList的指定位置上addAll()将一个新集合中的所有元素添加到ArrayList中clear()删除ArrayList中所有的元素contains()判断元素是否在ArrayList中get()通过索引值获取ArrayList中的元素indexOf()返回ArrayList中某个元素的索引值removeAll()删除ArrayList中指定集合的所有元素remove()删除ArrayList里的单个元素size()返回ArrayList的元素数量isEmpty()判断ArrayList是否为空subList()截取ArrayList的部分元素set()替换ArrayList中指定索引的元素sort()对ArrayList的数据元素进行排序toArray()将ArrayList转换为数组toString()将ArrayList转换为字符串ensureCapacity()设置指定容量大小的ArrayListlastIndexOf()返回指定元素在ArrayList中最后一次出现的位置retainAll()保留指定集合中的数据元素containsAll()查看ArrayList是否包含了指定集合的所有元素trimToSize()将ArrayList的容量调整为数组的元素个数removeRange()删除ArrayList中指定索引间存在的元素replaceAll()用给定的数据元素替换掉指定数组中每个元素removeIf()删除所有满足特定条件的ArrayList元素forEach()遍历ArrayList中每个元素并执行特定操作
接下来我们就挑选几个常用的方法,通过几个案例来给大家讲解一下ArrayList的用法。
3. 添加元素
ArrayList给我们提供了多个与添加相关的方法,比如add()和addAll()方法,可以将元素添加到集合中。另外如果我们要计算ArrayList中元素的数量,可以使用size()方法。
import java.util.ArrayList;
public class Demo05 {
public static void main(String[] args) {
//创建ArrayList集合,
ArrayList
//一个一个地添加元素
names.add("一一哥");
names.add("java");
names.add("数学");
//遍历集合
for (String name : names) {
System.out.println("name="+name+",size="+names.size());
}
ArrayList
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集合,
ArrayList
//一个一个地添加元素
names.add("一一哥");
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集合,
ArrayList
//一个一个地添加元素
names.add("一一哥");
names.add("java");
names.add("数学");
//删除集合中指定位置上的某个元素
names.remove(0);
//删除集合中的某个指定元素
names.remove("java");
//遍历集合
for (String name : names) {
System.out.println("name="+name);
}
ArrayList
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
//一个一个地添加元素
nums.add(100);
nums.add(85);
nums.add(120);
nums.add(55);
//对集合进行排序,默认是升序排列
Collections.sort(nums);
//遍历集合
for (Integer num : nums) {
System.out.println("num="+num);
}
}
}
8. 配套视频
本节内容配套视频链接如下:戳链接即可查看
三. LinkedList集合
1. 简介
LinkedList采用链表结构来保存数据,所以是一种链表集合,类似于ArrayList,也是List的一个子类,位于java.util包中。它的底层是基于线性链表这种常见的数据结构,但并没有按线性的顺序存储数据,而是在每个节点中都存储了下一个节点的地址。
LinkedList的优点是便于向集合中插入或删除元素,尤其是需要频繁地向集合中插入和删除元素时,使用LinkedList类比ArrayList的效率更高。但LinkedList随机访问元素的速度则相对较慢,即检索集合中特定索引位置上的元素速度较慢。
2. LinkedList类关系
LinkedList直接继承自AbstractSequentialList,并实现了List、Deque、Cloneable、Serializable等多个接口。通过实现List接口,具备了列表操作的能力;通过实现Cloneable接口,具备了克隆的能力;通过实现Queue和Deque接口,可以作为队列使用;通过实现Serializable接口,可以具备序列化能力。LinkedList类结构关系如下图所示:
3. LinkedList与ArrayList对比
与ArrayList相比,LinkedList进行添加和删除的操作效率更高,但查找和修改的操作效率较低。基于这种特性,我们可以在以下情况中使用ArrayList:
需要经常访问获取列表中的某个元素;只需要在列表的 末尾 进行添加和删除某个元素。
当遇到如下情况时,可以考虑使用LinkedList:
需要经常通过 循环迭代来访问 列表中的某些元素;需要经常在列表的 开头、中间、末尾 等位置进行元素的添加和删除操作。
4. 常用方法
LinkedList中的很多方法其实都来自于List接口,所以它的很多方法与ArrayList是一样的。但由于其自身特点,也具有一些特有的常用方法,这里只列出LinkedList特有的常用方法,如下表所示:
方法描述public void addFirst(E e)将元素添加到集合的头部。public void addLast(E e)将元素添加到集合的尾部。public boolean offer(E e)向链表的末尾添加元素,成功为true,失败为false。public boolean offerFirst(E e)在链表头部插入元素,成功为true,失败为false。public boolean offerLast(E e)在链表尾部插入元素,成功为true,失败为false。public void clear()清空链表。public E removeFirst()删除并返回链表的第一个元素。public E removeLast()删除并返回链表的最后一个元素。public boolean remove(Object o)删除某一元素,成功为true,失败为false。public E remove(int index)删除指定位置的元素。public E poll()删除并返回第一个元素。public E remove()删除并返回第一个元素。public E getFirst()返回第一个元素。public E getLast()返回最后一个元素。public int lastIndexOf(Object o)查找指定元素最后一次出现的索引。public E peek()返回第一个元素。public E element()返回第一个元素。public E peekFirst()返回头部元素。public E peekLast()返回尾部元素。public Iterator descendingIterator()返回倒序迭代器。public ListIterator listIterator(int index)返回从指定位置开始到末尾的迭代器。
对这些方法进行基本的了解之后,接下来我们选择几个核心方法来来看看具体该怎么使用。
5. 添加/删除元素
我们可以通过addFirst()和addLast()方法,分别在链表的开头和结尾添加一个元素。当我们要频繁地在一个列表的开头和结尾进行元素添加、删除时,使用````LinkedList要比ArrayList```的效率更高。
import java.util.LinkedList;
public class Demo09 {
public static void main(String[] args) {
// 创建LinkedList集合
LinkedList
// 一个一个地添加元素
names.add("一一哥");
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
// 一个一个地添加元素
names.add("一一哥");
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);
}
}
}
7. 配套视频
本节内容配套视频链接如下:戳链接直达视频教程