List集合
Collection層次的結(jié)構(gòu)接口中,一些允許有重復(fù)的元素,例如:List接口。而另外一些不允許有重復(fù)的元素,例如:Set接口。其中也分為了有序與無序的(存儲順序)。
在JDK中沒有提供Collection接口的實現(xiàn)類,但是提供了更加具體的子接口(如Set、List和Queue接口)。
現(xiàn)在我們具體看一下List接口的特點。
List接口的介紹
List接口是位于java.util包
下的一個Collection子接口,是單列集合的一種,通常情況下我們會將所有實現(xiàn)了List接口的對象都稱為List接口。
List接口的特點:
- List接口中的元素存取是
有序
的,按照線性方式進行存儲。例如:按照 a、b、c進入,也按照a、b、c取出。 - List集合是帶有
索引
的集合,通過索引可以更精確的操作集合中的元素(與數(shù)組的索引類似) - List集合中的元素可以
重復(fù)
。
LIst接口中的常用方法
List接口是Collection集合中的子接口,不僅繼承了Collection集合中的全部方法,而且還增加了一些根據(jù)元素索引操作集合的特有方法。
Collection集合中的方法詳見:Collection集合以及方法
List集合中的特有方法:
1、添加元素
-
void add(int index,E ele):
在指定索引位置添加元素ele -
boolean addAll(int index,Collection<? extends E> eles):
在指定位置添加一個集合eles中的所有元素(<? extends E>表示泛型上限)
2、獲取元素
-
E get(int index):
獲取List集合中指定索引位置的元素 -
List subList(int fromIndex,int toIndex):
獲取List集合中指定片段[fromIndex,toIndex)的索引
3、獲取元素索引
-
int indexOf(Object obj):
獲取指定元素的第一個索引 - int lastIndexOf(Object obj):獲取指定元素的最后一個索引
4、刪除元素
-
E remove(int index):
刪除指定索引位置的元素,返回的是刪除的元素的值
5、替換元素
-
E set(int index,E ele):
將指定索引位置的元素替換為新的元素ele
代碼測試:
public class ListMethod {
public static void main(String[] args) {
List list = new ArrayList();
list.add(123);
list.add("abc");
System.out.println("list = " + list); //list = [123, abc]
list.add(1,"java");
System.out.println("list = " + list); //list = [123, java, abc]
List l = new ArrayList();
l.add("list");
l.add("set");
list.addAll(2,l);
System.out.println("list = " + list); //list = [123, java, list, set, abc]
Object o = list.get(1);
System.out.println("o = " + o); //o = java
List subList = list.subList(1, 4);
System.out.println("subList = " + subList); //subList = [java, list, set]
int javaIndex = list.indexOf("java");
System.out.println("javaIndex = " + javaIndex); //javaIndex = 1
list.add("java");
int javaLastIndex = list.lastIndexOf("java");
System.out.println("javaLastIndex = " + javaLastIndex); //javaLastIndex = 5
Object remove = list.remove(4);
System.out.println("remove = " + remove); //remove = abc
System.out.println("list = " + list); //list = [123, java, list, set, java]
list.set(4,"spring");
System.out.println("list = " + list); //list = [123, java, list, set, spring]
}
}
結(jié)果演示:
List集合的遍歷方法
在List集合
中除了Collection集合
中的Iterator迭代器
和增強for循環(huán)
兩種遍歷方式外還增加了另外兩種迭代器方式:普通for循環(huán)
和ListIterator迭代器
。
- Iterator迭代器
public class GetEleTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("iterator");
list.add("foreach");
list.add("for");
list.add("ListIterator");
Iterator iterator = list.iterator();
while (iterator.hasNext()){ //iterator foreach for ListIterator
String element = (String) iterator.next();
System.out.print(element+" ");
}
}
}
- 增強for
public class GetEleTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("iterator");
list.add("foreach");
list.add("for");
list.add("ListIterator");
for (Object element : list){ //iterator foreach for ListIterator
String string = (String) element;
System.out.print(string + " ");
}
}
}
- 普通的for循環(huán)
因為List集合中提供了根據(jù)索引操作元素的方法,所以可以通過使用get(index)
方法來進行獲取元素值并遍歷
public class GetEleTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("iterator");
list.add("foreach");
list.add("for");
list.add("ListIterator");
for (int i = 0; i < list.size(); i++) { //iterator foreach for ListIterator
System.out.print(list.get(i)+" ");
}
}
}
-
ListIterator迭代器
除了上面三種的遍歷方式,LIst集合還提供了一種專門用于遍歷LIst集合的方式:listIterator()
,該方法返回了一個列表的迭代器對象,ListIterator是一個接口,該接口繼承了Iterator接口,里面封裝了一些特有的方法。 -
void add():銅鼓迭代器添加元素到對應(yīng)的集合
-
void set(Object obj):通過迭代器替換正在迭代的元素
-
void remove():通過迭代器刪除剛迭代的元素
-
boolean hasNext():判斷是否有下一個元素
-
boolean hasPrevious():往前遍歷,判斷是否有前一個元素
-
Object next():獲取下一個元素
-
Object previous():獲取前一個的元素
-
int nextIndex():向后遍歷,返回元素的索引
-
int previousIndex():向前遍歷,返回元素的索引
public class GetEleTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("iterator");
list.add("foreach");
list.add("for");
list.add("ListIterator");
ListIterator listIterator = list.listIterator();
while (listIterator.hasNext()){
System.out.print(listIterator.nextIndex());
String next = (String) listIterator.next();
System.out.print(":"+next+" ");
}
System.out.println();
while (listIterator.hasPrevious()){
System.out.print(listIterator.previousIndex());
Object previous = listIterator.previous();
System.out.print(":" +previous+" ");
}
}
}
List接口的實現(xiàn)類
ArrayList集合
ArrayList集合
是List接口
的典型實現(xiàn)類,底層使用的是長度可變的數(shù)組,ArrayList集合中的元素可以為空。
因為ArrayList集合
的底層使用的動態(tài)數(shù)組
進行存儲數(shù)據(jù),所以ArrayList集合的查詢
元素效率較快,但是增、刪
較慢。
ArrayList集合的底層實現(xiàn):
ArrayList沒有自己特殊的方法,常用的方法都是來自于Collection集合和List集合
Collection集合中的方法詳見:Collection集合以及方法
ArrayList集合與Vector集合進行比較,兩者都是使用的動態(tài)數(shù)組,但是ArrayList集合線程不安全,效率相對較高,Vector集合線程安全,基本上里面的每一個方法都有synchronized,所以效率相對較低。
ArrayList和Vector底層分析:
ArrayList底層實現(xiàn):可變長的數(shù)組,有索引,查詢效率高,增刪效率低
構(gòu)造方法:
new ArrayList():
jdk6中,空參構(gòu)造直接創(chuàng)建10長度的數(shù)組。
jdk7(新版)、jdk8中,默認(rèn)初始容量0,在添加第一元素時初始化容量為10
new ArrayList(int initialCapacity):
指定初始化容量
添加元素:add(E e);
首次添加元素,初始化容量為10
每次添加修改modCount屬性值
每次添加檢查容量是否足夠,容量不足時需要擴容,擴容大小為原容量的1.5倍
如果添加的元素容量大于原容量的0.5倍,則直接以添加元素的容量作為擴容的容量大小
移除元素:remove(E e);
每次成功移除元素,修改modCount值
每次成功移除需要需要移動元素,以保證所以元素是連續(xù)存儲的(刪除操作效率低的原因)
------------------------------
Vector實現(xiàn)類的不點:
初始容量為10,容量不足時擴容,如果capacityIncrement為0 擴容增加為原來的2倍,否則容量為舊的長度+capacityIncrement。
LinkedList實現(xiàn)類
LinkedList類
是另一個List接口
的常用實現(xiàn)類
因為LinkedList集合
的底層使用的雙向鏈表結(jié)構(gòu),所以LinkedList集合的特點是增刪快,但是查詢慢。
LinkedLIst集合的底層結(jié)構(gòu):
LinkedList集合的底層源碼實現(xiàn)
LinkedList集合特有的操作首尾元素的方法:
首尾元素的操作效率高
- void addFirst(Object obj):在鏈表的首節(jié)點添加一個元素
- void addLast(Object obj):在鏈表的添加元素
- Object getFirst():獲取鏈表首節(jié)點的元素
- Object getLast():獲取鏈表尾結(jié)點的元素
- Object removeFirst():移除鏈表首節(jié)點的元素
- Object removeLast():移除鏈表尾結(jié)點的元素
public class LinkedListTest {
public static void main(String[] args) {
LinkedList<Object> linkedList = new LinkedList<>();
linkedList.add("linkedList");
System.out.println("linkedList = " + linkedList); //[linkedList]
linkedList.addFirst("ArrayList");
System.out.println("linkedList = " + linkedList); //[ArrayList, linkedList]
linkedList.addLast("Vector");
System.out.println("linkedList = " + linkedList); //[ArrayList, linkedList, Vector]
Object o = linkedList.get(1);
System.out.println("o = " + o); //linkedList
Object first = linkedList.getFirst();
System.out.println("first = " + first); //ArrayList
Object last = linkedList.getLast();
System.out.println("last = " + last); //Vector
Object remove = linkedList.remove(1);
System.out.println("remove = " + remove); //linkedList
System.out.println("linkedList = " + linkedList); //[ArrayList, Vector]
Object removeFirst = linkedList.removeFirst();
System.out.println("removeFirst = " + removeFirst); //ArrayList
System.out.println("linkedList = " + linkedList); //[Vector]
Object removeLast = linkedList.removeLast();
System.out.println("removeLast = " + removeLast); //Vector
System.out.println("linkedList = " + linkedList); //[]
}
}
隊列與棧
隊列和棧都屬于邏輯結(jié)構(gòu)的一種,屬于特殊的線性結(jié)構(gòu),其物理結(jié)構(gòu)可以是數(shù)組,也可以是鏈表。
LinkedList
也實現(xiàn)了Deque接口(雙端隊列),Deque接口提供了實現(xiàn)隊列和棧結(jié)構(gòu)的方法。
Stack
是Vector的子類,Stack也是實現(xiàn)了棧結(jié)構(gòu),它是數(shù)組實現(xiàn)的棧結(jié)構(gòu)
隊列
隊列(Queue)
是一種(并非一定)先進先出(FIFO)的結(jié)構(gòu)
方法名 | add | remove | element | offer | poll | peek | put | take |
---|---|---|---|---|---|---|---|---|
作用 | 增加一個元索 | 移除并返回隊列頭部的元素 | 返回隊列頭部的元素 | 添加一個元素并返回true | 移除并返問隊列頭部的元素 | 返回隊列頭部的元素 | 添加一個元素 | 移除并返回隊列頭部的元素 |
是否有異常 | 隊列已滿,則拋出一個IIIegaISlabEepeplian異常 | 隊列為空,則拋出一個NoSuchElementException異常 | 隊列為空,則拋出一個NoSuchElementException異常 | 隊列已滿,則返回false | 隊列為空,則返回null | 隊列為空,則返回null | 如果隊列滿,則阻塞 | 隊列為空,則阻塞 |
public class QueueAndDequeTest {
public static void main(String[] args) {
//LinkedList實現(xiàn)了Deque,Deque又繼承了Queue
Queue queue = new LinkedList();
queue.add("queue");
System.out.println("queue = " + queue); //[queue]
Object element = queue.element();
System.out.println("element = " + element); //queue
Object remove = queue.remove();
System.out.println("remove = " + remove); //queue
System.out.println("queue = " + queue); //[]
boolean dequeBoolean = queue.offer("deque");
System.out.println("dequeBoolean = " + dequeBoolean); //true
System.out.println("queue = " + queue); //[deque]
Object peek = queue.peek();
System.out.println("peek = " + peek); //deque
System.out.println("queue = " + queue); //[deque]
Object poll = queue.poll();
System.out.println("poll = " + poll); //deque
System.out.println("queue = " + queue); //[]
}
}
棧
棧
是一種先進后出(FILO)或后進后進先出(LIFO)的結(jié)構(gòu)。
Deque,名稱 deque 是“double ended queue(雙端隊列)”的縮寫,通常讀為“deck”。此接口定義在雙端隊列兩端訪問元素的方法。提供插入、移除和檢查元素的方法。每種方法都存在兩種形式:一種形式在操作失敗時拋出異常,另一種形式返回一個特殊值(null
或 false
,具體取決于操作)。文章來源:http://www.zghlxwxcb.cn/news/detail-412271.html
雙端隊列也可用作 LIFO(后進先出)堆棧。應(yīng)優(yōu)先使用此接口而不是遺留 Stack
類。在將雙端隊列用作堆棧時,元素被推入雙端隊列的開頭并從雙端隊列開頭彈出。堆棧方法完全等效于 Deque
方法,如下表所示:文章來源地址http://www.zghlxwxcb.cn/news/detail-412271.html
堆棧方法 | 等效 Deque 方法 |
|
---|---|---|
查看棧頂元素 | push(e) | addFirst(e) |
彈出棧 | pop() | removeFirst() |
壓入棧 | peek() | peekFirst() |
@Test
public void test02(){
//模擬棧操作
LinkedList<String> stack = new LinkedList<>();
//入棧
stack.push("張三");
stack.push("李四");
stack.push("王五");
stack.push("趙六");
//刪除棧頂元素 彈棧
stack.pop();
stack.pop();
//獲取棧頂元素
Object peek = stack.peek();
System.out.println("peek = " + peek);
}
到了這里,關(guān)于List集合以及它的實現(xiàn)類和隊列、棧的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!