文章目录
List接口的特点:
List接口是Collection集合框架的重要分支:
- 有序的集合,存储元素和取出元素的顺序是一致的;
- 有索引,包含了一些带索引的方法
- 允许存储重复的元素
List接口中特有的带索引的方法:
List接口继承了Collection接口,关于Collection中的常用方法可参考:
Java集合架构常用类与Iterator迭代器
以下是List接口特有的四个方法:
public boolean add(int index ,E element):将元素添加到当前集合的指定的索引位置上。
public E remove(int index):在当前集合的指定索引位置上删除元素。
public E get(int index):获取当前集合指定索引位置上的元素。
public E set(int index,E element):用指定元素替换集合中指定索引位置上的元素。
public static void main(String[] args) {
List<String> list = new ArrayList<>();
System.out.println("===增加元素A,B,C,D==");
list.add("A");
list.add("B");
list.add("C");
list.add("D");
System.out.println(list);
System.out.println("===在索引位置3上增加元素5==");
list.add(3,"E");
System.out.println(list);
System.out.println("===删除索引位置3上的元素==");
list.remove(3);
System.out.println(list);
System.out.println("===通过get(int index)方法遍历list==");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("===在索引位置0上用F替换现在元素==");
list.set(0,"F");
System.out.println(list);
}
输出结果如下:
List接口的实现类ArrayList:
ArrayList类的特点为:查询快,增删慢。关于这个特点我们可以查看一下源码中的增加删除的方法实现:
ArrayList实现类(JDK1.8)中的成员方法public void add(int index, E element) ;*public E remove(int index)*源码
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
我们发现,ArrayList这两个成员方法对在指定索引位置上增加或者删除元素的方法中都进行了数组的复制操作,即利用了System类提供了一个native静态方法arraycopy()实现数组的复制:
该方法是用了native关键字,调用的是JDK中的底层函数。
public static native void arraycopy(Object src,int srcPos,Object dest, int destPos,int length);
- @param src the source array. 源数组
- @param srcPos starting position in the source array. 源数组的起始位置
- @param dest the destination array. 目标数组
- @param destPos starting position in the destination data. 目标数组的起始位置
- @param length the number of array elements to be copied. 复制的长度
List接口的实现类LinkedList:
LinkedList类的特点为:查询慢,增删快:
- 底层是一个链表结构;
- 类中包含了大量操作首尾元素的方法:
–public void addFirst(E e):将指定元素插入列表的开头。
–public void addLast(E e):将指定元素增加到列表的结尾。
–public void push(E e):将指定元素推入列表的栈尾。
–public E getFirst();返回此列表的第一个元素。
–public E getLast():返回此列表的最后一个元素。
–public E removeFirst():移除并返回列表的第一个元素。
–public E removeLast():移除并返回列表的最后一个元素。
–public E pop():弹出列表所表示的栈的一个元素。
–public boolean isEmpty():列表是否为空。
public static void main(String[] args) {
LinkedList<String> linkedList = new LinkedList<>();
System.out.println("===增加元素A,B,C,D==");
linkedList.add("A");
linkedList.add("B");
linkedList.add("C");
linkedList.add("D");
System.out.println(linkedList);
System.out.println("===在列表头上增加元素E==");
linkedList.addFirst("E");
System.out.println(linkedList);
System.out.println("===在列表头上增加元素F==");
linkedList.push("F");
System.out.println(linkedList);
System.out.println("===获取列表的第一个元素==");
System.out.println(linkedList.getFirst());
System.out.println("===获取列表的最后一个元素==");
System.out.println(linkedList.getLast());
System.out.println("===弹出列表的第一个元素==");
System.out.println(linkedList.pop());
System.out.println("===删除列表上的第一个元素==");
System.out.println(linkedList.removeFirst());
System.out.println("===删除列表上的最后一个元素==");
System.out.println(linkedList.removeLast());
System.out.println(linkedList);
}
代码运行结果如下:
List接口的实现类Vector:
Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性。
看下JDK中Vector增加元素与删除元素的源码:关键字synchronized修饰了这两个方法,确保线程互斥的访问同步。
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj);
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}
测试代码:
public static void main(String[] args) {
Vector<String> vector = new Vector<>();
System.out.println("===增加元素A,B,C,D==");
vector.addElement("A");
vector.addElement("B");
vector.addElement("C");
vector.addElement("D");
System.out.println(vector);
System.out.println("===移除元素A,B,C,D==");
vector.removeAllElements();
System.out.println("列表是否为空:"+vector.isEmpty());
}
输出结果:
ArrayList LinkedList Vector三者的使用场景:
ArrayList和Vector都是基于数组实现的,数组的特点是查询快,增删慢;
ArrayList线程不安全,Vector保证线程安全。
LinkedList 是基于双向链表实现的,LinkedList同样线程不安全,链表的特点是增删快,查询慢。
- 如果程序中更多的是进行元素的频繁访问或者从集合末端进行增加或删除元素,那么建议使用ArrayList;
- 如果程序中更多的是进行随机插入和删除操作,较少查询,则建议使用LinkedList。
- 如果程序要保证线程安全性,则选择使用Vector。