集合之List集合
List系列集合的特点:有序、可重复、有索引
- 有序:存储和取出的元素顺序一致
- 有索引:可以通过索引操作元素
- 可重复:存储的元素可以重复
List集合常用API
// 创建一个ArrayList集合对象
List<String> list = new ArrayList<>();
list.add("java");
list.add("php");
list.add("go");
//1.在某个索引位置插入元素
//public void add(int index, E element);
list.add(0,"vue"); //数组变为 [VUE, Java, php, go]
//2.根据索引删除元素,返回被删除的元素值
//public E remove(int index);
String remove = list.remove(0); //remove = VUE
//3.根据索引获取元素
//public E get(int index);
String s = list.get(1); // s = php
//4.修改指定索引处的元素,并返回被修改的元素值
//public E set(int index, E element);
String s1 = list.set(0, "Java"); //s1 = java
System.out.println(list); //输出结果为 [Java, php, go]
List集合的迭代方法
在学习Collection集合接口的时候,我们已经总结过该体系下集合的遍历。通用情况下可以使用迭代器和增强for循环。由于List集合是有索引的,所以List集合还可以通过for循环,使用索引进行遍历
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
ArrayList的特点
- ArrayList集合的底层是基于数组而实现的,特点是可以根据索引直接进行查询。所以查询快,但是增删需要做元素的移位操作,所以速度慢
- 第一次创建集合时并添加第一个元素的时候,底层会默认创建一个长度为10的数组
- 如果添加元素导致集合容量被填满,集合则会进行自动扩容。扩容的大小是原有容量的1.5倍
Linkedlist的特点
- LinkedList集合的底层是基于双链表实现的,特点是查询速度慢,但是增删首尾元素非常快。
- 由于LinkedList操作首尾数据特别快,所以提供了 addFirst( ),addLast( ),getFirst( ),getLast( ),removeFirst( ),removeLast( )等操作首尾数据的方法
//LinkedList可以模拟实现队列结构和栈结构
//栈 先进后出
LinkedList<String> stack = new LinkedList<>();
//入栈 1--2--3--4--5
stack.addFirst("1");
stack.addFirst("2");
stack.addFirst("3");
stack.addFirst("4");
stack.addFirst("5");
//出栈 5--4--3--2--1
System.out.println(stack.removeFirst()); // 5
System.out.println(stack.removeFirst()); // 4
System.out.println(stack.removeFirst()); // 3
System.out.println(stack.removeFirst()); // 2
System.out.println(stack.removeFirst()); // 1
//队列 先进先出
//入队
stack.addLast("1");
stack.addLast("2");
stack.addLast("3");
stack.addLast("4");
stack.addLast("5");
//出队
System.out.println(stack.removeFirst()); // 1
System.out.println(stack.removeFirst()); // 2
System.out.println(stack.removeFirst()); // 3
System.out.println(stack.removeFirst()); // 4
System.out.println(stack.removeFirst()); // 5
从集合中找出某个元素并删除的时候可能会出现并发修改异常的问题
解决方法:
- 使用迭代器遍历,并使用迭代器自己的删除方法进行操作
//从集合中遍历元素,并删除符合条件的元素时,应该从集合后面往前进行遍历,可以避免漏掉元素
//将整型集合[121,99,78,88]中小于100的元素进行删除
ArrayList<Integer> lists = new ArrayList<>();
lists.add(121);
lists.add(99);
lists.add(78);
lists.add(88);
Iterator<Integer> iterator = lists.iterator();
while (iterator.hasNext()) {
if (iterator.next() < 100) {
iterator.remove(); //使用迭代器自带的删除方法,而不是使用集合的删除方法
}
}
- 使用for循环遍历并删除元素
//从集合中遍历元素,并删除符合条件的元素时,应该从集合后面往前进行遍历,可以避免漏掉元素
//将整型集合[121,99,78,88]中小于100的元素进行删除
ArrayList<Integer> lists = new ArrayList<>();
lists.add(121);
lists.add(99);
lists.add(78);
lists.add(88);
for (int i = 0; i < lists.size(); i++) {
if(lists.get(i)<100){
lists.remove(i);
}
}
System.out.println(lists); //输出结果 [121, 78]
/*
我们可以发现,输出的结果中有元素不符合要求,但是同样没有被删除
遍历集合的过程如下:
i = 0 lists.size() = 4 ,lists.get(0)=121> 100 保留, i++ lists:[121,99,78,88]
i = 1 lists.size() = 4 ,lists.get(1)=99 < 100 删除, i++ lists:[121,78,88]
i = 2 lists.size() = 3 ,lists.get(2)=88 < 100 删除, i++ lists:[121,78]
此时,i = 3 > lists.size(),则跳出了循环。
但是78并没有被正确删除,这是由于在删除的过程中,集合的大小是动态变化的,索引值却在正常的递增。
这就回导致一部分符合条件的元素,也无法被删除
解决这个问题,可以通过从集合后面往前进行遍历
*/
for (int i = lists.size()-1; i >=0;i--) {
if(lists.get(i)<100){
lists.remove(i);
}
}
//或者在从前往后的遍历过程中,如果删除了元素,则将i的值先进行减一。两种方法均可以解决这个问题
for (int i = 0; i < lists.size();i++) {
if(lists.get(i)<100){
lists.remove(i);
i--;
}
}
System.out.println(lists); //输出结果 [121]
本文系作者 @Stone 原创发布在 zlprime。未经许可,禁止转载。