當前位置:首頁 » 編程語言 » 紅黑樹java實現

紅黑樹java實現

發布時間: 2023-10-05 23:27:52

java中幾種Map在什麼情況下使用,並簡單介紹原因及原理

一、Map用於保存具有映射關系的數據,Map里保存著兩組數據:key和value,它們都可以使任何引用類型的數據,但key不能重復。所以通過指定的key就可以取出對應的value。Map介面定義了如下常用的方法:
1、void clear():刪除Map中所以鍵值對。
2、boolean containsKey(Object key):查詢Map中是否包含指定key,如果包含則返回true。
3、boolean containsValue(Object value):查詢Map中是否包含指定value,如果包含則返回true。
4、Set entrySet():返回Map中所包含的鍵值對所組成的Set集合,每個集合元素都是Map.Entry對象(Entry是Map的內部類)。
5、Object get(Object key):返回指定key所對應的value,如Map中不包含key則返回null。
6、boolean isEmpty():查詢Map是否為空,如果空則返回true。
7、Set keySet():返回該Map中所有key所組成的set集合。
8、Object put(Object key,Object value):添加一個鍵值對,如果已有一個相同的key值則新的鍵值對覆蓋舊的鍵值對。
9、void putAll(Map m):將指定Map中的鍵值對復制到Map中。
10、Object remove(Object key):刪除指定key所對應的鍵值對,返回可以所關聯的value,如果key不存在,返回null。
11、int size():返回該Map里的鍵值對的個數。
12、Collection values():返回該Map里所有value組成的Collection。
Map中包含一個內部類:Entry。該類封裝了一個鍵值對,它包含了三個方法:
1、Object getKey():返回該Entry里包含的key值。
2、Object getValeu():返回該Entry里包含的value值。
3、Object setValue(V value):設置該Entry里包含的value值,並返回新設置的value值。

二、HashMap和Hashtable實現類:
1、HashMap與HashTable的區別:
1) 同步性:Hashtable是同步的,這個類中的一些方法保證了Hashtable中的對象是線程安全的。而HashMap則是非同步的,因此HashMap中的對象並不是線程安全的。因為同步的要求會影響執行的效率,所以如果你不需要線程安全的集合那麼使用HashMap是一個很好的選擇,這樣可以避免由於同步帶來的不必要的性能開銷,從而提高效率。
2) 值:HashMap可以讓你將空值作為一個表的條目的key或value,但是Hashtable是不能放入空值的。HashMap最多隻有一個key值為null,但可以有無數多個value值為null。
2、性能:HashMap的性能最好,HashTable的性能是最差(因為它是同步的)
3、注意:
1)用作key的對象必須實現hashCode和equals方法。
2)不能保證其中的鍵值對的順序
3)盡量不要使用可變對象作為它們的key值。

三、LinkedHashMap:
它的父類是HashMap,使用雙向鏈表來維護鍵值對的次序,迭代順序與鍵值對的插入順序保持一致。LinkedHashMap需要維護元素的插入順序,so性能略低於HashMap,但在迭代訪問元素時有很好的性能,因為它是以鏈表來維護內部順序。

四、TreeMap:
Map介面派生了一個SortMap子介面,SortMap的實現類為TreeMap。TreeMap也是基於紅黑樹對所有的key進行排序,有兩種排序方式:自然排序和定製排序。Treemap的key以TreeSet的形式存儲,對key的要求與TreeSet對元素的要求基本一致。
1、Map.Entry firstEntry():返回最小key所對應的鍵值對,如Map為空,則返回null。
2、Object firstKey():返回最小key,如果為空,則返回null。
3、Map.Entry lastEntry():返回最大key所對應的鍵值對,如Map為空,則返回null。
4、Object lastKey():返回最大key,如果為空,則返回null。
5、Map.Entry higherEntry(Object key):返回位於key後一位的鍵值對,如果為空,則返回null。
6、Map.Entry lowerEntry(Object key):返回位於key前一位的鍵值對,如果為空,則返回null。
7、Object lowerKey(Object key):返回位於key前一位key值,如果為空,則返回null。
8、NavigableMap subMap(Object fromKey,boolean fromlnclusive,Object toKey,boolean toInciusive):返回該Map的子Map,其key范圍從fromKey到toKey。
9、SortMap subMap(Object fromKey,Object toKey );返回該Map的子Map,其key范圍從fromkey(包括)到tokey(不包括)。
10、SortMap tailMap(Object fromkey ,boolean inclusive):返回該Map的子Map,其key范圍大於fromkey(是否包括取決於第二個參數)的所有key。
11、 SortMap headMap(Object tokey ,boolean inclusive):返回該Map的子Map,其key范圍小於tokey(是否包括取決於第二個參數)的所有key。

五、WeakHashMap:
WeakHashMap與HashMap的用法基本相同,區別在於:後者的key保留對象的強引用,即只要HashMap對象不被銷毀,其對象所有key所引用的對象不會被垃圾回收,HashMap也不會自動刪除這些key所對應的鍵值對對象。但WeakHashMap的key所引用的對象沒有被其他強引用變數所引用,則這些key所引用的對象可能被回收。WeakHashMap中的每個key對象保存了實際對象的弱引用,當回收了該key所對應的實際對象後,WeakHashMap會自動刪除該key所對應的鍵值對。

六、IdentityHashMap類:
IdentityHashMap與HashMap基本相似,只是當兩個key嚴格相等時,即key1==key2時,它才認為兩個key是相等的 。IdentityHashMap也允許使用null,但不保證鍵值對之間的順序。

七、EnumMap類:
1、EnumMap中所有key都必須是單個枚舉類的枚舉值,創建EnumMap時必須顯示或隱式指定它對應的枚舉類。
2、EnumMap根據key的自然順序,即枚舉值在枚舉類中定義的順序,來維護鍵值對的次序。
3、EnumMap不允許使用null作為key值,但value可以。

② 為什麼學習集合關系

集合可以說是學習 Java 中最重要的一塊知識點了,無論做任何業務系統,集合總是最為基礎的那塊 API。我第一次接觸集合,是在我大三的時候,那時候去面試,面試官問我:你了解過集合嗎?可惜那時候沒什麼項目經驗,所以基本沒有了解過,因此也錯失了機會。

到了現在,我已經工作了5年了,也做過了大大小小十幾個項目。這些項目中有簡單的 SSH 項目,也有分布式高並發的復雜項目。無論在哪個項目中,關於集合的時候是必不可少的。但我現在慢慢回顧過去做的項目,我發現自己使用到的集合還是比較少,基本上只有:ArrayList、HashSet、HashMap 這幾個。

但當我開始深入去了解 JDK 集合的整個體系時,我發現之前的我了解得確實非常淺顯。例如關於 List 的實現有 ArrayList、LinkedList、Vector、Stack 這四種實現,但我們很多時候只是直接使用 ArrayList,而不是根據場景去選擇。

1.學習集合源碼,能夠讓我們使用得更加准確。

當我們深入學習了源碼之後,我們就能夠了解其特性,從而能夠根據我們的使用場景去做出更好的選擇,從而讓我們的代碼運行效率更高。

我們舉一個最簡單的例子 —— ArrayList 和 LinkedList。它們兩者底層採用了完全不同的實現方式,ArrayList 使用數組實現,而 LinkedList 則使用鏈表實現。這使得 ArrayList 的讀取效率高,而 LinkedList 的讀取效率低。但因為 LinkedList 採用鏈表實現,所以其增加和刪除比較方便,而 ArrayList 則比較麻煩。所以 ArrayList 比較適合用於讀場合較多的情況,而 LinkedList 比較適合用於增加、刪除較多的場景。

我們來看另外一個例子 —— HashMap 和 TreeMap。乍看之下,他們都是 Map 集合的實現,但是它們內部有著截然不同的實現。HashMap 是 Map 介面的哈希實現,其內部使用了鏈表和紅黑樹實現。而 TreeMap 是 Map 介面的有序實現,其內部使用了紅黑樹實現。所以 HashMap 一般用來存儲 key、value 的實現,而 TreeMap 常用存儲需要排序的元素。

除了我們舉的這兩個例子之外,還有許多這樣的例子,比如:HashMap 與 LinkedHashMap 的區別,HashMap 與 WeakHashMap 的區別,LinkedList 與 ArrayDeque 的區別。

2.學習集合源碼,讓我們學習經典的設計方式。

在集合的整個架構設計中,其類繼承體系非常簡單,但是卻很經典。例如:Collection 介面設計了集合通用的操作,每個集合類型都有對應的介面(List、Set、Map),每個集合類型都有對應的抽象實現(AbstractList、AbstractSet、AbstractMap)等。
當我們閱讀這些源碼的時候,這種設計方式都會潛移默化地影響我們。當我們之後自己設計一個框架的時候,我們就會不知不覺地用上去。所有的創新都是從模仿開始的,所以閱讀優秀的集合源碼很重要。

3.幫助通過面試,獲得更高的薪酬。

現在關於集合的原理是 Java 工程師面試的家常菜,幾乎每一個企業的面試都會問到。如果你連這塊東西都沒搞清楚,那麼你就不需要聊其他了,直接被幹掉。而如果你能將整個 Java 集合體系清晰地說出去,並且舉一反三地對比,那麼你就比其他人優秀了。

4.學習經典的數據結構。

還記得大學在學習數據結構的時候,我們都是從理論上去記憶。但是當我看完集合源碼之後,我忽然發現——JDK集合源碼簡直就是數據結構的最佳實踐呀!

數據結構中最為基礎的幾個結構為:順序表、單鏈表、雙向鏈表、隊列、棧、二叉堆、紅黑樹、哈希表。這些所有的實現都能在 JDK 集合的實現中找到。例如:ArrayList 就是順序表的實現,LinkedList 就是雙向鏈表的實現,Stack 就是棧的實現,HashMap 就是哈希表的實現,TreeMap 就是紅黑樹的實現,PriorityQueue 就是二叉堆的實現。

5.所有技術的基礎

集合源碼可以說是 JDK 所有源碼中最為簡單的一塊了,而且也是其他所有源碼的基礎。例如線程池的源碼中也大量使用了阻塞隊列,如果你連集合源碼都搞不懂,那麼線程池的源碼你也肯定看不懂的。而如果線程池源碼看不懂,那麼你 netty 的源碼也看不懂的。netty 源碼看不懂,那麼 bbo 的源碼也是看不懂的。
看明白了么?這些技術都是一換扣著一換的。如果你想要後續學習更加快速,那麼你就必須把最基礎的東西學明白了。如果連最基礎的東西都沒學明白,就直接去學其他更復雜的東西,最後只會越來越難,最終逃脫不了放棄的命運。

讀到了這里,我相信你也對集合的重要性有了不一樣的認識。那麼接下來一段時間,就讓我和你一起來深入學學集合源碼吧。如果覺得讀了有用,那麼請給我一個贊吧。你們的贊是我繼續寫下去的動力!

③ java集合類哪個函數可以

java集合裡面的函數
java集合裡面的函數_java集合【1】——— 從集合介面框架說起

百里方欣
原創
關注
0點贊·155人閱讀
(一) java集合分類

之前大概分為三種,Set,List,Map三種,JDK5之後,增加Queue.主要由Collection和Map兩個介面衍生出來,同時Collection介面繼承Iterable介面,所以我們也可以說java裡面的集合類主要是由Iterable和Map兩個介面以及他們的子介面或者其實現類組成。我們可以認為Collection介面定義了單列集合的規范,每次只能存儲一個元素,而Map介面定義了雙列集合的規范,每次能存儲一對元素。

Iterable介面:主要是實現遍歷功能

Collection介面: 允許重復

Set介面:無序,元素不可重復,訪問元素只能通過元素本身來訪問。

List介面:有序且可重復,可以根據元素的索引來訪問集合中的元素。

Queue介面:隊列集合

Map介面:映射關系,簡單理解為鍵值對,Key不可重復,與Collection介面關系不大,只是個別函數使用到。

整個介面框架關系如下(來自網路):

(1) Iterable介面

1. 內部定義的方法

java集合最源頭的介面,實現這個介面的作用主要是集合對象可以通過迭代器去遍歷每一個元素。

源碼如下:

// 返回一個內部元素為T類型的迭代器(JDK1.5隻有這個介面)

Iterator iterator();

// 遍歷內部元素,action意思為動作,指可以對每個元素進行操作(JDK1.8添加)

default void forEach(Consumer super T> action) {}

// 創建並返回一個可分割迭代器(JDK1.8添加),分割的迭代器主要是提供可以並行遍歷元素的迭代器,可以適應現在cpu多核的能力,加快速度。

default Spliterator spliterator() {

return Spliterators.spliteratorUnknownSize(iterator(), 0);

}

從上面可以看出,foreach迭代以及可分割迭代,都加了default關鍵字,這個是Java 8 新的關鍵字,以前介面的所有介面,具體子類都必須實現,而對於deafult關鍵字標識的方法,其子類可以不用實現,這也是介面規范發生變化的一點。

下面我們分別展示三個介面的調用:

1.1 iterator方法

public static void iteratorHasNext(){

List list=new ArrayList();

list.add("Jam");

list.add("Jane");

list.add("Sam");

// 返回迭代器

Iterator iterator=list.iterator();

// hashNext可以判斷是否還有元素

while(iterator.hasNext()){

//next()作用是返回當前指針指向的元素,之後將指針移向下個元素

System.out.println(iterator.next());

}

}

當然也可以使用for-each loop方式遍歷

for (String item : list) {

System.out.println(item);

}

但是實際上,這種寫法在class文件中也是會轉成迭代器形式,這只是一個語法糖。class文件如下:

public class IterableTest {

public IterableTest() { }

public static void main(String[] args) {

iteratorHasNext();

}

public static void iteratorHasNext() {

List list = new ArrayList();

list.add("Jam");

list.add("Jane");

list.add("Sam");

Iterator iterator = list.iterator();

Iterator var2 = list.iterator();

while(var2.hasNext()) {

String item = (String)var2.next();

System.out.println(item);

}

}

}

需要注意的一點是,迭代遍歷的時候,如果刪除或者添加元素,都會拋出修改異常,這是由於快速失敗【fast-fail】機制。

public static void iteratorHasNext(){

List list=new ArrayList();

list.add("Jam");

list.add("Jane");

list.add("Sam");

for (String item : list) {

if(item.equals("Jam")){

list.remove(item);

}

System.out.println(item);

}

}

從下面的錯誤我們可以看出,第一個元素是有被列印出來的,也就是remove操作是成功的,只是遍歷到第二個元素的時候,迭代器檢查,發現被改變了,所以拋出了異常。

Jam

Exception in thread "main" java.util.

at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)

at java.util.ArrayList$Itr.next(ArrayList.java:859)

at IterableTest.iteratorHasNext(IterableTest.java:15)

at IterableTest.main(IterableTest.java:7)

1.2 forEach方法

其實就是把對每一個元素的操作當成了一個對象傳遞進來,對每一個元素進行處理。

default void forEach(Consumer super T> action) {

Objects.requireNonNull(action);

for (T t : this) {

action.accept(t);

}

}

```java

當然像ArrayList自然也是有自己的實現的,那我們就可以使用這樣的寫法,簡潔優雅。forEach方法在java8中參數是`java.util.function.Consumer`,可以稱為**消費行為**或者說**動作**類型。

```java

list.forEach(x -> System.out.print(x));

同時,我們只要實現Consumer介面,就可以自定義動作,如果不自定義,默認迭代順序是按照元素的順序。

public class ConsumerTest {

public static void main(String[] args) {

List list=new ArrayList();

list.add("Jam");

list.add("Jane");

list.add("Sam");

MyConsumer myConsumer = new MyConsumer();

Iterator it = list.iterator();

list.forEach(myConsumer);

}

static class MyConsumer implements Consumer {

@Override

public void accept(Object t) {

System.out.println("自定義列印:" + t);

}

}

}

輸出的結果:

自定義列印:Jam

自定義列印:Jane

自定義列印:Sam

1.3 spliterator方法

這是一個為了並行遍歷數據元素而設計的迭代方法,返回的是Spliterator,是專門並行遍歷的迭代器。以發揮多核時代的處理器性能,java默認在集合框架中提供了一個默認的Spliterator實現,底層也就是Stream.isParallel()實現的,我們可以看一下源碼:

// stream使用的就是spliterator

default Stream stream() {

return StreamSupport.stream(spliterator(), false);

}

default Spliterator spliterator() {

return Spliterators.spliterator(this, 0);

}

public static Stream stream(Spliterator spliterator, boolean parallel) {

Objects.requireNonNull(spliterator);

return new ReferencePipeline.Head<>(spliterator,

StreamOpFlag.fromCharacteristics(spliterator),

parallel);

}

使用的方法如下:

public static void spliterator(){

List list = Arrays.asList("1", "2", "3","4","5","6","7","8","9","10");

// 獲取可迭代器

Spliterator spliterator = list.spliterator();

// 一個一個遍歷

System.out.println("tryAdvance: ");

spliterator.tryAdvance(item->System.out.print(item+" "));

spliterator.tryAdvance(item->System.out.print(item+" "));

System.out.println("\n-------------------------------------------");

// 依次遍歷剩下的

System.out.println("forEachRemaining: ");

spliterator.forEachRemaining(item->System.out.print(item+" "));

System.out.println("\n------------------------------------------");

// spliterator1:0~10

Spliterator spliterator1 = list.spliterator();

// spliterator1:6~10 spliterator2:0~5

Spliterator spliterator2 = spliterator1.trySplit();

// spliterator1:8~10 spliterator3:6~7

Spliterator spliterator3 = spliterator1.trySplit();

System.out.println("spliterator1: ");

spliterator1.forEachRemaining(item->System.out.print(item+" "));

System.out.println("\n------------------------------------------");

System.out.println("spliterator2: ");

spliterator2.forEachRemaining(item->System.out.print(item+" "));

System.out.println("\n------------------------------------------");

System.out.println("spliterator3: ");

spliterator3.forEachRemaining(item->System.out.print(item+" "));

}

tryAdvance() 一個一個元素進行遍歷

forEachRemaining() 順序地分塊遍歷

trySplit()進行分區形成另外的 Spliterator,使用在並行操作中,分出來的是前面一半,就是不斷把前面一部分分出來

結果如下:

tryAdvance:

1 2

-------------------------------------------

forEachRemaining:

3 4 5 6 7 8 9 10

------------------------------------------

spliterator1:

8 9 10

------------------------------------------

spliterator2:

1 2 3 4 5

------------------------------------------

spliterator3:

6 7

還有一些其他的用法在這里就不列舉了,主要是trySplit()之後,可以用於多線程遍歷。理想的時候,可以平均分成兩半,有利於並行計算,但是不是一定平分的。

2. Collection介面 extend Iterable

Collection介面可以算是集合類的一個根介面之一,一般不能夠直接使用,只是定義了一個規范,定義了添加,刪除等管理數據的方法。繼承Collection介面的有List,Set,Queue,不過Queue定義了自己的一些介面,相對來說和其他的差異比較大。

2.1 內部定義的方法

源碼如下:

boolean add(Object o) //添加元素

boolean remove(Object o) //移除元素

boolean addAll(Collection c) //批量添加

boolean removeAll(Collection c) //批量移除

void retainAll(Collection c) // 移除在c中不存在的元素

void clear() //清空集合

int size() //集合大小

boolean isEmpty() //是否為空

boolean contains(Object o) //是否包含在集合中

boolean containsAll(Collection c) //是否包含所有的元素

Iterator iterator() // 獲取迭代器

Object[] toArray() // 轉成數組

default boolean removeIf(Predicate super E> filter) {} // 刪除集合中復合條件的元素,刪除成功返回true

boolean equals(Object o)

int hashCode()

default Spliterator spliterator() {} //獲取可分割迭代器

default Stream stream() {} //獲取流

default Stream parallelStream() {} //獲取並行流

裡面獲取並行流的方法parallelStream(),其實就是通過默認的ForkJoinPool(主要用來使用分治法(Divide-and-Conquer Algorithm)來解決問題),提高多線程任務的速度。我們可以使用ArrayList來演示一下平行處理能力。例如下面的例子,輸出的順序就不一定是1,2,3...,可能是亂序的,這是因為任務會被分成多個小任務,任務執行是沒有特定的順序的。

List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

list.parallelStream()

.forEach(out::println);

2.2 繼承Collection的主要介面

graph LR;

Collection -->List-有順序,可重復

List-有順序,可重復 -->LinkedList-使用鏈表實現,線程不安全

List-有順序,可重復 -->ArrayList-數組實現,線程不安全

List-有順序,可重復 -->Vector-數組實現,線程安全

Vector-數組實現,線程安全 -->Stack-堆棧,先進後出

Collection-->Set-不可重復,內部排序

Set-不可重復,內部排序-->HashSet-hash表存儲

HashSet-hash表存儲-->LinkHashSet-鏈表維護插入順序

Set-不可重復,內部排序-->TreeSet-二叉樹實現,排序

Collection-->Queue-隊列,先進先出

2.2.1 List extend Collection

繼承於Collection介面,有順序,取出的順序與存入的順序一致,有索引,可以根據索引獲取數據,允許存儲重復的元素,可以放入為null的元素。

最常見的三個實現類就是ArrayList,Vector,LinkedList,ArrayList和Vector都是內部封裝了對數組的操作,唯一不同的是,Vector是線程安全的,而ArrayList不是,理論上ArrayList操作的效率會比Vector好一些。

裡面是介面定義的方法:

int size(); //獲取大小

boolean isEmpty(); //判斷是否為空

boolean contains(Object o); //是否包含某個元素

Iterator iterator(); //獲取迭代器

Object[] toArray(); // 轉化成為數組(對象)

T[] toArray(T[] a); // 轉化為數組(特定位某個類)

boolean add(E e); //添加

boolean remove(Object o); //移除元素

boolean containsAll(Collection> c); // 是否包含所有的元素

boolean addAll(Collection extends E> c); //批量添加

boolean addAll(int index, Collection extends E> c); //批量添加,指定開始的索引

boolean removeAll(Collection> c); //批量移除

boolean retainAll(Collection> c); //將c中不包含的元素移除

default void replaceAll(UnaryOperator operator) {}//替換

default void sort(Comparator super E> c) {}// 排序

void clear();//清除所有的元素

boolean equals(Object o);//是否相等

int hashCode(); //計算獲取hash值

E get(int index); //通過索引獲取元素

E set(int index, E element);//修改元素

void add(int index, E element);//在指定位置插入元素

E remove(int index);//根據索引移除某個元素

int indexOf(Object o); //根據對象獲取索引

int lastIndexOf(Object o); //獲取對象元素的最後一個元素

ListIterator listIterator(); // 獲取List迭代器

ListIterator listIterator(int index); // 根據索引獲取當前的位置的迭代器

List subList(int fromIndex, int toIndex); //截取某一段數據

default Spliterator spliterator(){} //獲取可切分迭代器

上面的方法都比較簡單,值得一提的是裡面出現了ListIterator,這是一個功能更加強大的迭代器,繼承於Iterator,只能用於List類型的訪問,拓展功能例如:通過調用listIterator()方法獲得一個指向List開頭的ListIterator,也可以調用listIterator(n)獲取一個指定索引為n的元素的ListIterator,這是一個可以雙向移動的迭代器。

操作數組索引的時候需要注意,由於List的實現類底層很多都是數組,所以索引越界會報錯IndexOutOfBoundsException。

說起List的實現子類:

ArrayList:底層存儲結構是數組結構,增加刪除比較慢,查找比較快,是最常用的List集合。線程不安全。

LinkedList:底層是鏈表結構,增加刪除比較快,但是查找比較慢。線程不安全。

Vector:和ArrayList差不多,但是是線程安全的,即同步。

2.2.2 Set extend Collection

Set介面,不允許放入重復的元素,也就是如果相同,則只存儲其中一個。

下面是源碼方法:

int size(); //獲取大小

boolean isEmpty(); //是否為空

boolean contains(Object o); //是否包含某個元素

Iterator iterator(); //獲取迭代器

Object[] toArray(); //轉化成為數組

T[] toArray(T[] a); //轉化為特定類的數組

boolean add(E e); //添加元素

boolean remove(Object o); //移除元素

boolean containsAll(Collection> c); //是否包含所有的元素

boolean addAll(Collection extends E> c); //批量添加

boolean retainAll(Collection> c); //移除所有不存在於c集合中的元素

boolean removeAll(Collection> c); //移除所有在c集合中存在的元素

void clear(); //清空集合

boolean equals(Object o); //是否相等

int hashCode(); //計算hashcode

default Spliterator spliterator() {} //獲取可分割迭代器

主要的子類:

HashSet

允許空值

通過HashCode方法計算獲取hash值,確定存儲位置,無序。

LinkedHashSet

HashSet的子類

有順序

TreeSet

如果無參數構建Set,則需要實現Comparable方法。

亦可以創建時傳入比較方法,用於排序。

2.2.3 Queue extend Collection

隊列介面,在Collection介面的接觸上添加了增刪改查介面定義,一般默認是先進先出,即FIFO,除了優先隊列和棧,優先隊列是自己定義了排序的優先順序,隊列中不允許放入null元素。

下面是源碼:

boolean add(E e); //插入一個元素到隊列,失敗時返回IllegalStateException (如果隊列容量不夠)

boolean offer(E e); //插入一個元素到隊列,失敗時返回false

E remove(); //移除隊列頭的元素並移除

E poll(); //返回並移除隊列的頭部元素,隊列為空時返回null

E element(); //返回隊列頭元素

E peek(); //返回隊列頭部的元素,隊列為空時返回null

主要的子介面以及實現類有:

Deque(介面):Queue的子介面,雙向隊列,可以從兩邊存取

ArrayDeque:Deque的實現類,底層用數組實現,數據存貯在數組中

AbstractQueue:Queue的子介面,僅實現了add、remove和element三個方法

PriorityQueue:按照默認或者自己定義的順序來排序元素,底層使用堆(完全二叉樹)實現,使用動態數組實現,

BlockingQueue: 在java.util.concurrent包中,阻塞隊列,滿足當前無法處理的操作。

(2) Map介面

定義雙列集合的規范Map,每次存儲一對元素,即key和value。

key的類型可以和value的類型相同,也可以不同,任意的引用類型都可以。

key是不允許重復的,但是value是可以重復的,所謂重復是指計算的hash值系統。

下面的源碼的方法:

V put(K key, V value); // 添加元素

V remove(Object key); // 刪除元素

void putAll(Map extends K, ? extends V> m); // 批量添加

void clear() // 移除所有元素

V get(Object key); // 通過key查詢元素

int size(); // 查詢集合大小

boolean isEmpty(); // 集合是否為空

boolean containsKey(Object key); // 是否包含某個key

boolean containsValue(Object value); // 是否包含某個value

Set keySet(); // 獲取所有key的set集合

Collection values(); // 獲取所有的value的set集合

Set> entrySet(); // 返回鍵值對的set,每一個鍵值對是一個entry對象

boolean equals(Object o); // 用於比較的函數

int hashCode(); // 計算hashcode

default V getOrDefault(Object key, V defaultValue) // 獲取key對應的Value,沒有則返回默認值()

default void forEach(BiConsumer super K, ? super V> action) {} // 遍歷

default void replaceAll(BiFunction super K, ? super V, ? extends V> function) {} // 批量替換

// 缺少這個key的時候才會添加進去

// 返回值是是key對應的value值,如果不存在,則返回的是剛剛放進去的value

default V putIfAbsent(K key, V value) {}

default boolean remove(Object key, Object value) {} // 移除元素

default boolean replace(K key, V oldValue, V newValue) {} // 替換

default V replace(K key, V value) {} //替換

// 和putIfAbsent有點像,只不過傳進去的mappingFunction是映射函數,也就是如果不存在key對應的value,將會執行函數,函數返回值會被當成value添加進去,同時返回新的value值

default V computeIfAbsent(K key,Function super K, ? extends V> mappingFunction) {}

// 和computeIfAbsent方法相反,只有key存在的時候,才會執行函數,並且返回

default V computeIfPresent(K key,BiFunction super K, ? super V, ? extends V> remappingFunction) {}

// 不管如何都會執行映射函數,返回value

default V compute(K key,BiFunction super K, ? super V, ? extends V> remappingFunction) {}

default V merge(K key, V value,BiFunction super V, ? super V, ? extends V> remappingFunction) {}

值得注意的是,Map裡面定義了一個Entry類,其實就是定義了一個存儲數據的類型,一個entry就是一個.

Map的常用的實現子類:

HashMap:由數組和鏈表組成,線程不安全,無序。

LinkedHashMap:如果我們需要是有序的,那麼就需要它,時間和空間效率沒有HashMap那麼高,底層是維護一條雙向鏈表,保證了插入的順序。

ConcurrentHashMap:線程安全,1.7JDK使用鎖分離,每一段Segment都有自己的獨立鎖,相對來說效率也比較高。JDK1.8拋棄了Segment,使用Node數組+鏈表和紅黑樹實現,在線程安全控制上使用Synchronize和CAS,可以認為是優化的線程安全的HashMap。

HashTable:對比與HashMap主要是使用關鍵字synchronize,加上同步鎖,線程安全。

(二)總結

這些集合原始介面到底是什麼?為什麼需要?

我想,這些介面其實都是一種規則/規范的定義,如果不這么做也可以,所有的子類自己實現,但是從迭代以及維護的角度來說,這就是一種抽象或者分類,比如定義了Iterator介面,某一些類就可以去繼承或者實現,那就得遵守這個規范/契約。可以有所拓展,每個子類的拓展不一樣,所以每個類就各有所長,但是都有一個中心,就是原始的集合介面。比如實現Map介面的所有類的中心思想都不變,只是各有所長,各分千秋,形成了大千集合世界。

【作者簡介】:

秦懷,公眾號【秦懷雜貨店】作者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。個人寫作方向:Java源碼解析,JDBC,Mybatis,Spring,redis,分布式,劍指Offer,LeetCode等,認真寫好每一篇文章,不喜歡標題黨,不喜歡花里胡哨,大多寫系列文章,不能保證我寫的都完全正確,但是我保證所寫的均經過實踐或者查找資料。遺漏或者錯誤之處,還望指正。

平日時間寶貴,只能使用晚上以及周末時間學習寫作,關注我,我們一起成長吧~

熱點內容
青驕如何重置賬號密碼 發布:2025-02-01 09:57:51 瀏覽:520
阿里雲伺服器鏡像市場 發布:2025-02-01 09:46:04 瀏覽:525
任子行伺服器管理口默認地址 發布:2025-02-01 09:42:58 瀏覽:996
設備作為FTP客戶端時 發布:2025-02-01 09:35:07 瀏覽:936
安卓如何登錄ios明日之後 發布:2025-02-01 09:31:59 瀏覽:306
怎麼查看手機存儲卡 發布:2025-02-01 09:31:51 瀏覽:341
java知識點總結 發布:2025-02-01 09:08:32 瀏覽:685
如何在手機版給伺服器加光影 發布:2025-02-01 09:02:14 瀏覽:728
簡單神器安卓系統的哪個好 發布:2025-02-01 09:00:48 瀏覽:355
社保卡密碼如何異地改密碼 發布:2025-02-01 08:57:22 瀏覽:34