《Java核心技术 卷I》链表
链表
ArrayList底层是数组,增删慢。
集合框架中的类
从数组中删除一个元素
链表(linked list)解决这个问题,在Java程序中所有链表实际上是双向链接(doubly linked),每个链接存放前面的引用。
删除元素很容易,将前后引用对象指向另一个就可以了。
小练习,增加5个元素,然后将第2个元素删除
package collection;
import java.util.Iterator;
import java.util.LinkedList;
public class LinkedListTest {
public static void main(String[] args) {
var staff = new LinkedList<String>();
staff.add("Amy");
staff.add("Bob");
staff.add("Carl");
staff.add("Dog");
staff.add("Egg");
Iterator<String> iter = staff.iterator();
String f = iter.next();
String s = iter.next();
System.out.println(f);
iter.remove();
iter = staff.iterator();
iter.forEachRemaining((e)->{
System.out.println(e);
});
}
}
结果:Amy Amy Carl Dog Egg
Iterator接口中没有add方法,提供子接口ListIterator包含add方法,返回值为void,假定add操作总是能增加元素。
ListIterator接口有两个方法,E previous()和hasPrevious()用来反向遍历链表。
LinkedList返回了一个ListIterator接口的迭代器对象。
小案例
package collection;
import java.util.LinkedList;
import java.util.ListIterator;
public class LinkedListListIteratorTest {
public static void main(String[] args) {
var staff = new LinkedList<String>();
staff.add("Amy");
staff.add("Bob");
staff.add("Carl");
staff.add("Dog");
staff.add("Egg");
ListIterator<String> iter = staff.listIterator();
iter.next();//略过第一个元素
iter.add("Juliet");
iter = staff.listIterator();
iter.forEachRemaining((e)->{
System.out.print(e+" ");
});
}
}
//结果:Amy Juliet Bob Carl Dog Egg
不略过任何元素,则当前元素插入后为表头,若迭代器越过链表最后一个元素(hasNext返回false),插入的元素称为列表的新表尾。
链表有n个元素,会有n+1个位置可以添加新元素。
ABC三个元素就有4个位置,|ABC A|BC AB|C ABC|
set方法用新元素替换调用next和previous方法返回上一个元素。
某个迭代器修改集合,另一个迭代器访问,会出错,抛出ConcurrentModificationException异常。
package collection;
import java.util.LinkedList;
import java.util.ListIterator;
public class LinkedListListIteratorTest {
public static void main(String[] args) {
var staff = new LinkedList<String>();
staff.add("Amy");
staff.add("Bob");
staff.add("Carl");
staff.add("Dog");
staff.add("Egg");
ListIterator<String> iter1 = staff.listIterator();
ListIterator<String> iter2 = staff.listIterator();
iter1.next();
iter1.remove();
iter2.next();
}
}
//Exception in thread "main" java.util.ConcurrentModificationException
LinkedList类提供了get方法反问特定元素,效率并不高。
注释:get方法做了一个微小的优化,如果索引大于size()/2,就从列表尾端搜索元素。
列表迭代器还有一个方法是告诉你当前位置的索引,有两个索引,nextIndex和previousIndex。
list.listIterator(n)将返回一个迭代器指向n的元素前面的位置,效率高。
java.util.List 1.2
- ListIterator listIterator(),返回一个列表迭代器,用来访问列表中的元素。
- ListIterator listIterator(int index),返回一个列表迭代器,访问列表中给定索引的元素。
- void(int i,E element),在给定位置添加一个元素。
- void addAll(int i,Collection elements),将集合中的所有元素添加到给定位置。
- E remove(int i),删除并返回给定位置的元素。
- E get(int i),获取给定位置的元素。
- E set(int i,E element),用一个新元素替换给定位置的元素,并返回原来那个元素。
- int indexOf(Object element),返回与指定元素相等的元素在列表中第一次出现的位置,如果没有这样的元素则返回-1。
- int lastIndexOf(Object element),返回与指定元素相等的元素在列表中最后一次出现的位置,如果没有这样的元素将返回-1。
java.util.ListIterator 1.2
- void add(E newElement),在当前位置前添加一个元素。
- void set(E newElement),用新元素替换next或previous访问的上一个元素。
- boolean hasPrevious(),当反向迭代列表时,如果还有可以访问的元素,返回true。
- E previous(),返回前一个对象,如果已经到达了列表的头部,就抛出NoSuchElementException异常。
- int nextIndex(),返回下一次调用next方法时将返回的元素的索引。
- int previousIndex(),返回下一次调用previous方法时将返回的元素的索引。
java.util.LinkedList 1.2
- LinkedList(),构造一个空链表
- LinkedList(Collection elements),构造一个链表,并将集合中所有的元素添加到这个链表中。
- void addFirst(E element)
- void addLast(E element),将某元素添加到列表的头部或尾部。
- E getFirst()
- E getLast(),返回列表头部或尾部的元素。
- E removeFirst()
- E removeLast(),删除并返回列表头部或尾部的元素。