- 在集合类中,
List是最基础的一种集合:它是一种有序列表。List的行为和数组几乎完全相同,在添加和删除元素的时候,会非常不方便。因此,在实际应用中,需要增删元素的有序列表,我们使用最多的是ArrayList。实际上,ArrayList在内部使用了数组来存储所有元素。 ArrayList把添加和删除的操作封装起来,让我们操作List类似于操作数组,却不用关心内部元素如何移动。- 我们考察
List<E>接口,可以看到几个主要的接口方法:
- 在末尾添加一个元素:
boolean add(E e) - 在指定索引添加一个元素:
boolean add(int index, E e) - 删除指定索引的元素:
int remove(int index) - 删除某个元素:
int remove(Object e) - 获取指定索引的元素:
E get(int index) - 获取链表大小(包含元素的个数):
int size()
实现
List接口并非只能通过数组(即ArrayList的实现方式)来实现,另一种LinkedList通过“链表”也实现了List接口。在LinkedList中,它的内部每个元素都指向下一个元素:
我们来比较一下
ArrayList和LinkedList: | | ArrayList | LinkedList | | :—- | :—- | :—- | | 获取指定元素 | 速度很快 | 需要从头开始查找元素 | | 添加元素到末尾 | 速度很快 | 速度很快 | | 在指定位置添加/删除 | 需要移动元素 | 不需要移动元素 | | 内存占用 | 少 | 较大 |
通常情况下,我们总是优先使用ArrayList。
- List的特点
- 允许添加重复的元素
- 允许添加null
public class ListTest {public static void main(String[] args) {List<String> list=new ArrayList<>();list.add("apple");//size=1list.add("pear"); //size=2list.add("apple"); //size=3list.add(null); //size=4System.out.println(list.size());System.out.println(list);}}
- 创建LIst的方法
- 使用
ArrayList和LinkedList - 通过
List接口提供的of()方法(JDK9新特性)List<Integer> list = List.of(1, 2, 5);//但是List.of()方法不接受null值,如果传入null,会抛出NullPointerException异常。
- 遍历List的方法
for循环+索引
public class Main {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("apple");//size=1list.add("pear"); //size=2list.add("banana"); //size=3for (int i = 0; i < list.size(); i++) {String s = list.get(i);System.out.println(s);}}}
但这种方式并不推荐,一是代码复杂,二是因为
get(int)方法只有ArrayList的实现是高效的,换成LinkedList后,索引越大,访问速度越慢。使用迭代器
Iterator来访问List
Iterator对象有两个方法:boolean hasNext()判断是否有下一个元素,E next()返回下一个元素。
public class Main {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("apple");//size=1list.add("pear"); //size=2list.add("banana"); //size=3for (Iterator<String> it = list.iterator(); it.hasNext(); ) {String s = it.next();System.out.println(s);}}}
由于Iterator遍历是如此常用,所以,Java的for each循环本身就可以帮我们使用Iterator遍历。
for (String s : list) {System.out.println(s);}
List和Array的转换
List—>Array
调用
toArray()方法直接返回一个Object[]数组,这种方法会丢失类型信息,所以实际应用很少。Object[] array=list.toArray();for (Object s:array){System.out.println(s);}
ii. 给
toArray(T[])传入一个类型相同的Array,List内部自动把元素复制到传入的Array中。public class Main {public static void main(String[] args) {List<Integer> list = List.of(12, 34, 56);Integer[] array = list.toArray(new Integer[3]);for (Integer n : array) {System.out.println(n);}}}
注意:如果传入的数组不够大,那么
List内部会创建一个新的刚好够大的数组,填充后返回;如果传入的数组比List元素还要多,那么填充完元素后,剩下的数组元素一律填充null。
b. Array—>List通过
List.of(T...)方法(JDK9)- 对于JDK 11之前的版本,可以使用
Arrays.asList(T...)方法把数组转换成List
注意,如果我们调用Integer[] array1 = { 1, 2, 3 };List<Integer> list2 = Arrays.asList(array);System.out.println(list2);
List.of(),它返回的是一个只读List,对只读List调用add()、remove()方法会抛出UnsupportedOperationException。
