Java 集合(2)List
1、List接口
Collection下有两大重要接口List
和Set
集合。
List集合是有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置
进行精确地控制。用户可以根据元素的整数索引
(在列表中的位置)访问元素,并搜索列表中的元素。与 set 不同,list列表通常允许重复的元素
。
总结:
List
:有序的
,带索引的
,通过索引就可以精确的操作集合中的元素,元素是可以重复的。
List提供了增删改查动作
- 增加add(element) add(index,element) ;
- 删除remove(element) remove(index);
- 修改set(index,element);
- 查询get(index);
List list = new ArrayList();
//1,添加元素。
list.add(new Student("wangcai1",21));
list.add(new Student("wangcai2",22));
list.add(new Student("wangcai3",23));
//2,插入元素。
list.add(1, new Student("xiaoqiang",25));
//3,删除元素。
list.remove(2);//IndexOutOfBoundsException
//4,修改元素。
list.set(1, new Student("xiaoming",11));
for (Iterator it = list.iterator(); it.hasNext();) {
Student stu = (Student) it.next();
System.out.println(stu);
}
由于List集合拥有索引,因此List集合迭代方式除了使用迭代器之外,还可以使用索引进行迭代。
for (int i = 0; i < list.size(); i++) {
Student stu = (Student) list.get(i);
System.out.println(stu);
}
1.1、ListIterator介绍
List集合迭代元素中,对元素进行判断,一旦条件满足就添加一个新元素。
public class LinkedListIteratorDemo {
//在list集合迭代元素中,对元素进行判断,一旦条件满足就添加一个新元素
public static void main(String[] args) {
//创建List容器
List list = new ArrayList();
//给容器中添加元素
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
//遍历容器,当有元素为"abc2"时,将其修改为"itcast"
Iterator it = list.iterator();
while(it.hasNext()){
Object obj = it.next();
//判断取出的元素是否是"abc2",是就添加一个新元素
if("abc2".equals(obj)){
list.add("itcast");
}
}
//打印容器中的元素
System.out.println(list);
}
}
运行上述代码发生了异常 java.util.ConcurrentModificationException
在迭代过程中,使用了集合的方法对元素进行操作。导致迭代器并不知道集合中的变化,容易引发数据的不确定性
。
解决:
在迭代时,不要使用集合的方法操作元素。使用迭代器的方法操作。但是迭代器Iterator的方式只有 hasNext()
,next()
,remove()
;Iterator有一个子接口ListIterator
可以完成该问题的解决。通过List接口中的listIterator()就可以获取。
public class LinkedListIteratorDemo {
//在list集合迭代元素中,对元素进行判断,一旦条件满足就添加一个新元素
public static void main(String[] args) {
//创建List容器
List list = new ArrayList();
//给容器中添加元素
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
//遍历容器,当有元素为"abc2"时,将其修改为"itcast"
ListIterator it = list.listIterator();
while(it.hasNext()){
Object obj = it.next();
if("abc2".equals(obj)){
it.add("itcast");
}
}
//打印容器中的元素
System.out.println(list);
}
}
注意:该列表迭代器只有List接口有。而且这个迭代器可以完成在迭代过程中的增删改查动作。
1.2、List常用子类介绍
List接口有多个子类,这里我们介绍几个最常用的集合,其他的集合不是很常用,大家如果有用到可以查阅相关API,集合用法差别不是特别大。首先我们来学习List下的常用集合ArrayList
、Vector
、LinkedList
集合。
ArrayList:是数组结构,长度是可变的(原理是创建新数组+复制数组),查询速度很快,增删较慢,不同步的。
Vector:可以增长的数组结构。同步的。效率非常低。已被ArrayList替代。
LinkedList:是链表结构,不同步的,增删速度很快,查询速度较慢。
1.3、LinkedList的特有方法
LinkedList 类还为在列表的开头及结尾 get
、remove
和 insert
元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
就是可以使用LinkedList集合可以实现堆栈,队列。
堆栈:先进后出 First in Last Out FILO
队列:先进先出 First in First Out FIFO
LinkedList是List的子类,List中的方法LinkedList都是可以使用,这里就不做详细介绍,那么我们只需要了解LinkedList的特有方法即可。
LinkedList中的方法围绕头和尾展开定义的。First Last。
addFirst();给头部添加元素
addLast();给末尾添加元素
getFirst();:获取头部元素。
getLast();获取末尾元素
removeFirst();获取头部元素,并删除头部元素。
removeLast();获取末尾元素,并删除末尾元素。
LinkedList link = new LinkedList();
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
System.out.println(link.getFirst());
System.out.println(link.getLast());
System.out.println(link.removeFirst());
System.out.println(link.removeLast());
while(!link.isEmpty()){
System.out.println(link.removeLast());
}
1.4、LinkedList模拟队列
面试题:用LinkedList模拟一个堆栈或者队列数据结构。
public class LinkedListTest {
public static void main(String[] args) {
//创建一个堆栈或者队列数据结构对象,该对象中使用LinkedList来完成的。
//创建一个队列对象。
Queue queue = new Queue();
//往队列中添加元素。
queue.myAdd("itcast1");
queue.myAdd("itcast2");
queue.myAdd("itcast3");
queue.myAdd("itcast4");
while(!queue.isNull()){
System.out.println(queue.myGet());
}
}
}
/**
* 定义一个队列数据结构。Queue
*/
class Queue{
//封装了一个链表数据结构。
private LinkedList link;
/*
* 队列初始化时,对链表对象初始化。
*/
Queue(){
link = new LinkedList();
}
/**
* 队列的添加元素功能。
*/
public void myAdd(Object obj){
//内部使用的就是链表的方法。
link.addFirst(obj);
}
/**
* 队列的获取方法。
*/
public Object myGet(){
return link.removeLast();
}
/**
* 判断队列中元素是否空,没有元素就为true。
*/
public boolean isNull(){
return link.isEmpty();
}
}
1.5、去除List中的重复元素
案例:去除List集合中的重复元素。
思路:
- 先创建一个临时容器。用于
存储唯一性
的元素。 - 遍历原容器,将遍历到的元素到
临时容器
中去判断,是否存在。 - 如果存在,
不存储
到临时容器,如果不存在,存储
到临时容器中。 - 遍历结束后,临时容器中存储的就是唯一性的元素。
- 如果需要将这些唯一性的元素保留到原容器中,只要将
原容器清空
,将临时容器中的元素添加到原容器中即可。
public class ArrayListTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("abc1");
list.add("abc2");
list.add("abc1");
list.add("abc2");
list.add("abc1");
list.add("abc2");
getSingleElement(list);//去除重复元素。
System.out.println(list);
}
public static void getSingleElement(List list){
//1,创建一个临时容器。
List temp = new ArrayList();
//2,遍历原容器。
for (Iterator it = list.iterator(); it.hasNext();) {
Object obj = it.next();
//对遍历到的每一个元素都到临时容器中去判断是否包含。
if(!temp.contains(obj)){//如果不存在,
temp.add(obj);//添加到临时容器。
}
}
//唯一性的元素已经被记录到临时容器中。
//清空原容器中的元素。
list.lear();
//把临时容器中的元素添加到原容器中。
list.addAll(temp);
}
}