各个容器类的继承关系
ArrayList类
-
是什么?
public class ArrayList<E> extends AbstractList<E> implements List<E>,RandomAccess, Cloneable, Serializable;
它实现了List接口,Iterable接口,Collection接口,Serializable接口, Cloneable接口
可以将它看作一个数组实现类,通过它创建一个对象,拥有它所继承的所有方法来操作这个数组(对象),具体实现如下:
import java.util.ArrayList; import java.util.Iterator; public class ArrayListTest { public static void main(String[] args){ //可以不指定类型,即ArrayList list= new ArrayList(); ArrayList<String> list = new ArrayList(); list.add("卤蛋"); list.add("宝宝娟"); list.add("LOVE"); //因为创建的类型指定了String类型 //list.add(520); for(int i=0;i<list.size();i++) System.out.println(list.get(i)); //利用迭代器遍历 Iterator lter=list.iterator(); while(lter.hasNext()){ System.out.println(lter.next()); } } }
-
为什么?
首先讲一下一个概念:Arrays类
java数组中的实现类是Arrays,可以直接使用它创建一个数组对象,它的继承关系如下:public class Arraysextends Object
我们可以通过它对数组对象进行一系列操作如下:
import java.util.Arrays; public class ArrayTest { public static void main(String[] args){ int[] list=new int[]{1,2,3,4,5,1,0,9,2,33,55}; Arrays.sort(list); for (int i=0;i<11 ;i++ ) { System.out.println(list[i]); } } }
它和ArrayList有个本质区别:前者属于固定数组,后者则是可变长数组,即否则ArrayList可以动态改变数组的长度,这对于编程来说很重要,所以当我们不能够确定数组长度时优先使用ArrayList
-
怎么样?
它主要有以下构造方法:- ArrayList()
构造一个初始容量为 10 的空列表 - ArrayList(Collection<? extends E> c)
构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的 - ArrayList(int initialCapacity)
构造一个具有指定初始容量的空列表
它主要有以下方法,还有大量继承而来的方法:
- boolean add(E e)
将指定的元素添加到此列表的尾部 - void add(int index, E element)
将指定的元素插入此列表中的指定位置 - boolean addAll(Collection<? extends E> c)
按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部 - boolean addAll(int index, Collection<? extends E> c)
从指定的位置开始,将指定 collection 中的所有元素插入到此列表中 - void clear()
移除此列表中的所有元素 - Object clone()
返回此 ArrayList 实例的浅表副本 - boolean contains(Object o)
如果此列表中包含指定的元素,则返回 true - void ensureCapacity(int minCapacity)
如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数 - E get(int index)
返回此列表中指定位置上的元素 - int indexOf(Object o)
返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1 - boolean isEmpty()
如果此列表中没有元素,则返回 true - E remove(int index)
移除此列表中指定位置上的元素 - protected void removeRange(int fromIndex, int toIndex)
移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素 - E set(int index, E element)
用指定的元素替代此列表中指定位置上的元素 - int size()
返回此列表中的元素数 - Object[] toArray()
按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组 - T[] toArray(T[] a)
按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型
- ArrayList()
LinkedList类
-
是什么?
public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, Serializable
LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList 实现 List 接口,能进行队列操作。
LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。 -
为什么?
ArrayList底层是由数组支持,而LinkedList 是由双向链表实现的,其中的每个对象包含数据的同时还包含指向链表中前一个与后一个元素的引用 -
怎么样?
它有以下构造方法:- LinkedList()
构造一个空列表 - LinkedList(Collection<? extends E> c)
构造一个包含指定 collection 中的元素的列表,这些元素按其 collection 的迭代器返回的顺序排列
它有以下方法:
- boolean add(E e)
将指定元素添加到此列表的结尾 - void add(int index, E element)
在此列表中指定的位置插入指定的元素 - boolean addAll(Collection<? extends E> c)
添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序 - boolean addAll(int index, Collection<? extends E> c)
将指定 collection 中的所有元素从指定位置开始插入此列表 - void addFirst(E e)
将指定元素插入此列表的开头 - void addLast(E e)
将指定元素添加到此列表的结尾 - void clear()
从此列表中移除所有元素 - boolean contains(Object o)
如果此列表包含指定元素,则返回 true - Iterator descendingIterator()
返回以逆向顺序在此双端队列的元素上进行迭代的迭代器 - E element()
获取但不移除此列表的头(第一个元素)。 - E get(int index)
返回此列表中指定位置处的元素 - E getFirst()
返回此列表的第一个元素 - E getLast()
返回此列表的最后一个元素 - boolean offer(E e)
将指定元素添加到此列表的末尾(最后一个元素 ) - boolean offerFirst(E e)
在此列表的开头插入指定的元素 - E peek()
获取但不移除此列表的头 - E pop()
从此列表所表示的堆栈处弹出一个元素 - void push(E e)
将元素推入此列表所表示的堆栈 - E remove()
获取并移除此列表的头(第一个元素) - E remove(int index)
移除此列表中指定位置处的元素
- LinkedList()
ArrayDeque类
-
是什么?
继承关系:public class ArrayDeque<E> extends AbstractCollection<E> implements Deque<E>, Cloneable, Serializable;
LinkedList类实现了队列接口和双端队列接口Dueue,而ArrayDeque类实现了高效的双端接口实现,它是基于数组实现;
-
为什么?
一般的数组对于插入删除操作的效率很低,需要移动多次,但ArrayDeque却很高效,为什么呢?因为它的实现其实是利用循环数组实现的;
但是,有个问题,java中只有数组和链表之分,循环数组是什么?其实循环数组也就是数组,它根据线性数组来得以实现,基本实现原理如下:一个线性数组,最左端是0,如果按照传统线性数组的原理添加元素到数组头,需要将整个数组向后移动数组.length的长度,这是相当低效的办法,但是,循环数组却不是这样,它根据一种逻辑上的左移来实现的,即,有head和tail两个变量,当逻辑上左移时,tail在物理上将超出数组头的部分移动到数组尾部,但因为有tail,所以tail后的元素就是数组头部,从而实现较少的移动。
-
怎么样?
构造函数如下:
- ArrayDeque()
构造一个初始容量能够容纳 16 个元素的空数组双端队列 - ArrayDeque(Collection<? extends E> c)
构造一个包含指定 collection 的元素的双端队列,这些元素按 collection 的迭代器返回的顺序排列 - ArrayDeque(int numElements)
构造一个初始容量能够容纳指定数量的元素的空数组双端队列
部分常用方法:
- boolean add(E e)
将指定元素插入此双端队列的末尾 - void addFirst(E e)
将指定元素插入此双端队列的开头 - void addLast(E e)
将指定元素插入此双端队列的末尾 - boolean offer(E e)
将指定元素插入此双端队列的末尾 - boolean offerFirst(E e)
将指定元素插入此双端队列的开头 - boolean offerLast(E e)
将指定元素插入此双端队列的末尾 - E peek()
获取,但不移除此双端队列所表示的队列的头;如果此双端队列为空,则返回 null - E peekFirst()
获取,但不移除此双端队列的第一个元素;如果此双端队列为空,则返回 null - E peekLast()
获取,但不移除此双端队列的最后一个元素;如果此双端队列为空,则返回 null - E poll()
获取并移除此双端队列所表示的队列的头(换句话说,此双端队列的第一个元素);如果此双端队列为空,则返回 null - E pollFirst()
获取并移除此双端队列的第一个元素;如果此双端队列为空,则返回 null - E pollLast()
获取并移除此双端队列的最后一个元素;如果此双端队列为空,则返回 null - E pop()
从此双端队列所表示的堆栈中弹出一个元素 - void push(E e)
将元素推入此双端队列所表示的堆栈 - E remove()
获取并移除此双端队列所表示的队列的头 - boolean remove(Object o)
从此双端队列中移除指定元素的单个实例 - int size()
返回此双端队列中的元素数 - T[]
toArray(T[] a)
返回一个以恰当顺序包含此双端队列所有元素的数组(从第一个元素到最后一个元素);返回数组的运行时类型是指定数组的运行时类型
- ArrayDeque()