日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 容器_java容器考点总结和源码剖析!!!

發(fā)布時間:2023/12/19 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 容器_java容器考点总结和源码剖析!!! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

出自:https://github.com/CyC2018/CS-Notes

  • 一、概覽

    • Collection

    • Map

  • 二、容器中的設(shè)計模式

    • 迭代器模式

    • 適配器模式

  • 三、源碼分析

    • ArrayList

    • Vector

    • CopyOnWriteArrayList

    • LinkedList

    • HashMap

    • ConcurrentHashMap

    • LinkedHashMap

    • WeakHashMap

  • 參考資料

一、概覽

容器主要包括 Collection 和 Map 兩種,Collection 存儲著對象的集合,而 Map 存儲著鍵值對(兩個對象)的映射表。

Collection

1. Set

  • TreeSet:基于紅黑樹實現(xiàn),支持有序性操作,例如根據(jù)一個范圍查找元素的操作。但是查找效率不如 HashSet,HashSet 查找的時間復(fù)雜度為 O(1),TreeSet 則為 O(logN)。

  • HashSet:基于哈希表實現(xiàn),支持快速查找,但不支持有序性操作。并且失去了元素的插入順序信息,也就是說使用 Iterator 遍歷 HashSet 得到的結(jié)果是不確定的。

  • LinkedHashSet:具有 HashSet 的查找效率,且內(nèi)部使用雙向鏈表維護元素的插入順序。

2. List

  • ArrayList:基于動態(tài)數(shù)組實現(xiàn),支持隨機訪問。

  • Vector:和 ArrayList 類似,但它是線程安全的。

  • LinkedList:基于雙向鏈表實現(xiàn),只能順序訪問,但是可以快速地在鏈表中間插入和刪除元素。不僅如此,LinkedList 還可以用作棧、隊列和雙向隊列。

3. Queue

  • LinkedList:可以用它來實現(xiàn)雙向隊列。

  • PriorityQueue:基于堆結(jié)構(gòu)實現(xiàn),可以用它來實現(xiàn)優(yōu)先隊列。

Map

  • TreeMap:基于紅黑樹實現(xiàn)。

  • HashMap:基于哈希表實現(xiàn)。

  • HashTable:和 HashMap 類似,但它是線程安全的,這意味著同一時刻多個線程可以同時寫入 HashTable 并且不會導(dǎo)致數(shù)據(jù)不一致。它是遺留類,不應(yīng)該去使用它。現(xiàn)在可以使用 ConcurrentHashMap 來支持線程安全,并且 ConcurrentHashMap 的效率會更高,因為 ConcurrentHashMap 引入了分段鎖。

  • LinkedHashMap:使用雙向鏈表來維護元素的順序,順序為插入順序或者最近最少使用(LRU)順序。

二、容器中的設(shè)計模式

迭代器模式

Collection 繼承了 Iterable 接口,其中的 iterator() 方法能夠產(chǎn)生一個 Iterator 對象,通過這個對象就可以迭代遍歷 Collection 中的元素。

從 JDK 1.5 之后可以使用 foreach 方法來遍歷實現(xiàn)了 Iterable 接口的聚合對象。

List?list?=?new?ArrayList<>();
list.add("a");
list.add("b");for?(String?item?:?list)?{
????System.out.println(item);
}

適配器模式

java.util.Arrays#asList() 可以把數(shù)組類型轉(zhuǎn)換為 List 類型。

@SafeVarargs
public?static??List?asList(T...?a)

應(yīng)該注意的是 asList() 的參數(shù)為泛型的變長參數(shù),不能使用基本類型數(shù)組作為參數(shù),只能使用相應(yīng)的包裝類型數(shù)組。

Integer[]?arr?=?{1,?2,?3};
List?list?=?Arrays.asList(arr);

也可以使用以下方式調(diào)用 asList():

List?list?=?Arrays.asList(1,?2,?3);

三、源碼分析

如果沒有特別說明,以下源碼分析基于 JDK 1.8。

在 IDEA 中 double shift 調(diào)出 Search EveryWhere,查找源碼文件,找到之后就可以閱讀源碼。

ArrayList

1. 概覽

實現(xiàn)了 RandomAccess 接口,因此支持隨機訪問。這是理所當(dāng)然的,因為 ArrayList 是基于數(shù)組實現(xiàn)的。

public?class?ArrayList<E>?extends?AbstractList<E>implements?List<E>,?RandomAccess,?Cloneable,?java.io.Serializable

數(shù)組的默認大小為 10。

private?static?final?int?DEFAULT_CAPACITY?=?10;

2. 擴容

添加元素時使用 ensureCapacityInternal() 方法來保證容量足夠,如果不夠時,需要使用 grow() 方法進行擴容,新容量的大小為 oldCapacity + (oldCapacity >> 1),也就是舊容量的 1.5 倍。

擴容操作需要調(diào)用 Arrays.copyOf() 把原數(shù)組整個復(fù)制到新數(shù)組中,這個操作代價很高,因此最好在創(chuàng)建 ArrayList 對象時就指定大概的容量大小,減少擴容操作的次數(shù)。

public?boolean?add(E?e)?{
????ensureCapacityInternal(size?+?1);??//?Increments?modCount!!
????elementData[size++]?=?e;
????return?true;
}

private?void?ensureCapacityInternal(int?minCapacity)?{
????if?(elementData?==?DEFAULTCAPACITY_EMPTY_ELEMENTDATA)?{
????????minCapacity?=?Math.max(DEFAULT_CAPACITY,?minCapacity);
????}
????ensureExplicitCapacity(minCapacity);
}

private?void?ensureExplicitCapacity(int?minCapacity)?{
????modCount++;
????//?overflow-conscious?code
????if?(minCapacity?-?elementData.length?>?0)
????????grow(minCapacity);
}

private?void?grow(int?minCapacity)?{
????//?overflow-conscious?code
????int?oldCapacity?=?elementData.length;
????int?newCapacity?=?oldCapacity?+?(oldCapacity?>>?1);
????if?(newCapacity?-?minCapacity?0)
????????newCapacity?=?minCapacity;
????if?(newCapacity?-?MAX_ARRAY_SIZE?>?0)
????????newCapacity?=?hugeCapacity(minCapacity);
????//?minCapacity?is?usually?close?to?size,?so?this?is?a?win:
????elementData?=?Arrays.copyOf(elementData,?newCapacity);
}

3. 刪除元素

需要調(diào)用 System.arraycopy() 將 index+1 后面的元素都復(fù)制到 index 位置上,該操作的時間復(fù)雜度為 O(N),可以看出 ArrayList 刪除元素的代價是非常高的。

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;
}

4. Fail-Fast

modCount 用來記錄 ArrayList 結(jié)構(gòu)發(fā)生變化的次數(shù)。結(jié)構(gòu)發(fā)生變化是指添加或者刪除至少一個元素的所有操作,或者是調(diào)整內(nèi)部數(shù)組的大小,僅僅只是設(shè)置元素的值不算結(jié)構(gòu)發(fā)生變化。

在進行序列化或者迭代等操作時,需要比較操作前后 modCount 是否改變,如果改變了需要拋出 ConcurrentModificationException。

private?void?writeObject(java.io.ObjectOutputStream?s)throws?java.io.IOException{
????//?Write?out?element?count,?and?any?hidden?stuff
????int?expectedModCount?=?modCount;
????s.defaultWriteObject();

????//?Write?out?size?as?capacity?for?behavioural?compatibility?with?clone()
????s.writeInt(size);

????//?Write?out?all?elements?in?the?proper?order.
????for?(int?i=0;?i????????s.writeObject(elementData[i]);
????}

????if?(modCount?!=?expectedModCount)?{
????????throw?new?ConcurrentModificationException();
????}
}

5. 序列化

ArrayList 基于數(shù)組實現(xiàn),并且具有動態(tài)擴容特性,因此保存元素的數(shù)組不一定都會被使用,那么就沒必要全部進行序列化。

保存元素的數(shù)組 elementData 使用 transient 修飾,該關(guān)鍵字聲明數(shù)組默認不會被序列化。

transient?Object[]?elementData;?//?non-private?to?simplify?nested?class?access

ArrayList 實現(xiàn)了 writeObject() 和 readObject() 來控制只序列化數(shù)組中有元素填充那部分內(nèi)容。

private?void?readObject(java.io.ObjectInputStream?s)throws?java.io.IOException,?ClassNotFoundException?{
????elementData?=?EMPTY_ELEMENTDATA;

????//?Read?in?size,?and?any?hidden?stuff
????s.defaultReadObject();

????//?Read?in?capacity
????s.readInt();?//?ignored

????if?(size?>?0)?{
????????//?be?like?clone(),?allocate?array?based?upon?size?not?capacity
????????ensureCapacityInternal(size);

????????Object[]?a?=?elementData;
????????//?Read?in?all?elements?in?the?proper?order.
????????for?(int?i=0;?i????????????a[i]?=?s.readObject();
????????}
????}
}
private?void?writeObject(java.io.ObjectOutputStream?s)throws?java.io.IOException{
????//?Write?out?element?count,?and?any?hidden?stuff
????int?expectedModCount?=?modCount;
????s.defaultWriteObject();

????//?Write?out?size?as?capacity?for?behavioural?compatibility?with?clone()
????s.writeInt(size);

????//?Write?out?all?elements?in?the?proper?order.
????for?(int?i=0;?i????????s.writeObject(elementData[i]);
????}

????if?(modCount?!=?expectedModCount)?{
????????throw?new?ConcurrentModificationException();
????}
}

序列化時需要使用 ObjectOutputStream 的 writeObject() 將對象轉(zhuǎn)換為字節(jié)流并輸出。而 writeObject() 方法在傳入的對象存在 writeObject() 的時候會去反射調(diào)用該對象的 writeObject() 來實現(xiàn)序列化。反序列化使用的是 ObjectInputStream 的 readObject() 方法,原理類似。

ArrayList?list?=?new?ArrayList();
ObjectOutputStream?oos?=?new?ObjectOutputStream(new?FileOutputStream(file));
oos.writeObject(list);

Vector

1. 同步

它的實現(xiàn)與 ArrayList 類似,但是使用了 synchronized 進行同步。

public?synchronized?boolean?add(E?e)?{
????modCount++;
????ensureCapacityHelper(elementCount?+?1);
????elementData[elementCount++]?=?e;
????return?true;
}

public?synchronized?E?get(int?index)?{
????if?(index?>=?elementCount)
????????throw?new?ArrayIndexOutOfBoundsException(index);

????return?elementData(index);
}

2. 與 ArrayList 的比較

  • Vector 是同步的,因此開銷就比 ArrayList 要大,訪問速度更慢。最好使用 ArrayList 而不是 Vector,因為同步操作完全可以由程序員自己來控制;

  • Vector 每次擴容請求其大小的 2 倍空間,而 ArrayList 是 1.5 倍。

3. 替代方案

可以使用 Collections.synchronizedList(); 得到一個線程安全的 ArrayList。

List?list?=?new?ArrayList<>();
List?synList?=?Collections.synchronizedList(list);

也可以使用 concurrent 并發(fā)包下的 CopyOnWriteArrayList 類。

List?list?=?new?CopyOnWriteArrayList<>();

CopyOnWriteArrayList

讀寫分離

寫操作在一個復(fù)制的數(shù)組上進行,讀操作還是在原始數(shù)組中進行,讀寫分離,互不影響。

寫操作需要加鎖,防止并發(fā)寫入時導(dǎo)致寫入數(shù)據(jù)丟失。

寫操作結(jié)束之后需要把原始數(shù)組指向新的復(fù)制數(shù)組。

public?boolean?add(E?e)?{
????final?ReentrantLock?lock?=?this.lock;
????lock.lock();
????try?{
????????Object[]?elements?=?getArray();
????????int?len?=?elements.length;
????????Object[]?newElements?=?Arrays.copyOf(elements,?len?+?1);
????????newElements[len]?=?e;
????????setArray(newElements);
????????return?true;
????}?finally?{
????????lock.unlock();
????}
}

final?void?setArray(Object[]?a)?{
????array?=?a;
}
@SuppressWarnings("unchecked")
private?E?get(Object[]?a,?int?index)?{
????return?(E)?a[index];
}

適用場景

CopyOnWriteArrayList 在寫操作的同時允許讀操作,大大提高了讀操作的性能,因此很適合讀多寫少的應(yīng)用場景。

但是 CopyOnWriteArrayList 有其缺陷:

  • 內(nèi)存占用:在寫操作時需要復(fù)制一個新的數(shù)組,使得內(nèi)存占用為原來的兩倍左右;

  • 數(shù)據(jù)不一致:讀操作不能讀取實時性的數(shù)據(jù),因為部分寫操作的數(shù)據(jù)還未同步到讀數(shù)組中。

所以 CopyOnWriteArrayList 不適合內(nèi)存敏感以及對實時性要求很高的場景。

LinkedList

1. 概覽

基于雙向鏈表實現(xiàn),使用 Node 存儲鏈表節(jié)點信息。

private?static?class?Node<E>?{
????E?item;
????Node?next;
????Node?prev;
}

每個鏈表存儲了 first 和 last 指針:

transient?Node?first;transient?Node?last;

2. 與 ArrayList 的比較

  • ArrayList 基于動態(tài)數(shù)組實現(xiàn),LinkedList 基于雙向鏈表實現(xiàn);

  • ArrayList 支持隨機訪問,LinkedList 不支持;

  • LinkedList 在任意位置添加刪除元素更快。

HashMap

為了便于理解,以下源碼分析以 JDK 1.7 為主。

1. 存儲結(jié)構(gòu)

內(nèi)部包含了一個 Entry 類型的數(shù)組 table。

transient?Entry[]?table;

Entry 存儲著鍵值對。它包含了四個字段,從 next 字段我們可以看出 Entry 是一個鏈表。即數(shù)組中的每個位置被當(dāng)成一個桶,一個桶存放一個鏈表。HashMap 使用拉鏈法來解決沖突,同一個鏈表中存放哈希值相同的 Entry。

static?class?Entry<K,V>?implements?Map.Entry<K,V>?{
????final?K?key;
????V?value;
????Entry?next;int?hash;
????Entry(int?h,?K?k,?V?v,?Entry?n)?{
????????value?=?v;
????????next?=?n;
????????key?=?k;
????????hash?=?h;
????}public?final?K?getKey()?{return?key;
????}public?final?V?getValue()?{return?value;
????}public?final?V?setValue(V?newValue)?{
????????V?oldValue?=?value;
????????value?=?newValue;return?oldValue;
????}public?final?boolean?equals(Object?o)?{if?(!(o?instanceof?Map.Entry))return?false;
????????Map.Entry?e?=?(Map.Entry)o;
????????Object?k1?=?getKey();
????????Object?k2?=?e.getKey();if?(k1?==?k2?||?(k1?!=?null?&&?k1.equals(k2)))?{
????????????Object?v1?=?getValue();
????????????Object?v2?=?e.getValue();if?(v1?==?v2?||?(v1?!=?null?&&?v1.equals(v2)))return?true;
????????}return?false;
????}public?final?int?hashCode()?{return?Objects.hashCode(getKey())?^?Objects.hashCode(getValue());
????}public?final?String?toString()?{return?getKey()?+?"="?+?getValue();
????}
}

2. 拉鏈法的工作原理

HashMap?map?=?new?HashMap<>();
map.put("K1",?"V1");
map.put("K2",?"V2");
map.put("K3",?"V3");
  • 新建一個 HashMap,默認大小為 16;

  • 插入 鍵值對,先計算 K1 的 hashCode 為 115,使用除留余數(shù)法得到所在的桶下標(biāo) 115%16=3。

  • 插入 鍵值對,先計算 K2 的 hashCode 為 118,使用除留余數(shù)法得到所在的桶下標(biāo) 118%16=6。

  • 插入 鍵值對,先計算 K3 的 hashCode 為 118,使用除留余數(shù)法得到所在的桶下標(biāo) 118%16=6,插在 前面。

應(yīng)該注意到鏈表的插入是以頭插法方式進行的,例如上面的 不是插在 后面,而是插入在鏈表頭部。

查找需要分成兩步進行:

  • 計算鍵值對所在的桶;

  • 在鏈表上順序查找,時間復(fù)雜度顯然和鏈表的長度成正比。

3. put 操作

public?V?put(K?key,?V?value)?{
????if?(table?==?EMPTY_TABLE)?{
????????inflateTable(threshold);
????}
????//?鍵為?null?單獨處理
????if?(key?==?null)
????????return?putForNullKey(value);
????int?hash?=?hash(key);
????//?確定桶下標(biāo)
????int?i?=?indexFor(hash,?table.length);
????//?先找出是否已經(jīng)存在鍵為?key?的鍵值對,如果存在的話就更新這個鍵值對的值為?value
????for?(Entry?e?=?table[i];?e?!=?null;?e?=?e.next)?{
????????Object?k;if?(e.hash?==?hash?&&?((k?=?e.key)?==?key?||?key.equals(k)))?{
????????????V?oldValue?=?e.value;
????????????e.value?=?value;
????????????e.recordAccess(this);return?oldValue;
????????}
????}
????modCount++;//?插入新鍵值對
????addEntry(hash,?key,?value,?i);return?null;
}

HashMap 允許插入鍵為 null 的鍵值對。但是因為無法調(diào)用 null 的 hashCode() 方法,也就無法確定該鍵值對的桶下標(biāo),只能通過強制指定一個桶下標(biāo)來存放。HashMap 使用第 0 個桶存放鍵為 null 的鍵值對。

private?V?putForNullKey(V?value)?{
????for?(Entry?e?=?table[0];?e?!=?null;?e?=?e.next)?{if?(e.key?==?null)?{
????????????V?oldValue?=?e.value;
????????????e.value?=?value;
????????????e.recordAccess(this);return?oldValue;
????????}
????}
????modCount++;
????addEntry(0,?null,?value,?0);return?null;
}

使用鏈表的頭插法,也就是新的鍵值對插在鏈表的頭部,而不是鏈表的尾部。

void?addEntry(int?hash,?K?key,?V?value,?int?bucketIndex)?{
????if?((size?>=?threshold)?&&?(null?!=?table[bucketIndex]))?{
????????resize(2?*?table.length);
????????hash?=?(null?!=?key)???hash(key)?:?0;
????????bucketIndex?=?indexFor(hash,?table.length);
????}

????createEntry(hash,?key,?value,?bucketIndex);
}

void?createEntry(int?hash,?K?key,?V?value,?int?bucketIndex)?{
????Entry?e?=?table[bucketIndex];//?頭插法,鏈表頭部指向新的鍵值對
????table[bucketIndex]?=?new?Entry<>(hash,?key,?value,?e);
????size++;
}Entry(int?h,?K?k,?V?v,?Entry?n)?{
????value?=?v;
????next?=?n;
????key?=?k;
????hash?=?h;
}

4. 確定桶下標(biāo)

很多操作都需要先確定一個鍵值對所在的桶下標(biāo)。

int?hash?=?hash(key);
int?i?=?indexFor(hash,?table.length);

4.1 計算 hash 值

final?int?hash(Object?k)?{
????int?h?=?hashSeed;
????if?(0?!=?h?&&?k?instanceof?String)?{
????????return?sun.misc.Hashing.stringHash32((String)?k);
????}

????h?^=?k.hashCode();

????//?This?function?ensures?that?hashCodes?that?differ?only?by
????//?constant?multiples?at?each?bit?position?have?a?bounded
????//?number?of?collisions?(approximately?8?at?default?load?factor).
????h?^=?(h?>>>?20)?^?(h?>>>?12);
????return?h?^?(h?>>>?7)?^?(h?>>>?4);
}
public?final?int?hashCode()?{
????return?Objects.hashCode(key)?^?Objects.hashCode(value);
}

4.2 取模

令 x = 1<<4,即 x 為 2 的 4 次方,它具有以下性質(zhì):

x???:?00010000
x-1?:?00001111

令一個數(shù) y 與 x-1 做與運算,可以去除 y 位級表示的第 4 位以上數(shù):

y???????:?10110010
x-1?????:?00001111
y&(x-1)?:?00000010

這個性質(zhì)和 y 對 x 取模效果是一樣的:

y???:?10110010
x???:?00010000
y%x?:?00000010

我們知道,位運算的代價比求模運算小的多,因此在進行這種計算時用位運算的話能帶來更高的性能。

確定桶下標(biāo)的最后一步是將 key 的 hash 值對桶個數(shù)取模:hash%capacity,如果能保證 capacity 為 2 的 n 次方,那么就可以將這個操作轉(zhuǎn)換為位運算。

static?int?indexFor(int?h,?int?length)?{
????return?h?&?(length-1);
}

5. 擴容-基本原理

設(shè) HashMap 的 table 長度為 M,需要存儲的鍵值對數(shù)量為 N,如果哈希函數(shù)滿足均勻性的要求,那么每條鏈表的長度大約為 N/M,因此平均查找次數(shù)的復(fù)雜度為 O(N/M)。

為了讓查找的成本降低,應(yīng)該盡可能使得 N/M 盡可能小,因此需要保證 M 盡可能大,也就是說 table 要盡可能大。HashMap 采用動態(tài)擴容來根據(jù)當(dāng)前的 N 值來調(diào)整 M 值,使得空間效率和時間效率都能得到保證。

和擴容相關(guān)的參數(shù)主要有:capacity、size、threshold 和 load_factor。

參數(shù)含義
capacitytable 的容量大小,默認為 16。需要注意的是 capacity 必須保證為 2 的 n 次方。
size鍵值對數(shù)量。
thresholdsize 的臨界值,當(dāng) size 大于等于 threshold 就必須進行擴容操作。
loadFactor裝載因子,table 能夠使用的比例,threshold = capacity * loadFactor。
static?final?int?DEFAULT_INITIAL_CAPACITY?=?16;

static?final?int?MAXIMUM_CAPACITY?=?1?<30;

static?final?float?DEFAULT_LOAD_FACTOR?=?0.75f;

transient?Entry[]?table;

transient?int?size;

int?threshold;

final?float?loadFactor;

transient?int?modCount;

從下面的添加元素代碼中可以看出,當(dāng)需要擴容時,令 capacity 為原來的兩倍。

void?addEntry(int?hash,?K?key,?V?value,?int?bucketIndex)?{
????Entry?e?=?table[bucketIndex];
????table[bucketIndex]?=?new?Entry<>(hash,?key,?value,?e);if?(size++?>=?threshold)
????????resize(2?*?table.length);
}

擴容使用 resize() 實現(xiàn),需要注意的是,擴容操作同樣需要把 oldTable 的所有鍵值對重新插入 newTable 中,因此這一步是很費時的。

void?resize(int?newCapacity)?{
????Entry[]?oldTable?=?table;
????int?oldCapacity?=?oldTable.length;
????if?(oldCapacity?==?MAXIMUM_CAPACITY)?{
????????threshold?=?Integer.MAX_VALUE;
????????return;
????}
????Entry[]?newTable?=?new?Entry[newCapacity];
????transfer(newTable);
????table?=?newTable;
????threshold?=?(int)(newCapacity?*?loadFactor);
}

void?transfer(Entry[]?newTable)?{
????Entry[]?src?=?table;
????int?newCapacity?=?newTable.length;
????for?(int?j?=?0;?j?????????Entry?e?=?src[j];if?(e?!=?null)?{
????????????src[j]?=?null;do?{
????????????????Entry?next?=?e.next;int?i?=?indexFor(e.hash,?newCapacity);
????????????????e.next?=?newTable[i];
????????????????newTable[i]?=?e;
????????????????e?=?next;
????????????}?while?(e?!=?null);
????????}
????}
}

6. 擴容-重新計算桶下標(biāo)

在進行擴容時,需要把鍵值對重新放到對應(yīng)的桶上。HashMap 使用了一個特殊的機制,可以降低重新計算桶下標(biāo)的操作。

假設(shè)原數(shù)組長度 capacity 為 16,擴容之后 new capacity 為 32:

capacity?????:?00010000
new?capacity?:?00100000

對于一個 Key,

  • 它的哈希值如果在第 5 位上為 0,那么取模得到的結(jié)果和之前一樣;

  • 如果為 1,那么得到的結(jié)果為原來的結(jié)果 +16。

7. 計算數(shù)組容量

HashMap 構(gòu)造函數(shù)允許用戶傳入的容量不是 2 的 n 次方,因為它可以自動地將傳入的容量轉(zhuǎn)換為 2 的 n 次方。

先考慮如何求一個數(shù)的掩碼,對于 10010000,它的掩碼為 11111111,可以使用以下方法得到:

mask?|=?mask?>>?1????11011000
mask?|=?mask?>>?2????11111110
mask?|=?mask?>>?4????11111111

mask+1 是大于原始數(shù)字的最小的 2 的 n 次方。

num?????10010000
mask+1?100000000

以下是 HashMap 中計算數(shù)組容量的代碼:

static?final?int?tableSizeFor(int?cap)?{
????int?n?=?cap?-?1;
????n?|=?n?>>>?1;
????n?|=?n?>>>?2;
????n?|=?n?>>>?4;
????n?|=?n?>>>?8;
????n?|=?n?>>>?16;
????return?(n?0)???1?:?(n?>=?MAXIMUM_CAPACITY)???MAXIMUM_CAPACITY?:?n?+?1;
}

8. 鏈表轉(zhuǎn)紅黑樹

從 JDK 1.8 開始,一個桶存儲的鏈表長度大于 8 時會將鏈表轉(zhuǎn)換為紅黑樹。

9. 與 HashTable 的比較

  • HashTable 使用 synchronized 來進行同步。

  • HashMap 可以插入鍵為 null 的 Entry。

  • HashMap 的迭代器是 fail-fast 迭代器。

  • HashMap 不能保證隨著時間的推移 Map 中的元素次序是不變的。

ConcurrentHashMap

1. 存儲結(jié)構(gòu)

static?final?class?HashEntry<K,V>?{
????final?int?hash;
????final?K?key;
????volatile?V?value;
????volatile?HashEntry?next;
}

ConcurrentHashMap 和 HashMap 實現(xiàn)上類似,最主要的差別是 ConcurrentHashMap 采用了分段鎖(Segment),每個分段鎖維護著幾個桶(HashEntry),多個線程可以同時訪問不同分段鎖上的桶,從而使其并發(fā)度更高(并發(fā)度就是 Segment 的個數(shù))。

Segment 繼承自 ReentrantLock。

static?final?class?Segment<K,V>?extends?ReentrantLock?implements?Serializable?{

????private?static?final?long?serialVersionUID?=?2249069246763182397L;

????static?final?int?MAX_SCAN_RETRIES?=
????????Runtime.getRuntime().availableProcessors()?>?1???64?:?1;

????transient?volatile?HashEntry[]?table;transient?int?count;transient?int?modCount;transient?int?threshold;final?float?loadFactor;
}final?Segment[]?segments;

默認的并發(fā)級別為 16,也就是說默認創(chuàng)建 16 個 Segment。

static?final?int?DEFAULT_CONCURRENCY_LEVEL?=?16;

2. size 操作

每個 Segment 維護了一個 count 變量來統(tǒng)計該 Segment 中的鍵值對個數(shù)。

/**
?*?The?number?of?elements.?Accessed?only?either?within?locks
?*?or?among?other?volatile?reads?that?maintain?visibility.
?*/
transient?int?count;

在執(zhí)行 size 操作時,需要遍歷所有 Segment 然后把 count 累計起來。

ConcurrentHashMap 在執(zhí)行 size 操作時先嘗試不加鎖,如果連續(xù)兩次不加鎖操作得到的結(jié)果一致,那么可以認為這個結(jié)果是正確的。

嘗試次數(shù)使用 RETRIES_BEFORE_LOCK 定義,該值為 2,retries 初始值為 -1,因此嘗試次數(shù)為 3。

如果嘗試的次數(shù)超過 3 次,就需要對每個 Segment 加鎖。

/**
?*?Number?of?unsynchronized?retries?in?size?and?containsValue
?*?methods?before?resorting?to?locking.?This?is?used?to?avoid
?*?unbounded?retries?if?tables?undergo?continuous?modification
?*?which?would?make?it?impossible?to?obtain?an?accurate?result.
?*/
static?final?int?RETRIES_BEFORE_LOCK?=?2;

public?int?size()?{
????//?Try?a?few?times?to?get?accurate?count.?On?failure?due?to
????//?continuous?async?changes?in?table,?resort?to?locking.
????final?Segment[]?segments?=?this.segments;int?size;boolean?overflow;?//?true?if?size?overflows?32?bitslong?sum;?????????//?sum?of?modCountslong?last?=?0L;???//?previous?sumint?retries?=?-1;?//?first?iteration?isn't?retrytry?{for?(;;)?{//?超過嘗試次數(shù),則對每個?Segment?加鎖if?(retries++?==?RETRIES_BEFORE_LOCK)?{for?(int?j?=?0;?j?????????????????????ensureSegment(j).lock();?//?force?creation
????????????}
????????????sum?=?0L;
????????????size?=?0;
????????????overflow?=?false;for?(int?j?=?0;?j?????????????????Segment?seg?=?segmentAt(segments,?j);if?(seg?!=?null)?{
????????????????????sum?+=?seg.modCount;int?c?=?seg.count;if?(c?0?||?(size?+=?c)?0)
????????????????????????overflow?=?true;
????????????????}
????????????}//?連續(xù)兩次得到的結(jié)果一致,則認為這個結(jié)果是正確的if?(sum?==?last)break;
????????????last?=?sum;
????????}
????}?finally?{if?(retries?>?RETRIES_BEFORE_LOCK)?{for?(int?j?=?0;?j?????????????????segmentAt(segments,?j).unlock();
????????}
????}return?overflow???Integer.MAX_VALUE?:?size;
}

3. JDK 1.8 的改動

JDK 1.7 使用分段鎖機制來實現(xiàn)并發(fā)更新操作,核心類為 Segment,它繼承自重入鎖 ReentrantLock,并發(fā)度與 Segment 數(shù)量相等。

JDK 1.8 使用了 CAS 操作來支持更高的并發(fā)度,在 CAS 操作失敗時使用內(nèi)置鎖 synchronized。

并且 JDK 1.8 的實現(xiàn)也在鏈表過長時會轉(zhuǎn)換為紅黑樹。

LinkedHashMap

存儲結(jié)構(gòu)

繼承自 HashMap,因此具有和 HashMap 一樣的快速查找特性。

public?class?LinkedHashMap<K,V>?extends?HashMap<K,V>?implements?Map<K,V>

內(nèi)部維護了一個雙向鏈表,用來維護插入順序或者 LRU 順序。

/**
?*?The?head?(eldest)?of?the?doubly?linked?list.
?*/
transient?LinkedHashMap.Entry?head;/**
?*?The?tail?(youngest)?of?the?doubly?linked?list.
?*/transient?LinkedHashMap.Entry?tail;

accessOrder 決定了順序,默認為 false,此時維護的是插入順序。

final?boolean?accessOrder;

LinkedHashMap 最重要的是以下用于維護順序的函數(shù),它們會在 put、get 等方法中調(diào)用。

void?afterNodeAccess(Node?p)?{?}
void?afterNodeInsertion(boolean?evict)?{?}

afterNodeAccess()

當(dāng)一個節(jié)點被訪問時,如果 accessOrder 為 true,則會將該節(jié)點移到鏈表尾部。也就是說指定為 LRU 順序之后,在每次訪問一個節(jié)點時,會將這個節(jié)點移到鏈表尾部,保證鏈表尾部是最近訪問的節(jié)點,那么鏈表首部就是最近最久未使用的節(jié)點。

void?afterNodeAccess(Node?e)?{?//?move?node?to?last
????LinkedHashMap.Entry?last;if?(accessOrder?&&?(last?=?tail)?!=?e)?{
????????LinkedHashMap.Entry?p?=
????????????(LinkedHashMap.Entry)e,?b?=?p.before,?a?=?p.after;
????????p.after?=?null;if?(b?==?null)
????????????head?=?a;else
????????????b.after?=?a;if?(a?!=?null)
????????????a.before?=?b;else
????????????last?=?b;if?(last?==?null)
????????????head?=?p;else?{
????????????p.before?=?last;
????????????last.after?=?p;
????????}
????????tail?=?p;
????????++modCount;
????}
}

afterNodeInsertion()

在 put 等操作之后執(zhí)行,當(dāng) removeEldestEntry() 方法返回 true 時會移除最晚的節(jié)點,也就是鏈表首部節(jié)點 first。

evict 只有在構(gòu)建 Map 的時候才為 false,在這里為 true。

void?afterNodeInsertion(boolean?evict)?{?//?possibly?remove?eldest
????LinkedHashMap.Entry?first;if?(evict?&&?(first?=?head)?!=?null?&&?removeEldestEntry(first))?{
????????K?key?=?first.key;
????????removeNode(hash(key),?key,?null,?false,?true);
????}
}

removeEldestEntry() 默認為 false,如果需要讓它為 true,需要繼承 LinkedHashMap 并且覆蓋這個方法的實現(xiàn),這在實現(xiàn) LRU 的緩存中特別有用,通過移除最近最久未使用的節(jié)點,從而保證緩存空間足夠,并且緩存的數(shù)據(jù)都是熱點數(shù)據(jù)。

protected?boolean?removeEldestEntry(Map.Entry?eldest)?{
????return?false;
}

LRU 緩存

以下是使用 LinkedHashMap 實現(xiàn)的一個 LRU 緩存:

  • 設(shè)定最大緩存空間 MAX_ENTRIES ?為 3;

  • 使用 LinkedHashMap 的構(gòu)造函數(shù)將 accessOrder 設(shè)置為 true,開啟 LRU 順序;

  • 覆蓋 removeEldestEntry() 方法實現(xiàn),在節(jié)點多于 MAX_ENTRIES 就會將最近最久未使用的數(shù)據(jù)移除。

class?LRUCache<K,?V>?extends?LinkedHashMap<K,?V>?{
????private?static?final?int?MAX_ENTRIES?=?3;

????protected?boolean?removeEldestEntry(Map.Entry?eldest)?{
????????return?size()?>?MAX_ENTRIES;
????}

????LRUCache()?{
????????super(MAX_ENTRIES,?0.75f,?true);
????}
}
public?static?void?main(String[]?args)?{
????LRUCache?cache?=?new?LRUCache<>();
????cache.put(1,?"a");
????cache.put(2,?"b");
????cache.put(3,?"c");
????cache.get(1);
????cache.put(4,?"d");
????System.out.println(cache.keySet());
}[3,?1,?4]

WeakHashMap

存儲結(jié)構(gòu)

WeakHashMap 的 Entry 繼承自 WeakReference,被 WeakReference 關(guān)聯(lián)的對象在下一次垃圾回收時會被回收。

WeakHashMap 主要用來實現(xiàn)緩存,通過使用 WeakHashMap 來引用緩存對象,由 JVM 對這部分緩存進行回收。

private?static?class?Entry<K,V>?extends?WeakReference<Object>?implements?Map.Entry<K,V>

ConcurrentCache

Tomcat 中的 ConcurrentCache 使用了 WeakHashMap 來實現(xiàn)緩存功能。

ConcurrentCache 采取的是分代緩存:

  • 經(jīng)常使用的對象放入 eden 中,eden 使用 ConcurrentHashMap 實現(xiàn),不用擔(dān)心會被回收(伊甸園);

  • 不常用的對象放入 longterm,longterm 使用 WeakHashMap 實現(xiàn),這些老對象會被垃圾收集器回收。

  • 當(dāng)調(diào)用 ?get() 方法時,會先從 eden 區(qū)獲取,如果沒有找到的話再到 longterm 獲取,當(dāng)從 longterm 獲取到就把對象放入 eden 中,從而保證經(jīng)常被訪問的節(jié)點不容易被回收。

  • 當(dāng)調(diào)用 put() 方法時,如果 eden 的大小超過了 size,那么就將 eden 中的所有對象都放入 longterm 中,利用虛擬機回收掉一部分不經(jīng)常使用的對象。

public?final?class?ConcurrentCache<K,?V>?{

????private?final?int?size;

????private?final?Map?eden;private?final?Map?longterm;public?ConcurrentCache(int?size)?{this.size?=?size;this.eden?=?new?ConcurrentHashMap<>(size);this.longterm?=?new?WeakHashMap<>(size);
????}public?V?get(K?k)?{
????????V?v?=?this.eden.get(k);if?(v?==?null)?{
????????????v?=?this.longterm.get(k);if?(v?!=?null)this.eden.put(k,?v);
????????}return?v;
????}public?void?put(K?k,?V?v)?{if?(this.eden.size()?>=?size)?{this.longterm.putAll(this.eden);this.eden.clear();
????????}this.eden.put(k,?v);
????}
}

參考資料

  • Eckel B. Java 編程思想 [M]. 機械工業(yè)出版社, 2002.

  • Java Collection Framework

  • Iterator 模式

  • Java 8 系列之重新認識 HashMap

  • What is difference between HashMap and Hashtable in Java?

  • Java 集合之 HashMap

  • The principle of ConcurrentHashMap analysis

  • 探索 ConcurrentHashMap 高并發(fā)性的實現(xiàn)機制

  • HashMap 相關(guān)面試題及其解答

  • Java 集合細節(jié)(二):asList 的缺陷

  • Java Collection Framework – The LinkedList Class

其它優(yōu)質(zhì)文章請見后臺公眾號菜單

【191101】Java第一期資源

【191110】Java第二期資源

【191117】Java第三期資源

【191124】Java第四期資源

總結(jié)

以上是生活随笔為你收集整理的java 容器_java容器考点总结和源码剖析!!!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

久久久国产精品视频 | 992tv在线观看 | 337p日本欧洲亚洲大胆裸体艺术 | 日本在线观看一区二区 | 国产精品99久久久久 | 日韩免费观看一区二区 | www毛片com| 国产亚洲精品免费 | 久久国色夜色精品国产 | 久久精品亚洲精品国产欧美 | 久草在线免 | 国产精品激情在线观看 | 日韩中文久久 | 精品国产一区二区三区在线观看 | 日韩高清一 | 久久成人高清 | 亚洲成人资源在线观看 | 久久视频在线视频 | 欧亚日韩精品一区二区在线 | av三级在线播放 | 黄色在线观看免费 | av成人免费观看 | 丝袜美女视频网站 | 婷婷丁香综合 | 亚洲成人午夜av | 在线色吧 | 97在线精品国自产拍中文 | 丁香九月激情 | 亚洲jizzjizz日本少妇 | 久久久久久久久久电影 | 97电影在线看视频 | 国产精品久久久久影视 | 97在线视频免费看 | 国产 一区二区三区 在线 | 成人免费色 | 伊人干综合| 国产成人精品综合久久久 | 国产美腿白丝袜足在线av | 黄色小说免费在线观看 | 日本久久精品 | 久久久久久综合网天天 | 国产精品婷婷午夜在线观看 | 日韩精品短视频 | 深爱激情站 | 亚洲网站在线看 | 91丨porny丨九色 | a天堂免费| 国产成人精品久久亚洲高清不卡 | 日批视频国产 | 免费av 在线 | 又黄又爽的免费高潮视频 | 操操碰| 五月天精品视频 | 日韩欧美精品一区二区三区经典 | 天天色 天天 | 欧美视频www | 国产亚洲精品中文字幕 | 五月天激情视频在线观看 | 久久国产精品99久久久久久老狼 | 天天操综 | 日韩中文字幕电影 | 黄色一集片 | 国产精品青青 | 日韩欧美xxxx| 亚洲国产字幕 | 国产精品欧美久久久久无广告 | a精品视频 | 91chinese在线 | 91麻豆精品国产自产在线游戏 | 日韩av电影免费在线观看 | www.69xx| 国产不卡免费 | 亚洲爽爽网 | 亚洲成人精品国产 | 丁香激情婷婷 | 天天操操 | 久久美女视频 | av一级片 | 成人黄色国产 | 国产精品久久久久久久久久三级 | 久久观看 | 亚洲欧美成人综合 | 香蕉97视频观看在线观看 | 日韩国产精品久久久久久亚洲 | 久草精品视频在线看网站免费 | 91精品国产三级a在线观看 | 狠狠综合网 | 国产视频不卡一区 | 亚洲日韩欧美一区二区在线 | 国产一及片 | 九九爱免费视频在线观看 | 在线免费看片 | 99久久精品日本一区二区免费 | 麻豆视频入口 | 婷婷六月色 | 最近中文字幕在线 | 99久久激情 | 国产美女精品久久久 | 久久国产一区二区三区 | 天天插天天爽 | 国产精品99久久久久人中文网介绍 | 99久免费精品视频在线观看 | 五月天婷婷丁香花 | 最近中文字幕免费观看 | 激情综合网五月 | 久久久久人人 | 中文国产字幕在线观看 | 久久黄色片 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 在线免费观看的av网站 | 91视视频在线直接观看在线看网页在线看 | 偷拍久久久 | 超碰人人国产 | 国产96精品| 国内精品久久久久久久 | 黄色片网站大全 | 成人综合免费 | 六月婷婷久香在线视频 | 91插插视频 | 免费看黄在线观看 | 日本精品久久久久 | 午夜精品一区二区三区在线视频 | 99视频国产在线 | 91视频大全| 国产亚洲婷婷 | 日日夜夜精品视频天天综合网 | 狠狠操操网 | 国产精品第2页 | www.五月天婷婷 | 五月婷婷操 | 国产很黄很色的视频 | 99免费看片 | 国产精品综合久久 | 操处女逼| 国产aa免费视频 | 波多野结衣久久精品 | 欧美国产不卡 | 91麻豆精品国产午夜天堂 | 久久国产日韩 | 久久精品电影 | 久久成人欧美 | 日韩av不卡在线观看 | 人人干在线 | 99精品国产在热久久下载 | 亚洲欧美视频网站 | 欧美一级特黄aaaaaa大片在线观看 | 欧美激情第十页 | 日韩动态视频 | 国产区免费在线 | 成人国产一区 | 免费久久久久久 | 亚洲乱亚洲乱亚洲 | 久久三级视频 | 亚州精品在线视频 | 91精品国产一区二区三区 | 992tv在线成人免费观看 | 美女一区网站 | 国产手机在线视频 | 91成人精品国产刺激国语对白 | 麻豆影视网 | 久久精品国产精品亚洲 | 日韩一级片网址 | 91精品久久久久久综合乱菊 | 成年人免费av网站 | 五月天婷亚洲天综合网精品偷 | 狠狠狠狠狠狠 | 伊人婷婷激情 | 日本精品一区二区 | 新版资源中文在线观看 | 久久久久亚洲精品国产 | 九九热免费视频在线观看 | 91免费高清 | 又长又大又黑又粗欧美 | 欧美另类69| 中文在线资源 | 亚洲成熟女人毛片在线 | 欧美日韩国产亚洲乱码字幕 | 深爱五月网| www夜夜操 | 四虎成人精品在永久免费 | 免费中文字幕在线观看 | 亚洲特级毛片 | 欧美色婷婷 | 欧美淫视频 | 国产高清成人 | 国产精品99久久久久久宅男 | 麻豆视频免费看 | 99精品视频在线看 | 在线播放av网址 | 色播99 | 激情综合网婷婷 | 中文字幕精品在线 | 久久国产精品久久精品国产演员表 | 天天干天天操天天搞 | 国产精品中文字幕在线观看 | 在线观看www. | 久久伊99综合婷婷久久伊 | 高清不卡一区二区在线 | 在线观看视频免费播放 | 黄色成人小视频 | 99久久激情| 亚洲精品在线观 | 在线观看网站你懂的 | 中文字幕日韩一区二区三区不卡 | 国产麻豆果冻传媒在线观看 | 亚洲天堂免费视频 | 精品乱码一区二区三四区 | 久久精品欧美一区二区三区麻豆 | 五月天免费网站 | 在线免费观看国产黄色 | 青青草在久久免费久久免费 | 亚洲成av人片一区二区梦乃 | av播放在线| 国产日韩欧美中文 | 精品国产电影 | 在线观看视频你懂的 | 久久99热精品这里久久精品 | 国产伦精品一区二区三区免费 | 91福利影院在线观看 | 国产尤物一区二区三区 | 中文资源在线播放 | 日本一区二区免费在线观看 | 激情婷婷六月 | 亚洲一级片 | 成全在线视频免费观看 | 久久久麻豆精品一区二区 | 成年人在线免费视频观看 | 国产精品美女免费视频 | 性日韩欧美在线视频 | 九九视频网 | 精品产品国产在线不卡 | 国内精品久久久久久久久久久久 | 亚洲精品免费在线视频 | 人人插人人插 | 999精品| 中文理论片 | 又色又爽又黄高潮的免费视频 | 免费观看性生活大片 | 久久久.com| 欧美福利视频一区 | 99热在线看| 免费在线成人 | 一级片免费在线 | 成年人视频在线观看免费 | 天天激情站 | 美女在线免费观看视频 | 欧美精品久久99 | 国产99久久久久久免费看 | 亚洲成av人片一区二区梦乃 | 成人黄色片免费 | 丝袜美腿一区 | 尤物97国产精品久久精品国产 | 五月婷婷六月丁香 | 免费观看一区二区三区视频 | 色综合中文字幕 | 一区二区三区精品在线视频 | 国产成人av电影 | 色综合久久66 | 麻豆精品传媒视频 | 日韩视频欧美视频 | 国产日韩欧美在线影视 | 免费看黄20分钟 | 九九精品久久 | 91福利试看 | 91aaa在线观看 | 欧美日韩一区二区免费在线观看 | 福利一区二区三区四区 | 国产在线国产 | 91丨九色丨国产在线 | 色婷婷激情电影 | 欧美日韩亚洲国产一区 | 国产91精品在线播放 | 97成人精品 | 亚州视频在线 | 欧美不卡视频在线 | 深爱激情亚洲 | 中文字幕在线日本 | 亚洲国产精品成人va在线观看 | 国产精品区二区三区日本 | 国产高清av免费在线观看 | 国产精品国产精品 | 欧美性生爱 | 在线观看国产日韩 | 97电院网手机版 | 欧美一级片免费播放 | 91麻豆文化传媒在线观看 | 午夜精品久久久久 | 免费特级黄毛片 | 中文字幕专区高清在线观看 | 欧美在线free | 在线视频一区二区 | 日韩在线观看一区二区三区 | 国产免费一区二区三区最新 | 亚洲欧美日韩国产精品一区午夜 | 亚洲精品视频在线观看免费视频 | 在线免费av播放 | 成人在线观看影院 | 99久久成人 | 久久久久久久久久亚洲精品 | 99久久精品费精品 | 激情一区二区三区欧美 | 午夜黄色一级片 | 国产亚洲免费观看 | av在线精品 | 国产v视频 | av网址aaa| 在线精品视频免费播放 | 久久天堂亚洲 | 久久99热精品这里久久精品 | 在线国产视频 | 中文字幕在线观看三区 | 婷婷激情av| 伊人网综合在线观看 | 国产成人福利在线观看 | 最近中文字幕高清字幕在线视频 | 欧美精品久久 | 国产一区私人高清影院 | 国产精品视频最多的网站 | 亚洲午夜精品电影 | 欧美激情视频一区二区三区免费 | 久艹在线播放 | 香蕉视频网站在线观看 | 精品9999| 欧美激情另类文学 | www.av免费| 婷婷丁香七月 | 国产精品一级在线 | 欧美日韩免费观看一区=区三区 | 色全色在线资源网 | 国产欧美精品一区二区三区四区 | 久久精品视频4 | 99免费在线视频观看 | www免费网站在线观看 | 波多野结衣在线观看一区二区三区 | 国产高清在线视频 | 亚洲永久精品在线 | 激情综合啪| 精品视频久久 | 亚洲国产人午在线一二区 | 成人免费在线看片 | 看片网站黄 | 麻豆传媒一区二区 | 精品一二三区 | 欧美成人久久 | 91高清视频在线 | 欧美极品一区二区三区 | 中文字幕观看视频 | 免费成人在线网站 | av在线免费观看不卡 | 久久综合久久88 | 美女在线观看网站 | 久九视频 | 欧美性粗大hdvideo | 中文字幕91 | 久久a v视频 | 婷婷av综合 | 欧美一级免费高清 | 亚洲一区网 | 亚洲激情视频 | 日韩免费一区二区在线观看 | 91精品国产乱码久久桃 | 成人小视频在线观看免费 | 成人毛片100免费观看 | 国产一级免费片 | 久久久福利 | 97视频在线观看成人 | 五月天六月婷 | 成人精品99 | 日操干| 色综合天天视频在线观看 | 中文字幕日韩精品有码视频 | 亚洲精品小区久久久久久 | 亚洲欧美成人综合 | 天天综合成人 | 五月天精品视频 | 米奇四色影视 | 五月婷激情 | 高清av免费一区中文字幕 | 96视频免费在线观看 | 亚洲专区免费观看 | www.天天成人国产电影 | a午夜在线 | 国产在线一线 | 三日本三级少妇三级99 | 亚州视频在线 | 国产精品高清在线观看 | 国产亚洲精品xxoo | 国产精品初高中精品久久 | 中文字幕一区二区三区四区久久 | 天天摸天天操天天爽 | 婷婷色综合色 | 国产精品3区| 国产精品久久久久免费 | 蜜臀久久99精品久久久无需会员 | 黄色网在线播放 | av在线免费观看不卡 | 亚洲成人av电影在线 | 国产精品久久毛片 | 日韩av免费网站 | 午夜狠狠干 | 亚洲精品一区二区在线观看 | 免费av网址大全 | 中文一区二区三区在线观看 | 国产精品一区二区av日韩在线 | 丁香婷婷在线观看 | 中文字幕在线成人 | 久久精品视频4 | 这里只有精品视频在线观看 | 中文字幕免费高清av | 成人毛片一区 | 粉嫩av一区二区三区四区 | 国产亚洲婷婷免费 | 免费一级片视频 | 国产99久久久久久免费看 | 国产成人精品一区二 | 超碰97人人射妻 | 久久免费福利 | 国产成人精品一区二区三区福利 | 国产精品1区2区在线观看 | 亚洲最新av在线网址 | 国产精品三级视频 | 成人免费观看在线视频 | 国产欧美三级 | 久久99国产综合精品免费 | 免费三及片| av在线等 | 亚洲 综合 精品 | 中文字幕日韩在线播放 | 国产a视频免费观看 | 久草成人在线 | 99色在线| 国产精品伦一区二区三区视频 | 国产精品99免费看 | 欧美福利在线播放 | 国产一区二区三区视频在线 | 久久午夜视频 | 国产精品毛片一区二区在线看 | 91热在线 | 在线观看理论 | 超碰97人人干 | 天天看天天干天天操 | 狠狠操狠狠干天天操 | 久久午夜免费视频 | 国产福利在线免费 | 91桃色国产在线播放 | 国产精品理论在线观看 | 亚洲国产精品久久久久久 | 欧日韩在线视频 | 久久午夜精品 | 黄色精品免费 | 国产精品毛片一区二区三区 | 日本黄色黄网站 | 国产一区二区三区 在线 | 国产香蕉久久精品综合网 | 狠狠久久婷婷 | 天天操狠狠操 | 人人要人人澡人人爽人人dvd | 手机在线看永久av片免费 | 日日婷婷夜日日天干 | 最新国产精品久久精品 | 久草在线视频首页 | 超碰97av在线| 日韩av一区在线观看 | 超碰成人网 | www.天天射.com| 99亚洲精品在线 | 国产高清不卡av | 欧美日韩精品在线观看 | 精品国产资源 | 欧美激情精品久久久久久免费印度 | 婷婷久月 | 日本夜夜草视频网站 | 欧美日韩国产精品爽爽 | 久久在线一区 | 97精产国品一二三产区在线 | 欧美日韩中文在线视频 | 一区二区三区日韩精品 | 午夜在线国产 | www视频免费在线观看 | 9在线观看免费高清完整版在线观看明 | 99久久久久 | 中文字幕字幕中文 | 日韩一二区在线观看 | 伊人久久精品久久亚洲一区 | 精品国产一区二区三区不卡 | 久久久精品国产免费观看一区二区 | 亚洲国产wwwccc36天堂 | 9797在线看片亚洲精品 | 99色在线视频 | 欧美一级性视频 | 在线观看 亚洲 | 97超碰国产在线 | 欧美性粗大hdvideo | 亚洲人成网站精品片在线观看 | 日本夜夜草视频网站 | 国产精品一区二区三区在线 | 日韩欧美xxxx | 人人玩人人添人人澡超碰 | 二区视频在线 | 亚洲天天干 | 麻豆av一区二区三区在线观看 | 一区二区三区在线免费观看视频 | 欧美狠狠色 | 精品国产伦一区二区三区免费 | 亚洲视频综合 | 国外av在线 | 亚洲97在线| 国产精品av久久久久久无 | 一级精品视频在线观看宜春院 | 久久国产精品影片 | 久久久久久电影 | 国产91亚洲精品 | 色多多污污在线观看 | 2021国产精品 | 99精品久久久久久久久久综合 | 激情xxxx | 五月天天色 | 成人影片在线免费观看 | 国产精品久久久久久久久久免费看 | 激情图片区 | 成人亚洲免费 | 国产露脸91国语对白 | 亚洲国产免费 | 激情丁香 | 久草电影在线 | 日本在线观看一区二区 | 国产精品高清免费在线观看 | 日本一区二区高清不卡 | 天天综合久久综合 | 中文字幕免费高 | 国产精品一区二区在线免费观看 | 日韩h在线观看 | 国产伦精品一区二区三区高清 | 可以免费观看的av片 | 国产一区在线视频 | 日日碰狠狠躁久久躁综合网 | 久久人人添人人爽添人人88v | 亚洲最新视频在线 | 91精品免费 | 日韩在线观看小视频 | 中文国产字幕 | 黄色小网站在线观看 | 精品 一区 在线 | 一级片黄色片网站 | 天天看天天干 | 在线 国产 亚洲 欧美 | 日韩欧美网址 | 午夜视频久久久 | 在线观看一级 | 久久精品一区八戒影视 | 五月婷婷视频在线 | a级国产乱理伦片在线观看 亚洲3级 | 日日操狠狠干 | 91亚洲狠狠婷婷综合久久久 | 免费成人结看片 | 亚洲精品视频在线观看免费 | 日韩高清在线一区二区三区 | 91免费高清在线观看 | 亚洲视频免费在线看 | 四虎成人免费观看 | 免费黄色网址网站 | 中文字幕一区二区三区在线播放 | 美女一二三区 | 日韩久久精品一区二区 | 日韩国产欧美在线视频 | 中文字幕久久网 | 女人魂免费观看 | 久久精品一二三区 | 国产中文字幕视频 | 天天操天天干天天玩 | 青青草国产精品 | 国产精品第二页 | 2019天天干天天色 | 亚洲成aⅴ人在线观看 | 久久久国产精品一区二区三区 | 制服丝袜亚洲 | 狠狠天天 | 久久久精品综合 | 亚洲国产精品女人久久久 | 久久69精品 | 91精品视频免费 | 久久久久成人精品 | 久久看片 | 又黄又爽免费视频 | 91在线一区二区 | 久久激情小说 | 国产精品久久久av久久久 | 久久尤物电影视频在线观看 | 成人亚洲综合 | 最新中文字幕视频 | 精品国产电影 | 亚洲黄色免费在线看 | 成人啊 v| 国产视频一区在线 | 欧美a免费 | 免费观看一级特黄欧美大片 | 911久久香蕉国产线看观看 | 四川妇女搡bbbb搡bbbb搡 | 五月婷婷综合在线观看 | 久草视频免费在线观看 | 国产精品国产自产拍高清av | 久久国产精品久久精品 | 亚洲乱码久久久 | 在线欧美小视频 | 中文字幕你懂的 | 国产综合激情 | 国产精品九九九九九九 | 五月天视频网 | 亚洲码国产日韩欧美高潮在线播放 | 久久歪歪| 久久国产高清 | 国产伦精品一区二区三区在线 | 免费在线观看av网站 | 美女亚洲精品 | 欧美黑人性猛交 | 精品久久1 | 久久99精品久久久久蜜臀 | 亚洲一区二区三区毛片 | 中文字幕九九 | 日韩精品免费一线在线观看 | 国产成人精品亚洲 | 中文字幕成人在线 | 在线日本v二区不卡 | 天天综合网久久综合网 | 日韩高清 一区 | 黄色小网站在线观看 | 精品综合久久久 | 欧美成人在线网站 | 久亚洲 | 国产精品3| 手机在线黄色网址 | 在线观看免费91 | 国产精品免费不 | 美女视频网 | 欧美日一级片 | 在线视频a | 日韩色高清 | 在线观看国产麻豆 | 国产精品福利视频 | 亚洲高清在线精品 | 激情婷婷综合网 | 97日日碰人人模人人澡分享吧 | 国产99久久久国产精品免费看 | 国产理伦在线 | 亚洲欧美在线综合 | av五月婷婷 | 最新中文字幕视频 | 成人久久综合 | 日本中文字幕网站 | 天天干天天干天天色 | 国产精品第一视频 | 操操操日日日干干干 | 精品a级片 | 国产亚洲一级高清 | 欧美日韩国产精品一区二区三区 | 97免费视频在线 | 日本久久中文字幕 | 91精品国产亚洲 | 亚洲电影一级黄 | 右手影院亚洲欧美 | 婷婷干五月 | 91麻豆看国产在线紧急地址 | 日韩av中文字幕在线免费观看 | 99久久www| 日本韩国中文字幕 | 国产视频资源在线观看 | 久9在线 | 欧美精品久久久久久久久老牛影院 | 高清国产午夜精品久久久久久 | 日女人电影 | 欧美日韩亚洲国产一区 | 亚洲精品美女久久17c | 又色又爽又黄高潮的免费视频 | 日本久久久精品视频 | 久久免费a| 久久艹艹 | 日韩电影在线观看一区二区 | 四虎在线观看 | 中文字幕美女免费在线 | 日韩成人黄色 | 亚洲综合视频在线 | 久久久www成人免费毛片麻豆 | 天天婷婷| 激情网五月天 | 天天操天天舔天天干 | 国产日韩精品久久 | 亚洲激情六月 | 在线观看亚洲电影 | 91色九色 | 正在播放 国产精品 | 日韩色综合网 | 成人性生爱a∨ | 久草剧场| 免费能看的黄色片 | 国产成人亚洲在线电影 | 国产成人三级三级三级97 | 欧美欧美 | 国产精品男女视频 | 91一区啪爱嗯打偷拍欧美 | 91视频麻豆视频 | 91专区在线观看 | 手机在线小视频 | 国产精品午夜免费福利视频 | 亚洲欧美视频一区二区三区 | 国产精品成人一区 | 91视频啊啊啊 | 欧美怡红院视频 | 日本精品一区二区三区在线播放视频 | 国内精品中文字幕 | 日韩在线小视频 | 免费黄色看片 | 九九免费精品视频在线观看 | 在线日本看片免费人成视久网 | 亚洲成熟女人毛片在线 | 日韩天天综合 | 五月天婷婷视频 | 久久99热这里只有精品 | 国产精品二区三区 | 一区二区三区在线免费 | 天天操福利视频 | 国产夫妻自拍av | 五月天com| 久久兔费看a级 | 国产精品不卡在线播放 | 国产高清免费观看 | 天天干天天插 | 麻豆av电影| 一区二区三区电影大全 | 成人免费色 | 国产精品专区在线 | 久久午夜视频 | 色先锋资源网 | 久久精品国产亚洲精品 | 久久综合欧美精品亚洲一区 | 99精品欧美一区二区三区 | av网站免费线看精品 | 97色在线观看 | 视频91在线 | 日韩,精品电影 | 一区二区三区免费在线播放 | 色丁香久久| 波多野结衣一区二区三区中文字幕 | 成人羞羞视频在线观看免费 | 毛片永久新网址首页 | 亚洲欧美日韩一区二区三区在线观看 | 久久国产免费视频 | 人人爽人人片 | 日韩影视在线 | 在线观看视频亚洲 | 午夜婷婷在线播放 | 国产精品免费久久 | 友田真希x88av | 二区视频在线 | 久久久久久久国产精品 | 亚洲人成在线电影 | 国产精品久久久久久一二三四五 | 国产999精品久久久久久绿帽 | 69夜色精品国产69乱 | 亚洲免费观看视频 | 欧美日韩国产一区二区在线观看 | 婷婷丁香七月 | 免费亚洲成人 | 四虎影院在线观看av | 91精品国产综合久久婷婷香蕉 | 天天操天天干天天 | 欧美福利视频一区 | av 在线观看 | 日韩欧美高清不卡 | 国产999精品久久久久久麻豆 | 国产精品系列在线播放 | 久久免费成人精品视频 | 欧美日韩国产在线精品 | 欧美精品国产综合久久 | 久久天堂亚洲 | 91影视成人 | 麻豆播放| 国产999精品久久久久久 | 粉嫩一区二区三区粉嫩91 | 在线看日韩 | 人人爽人人爽人人 | av片无限看| 九九热免费在线视频 | 亚洲国产中文字幕在线观看 | 午夜影院一级片 | 精品一区电影 | 99久久www | 日韩午夜大片 | 免费视频网 | 亚洲精品 在线视频 | 最近更新的中文字幕 | 天天插伊人 | 欧美成年人在线视频 | 免费看成人片 | 婷婷精品国产一区二区三区日韩 | 精品国产视频一区 | 国产色网 | 久久人人爽人人爽人人片av软件 | 精品中文字幕在线 | 国色天香在线 | 91九色蝌蚪视频在线 | 国产精品久久久久久久久久久久 | 国产成人精品久久二区二区 | 久久久久亚洲国产 | av成人动漫在线观看 | 国产无套视频 | 正在播放国产一区二区 | 日韩丝袜 | 欧美日韩视频在线观看免费 | 国产免费一区二区三区网站免费 | 精品久久1 | 91在线色 | 天天拍天天操 | 97超碰中文字幕 | 亚洲国产精品久久久久婷婷884 | 香蕉视频在线观看免费 | 国产一级免费观看 | 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 久久视频在线观看 | 久久夜夜爽 | 免费av的网站 | 欧美在线视频第一页 | 天天干天天射天天爽 | 国产明星视频三级a三级点| 最近最新中文字幕视频 | 欧美性色网站 | www久久精品 | 久艹在线播放 | 久久9999久久免费精品国产 | 99免费在线观看 | 亚洲精品久久久久www | 精品国产综合区久久久久久 | 波多野结衣在线视频免费观看 | 午夜少妇一区二区三区 | 国产理论片在线观看 | 日韩黄色免费看 | 天天看天天干 | 国产综合在线观看视频 | 婷婷九九 | 日韩欧美高清一区二区三区 | 视频一区视频二区在线观看 | 五月天综合激情 | 国产欧美日韩精品一区二区免费 | 亚洲欧美一区二区三区孕妇写真 | 亚洲午夜小视频 | 亚洲精品免费在线播放 | av免费在线免费观看 | 欧美精品乱码久久久久 | 国产精品电影一区二区 | 日本精品在线 | 91视频这里只有精品 | 高清av影院| 国产福利在线免费 | 婷婷中文字幕在线观看 | 色狠狠久久av五月综合 | 欧美日韩在线看 | japanese黑人亚洲人4k | 最近最新中文字幕视频 | 韩日视频在线 | 日韩在线字幕 | 不卡av免费在线观看 | 99热国产在线观看 | 五月视频 | 久久精品影视 | 国产裸体视频网站 | a天堂免费 | 天天天天射 | av手机版 | 韩国在线一区二区 | 91视频在线免费观看 | 日韩偷拍精品 | 亚洲国产日韩一区 | 伊人成人精品 | 99久久99视频只有精品 | 日本二区三区在线 | 999久久久久| 天天草综合网 | 樱空桃av | 欧美亚洲三级 | 久草视频免费播放 | 国产精品99久久久久久小说 | 国产免费嫩草影院 | 99精品在线播放 | 天堂av观看 | 91爱爱网址 | 日本老少交| 久久精品小视频 | 亚洲欧美日韩一区二区三区在线观看 | 国产高清不卡av | 国产第一页福利影院 | 少妇高潮流白浆在线观看 | 色综合在 | 99久久日韩精品视频免费在线观看 | 9797在线看片亚洲精品 | 91高清免费看 | 四虎影视成人永久免费观看视频 | 国产精品麻豆果冻传媒在线播放 | 久久草草热国产精品直播 | 人操人 | 欧美午夜性生活 | 成人免费观看网站 | 天天操天天操天天操天天操天天操 | 2000xxx影视| 久久综合五月 | 久草爱 | 天天色天天色天天色 | 伊人天天狠天天添日日拍 | 999视频网站 | 亚洲成av人片一区二区梦乃 | 天天色天天射综合网 | 亚洲婷婷综合色高清在线 | 婷婷色综| 国产精品视频区 | 黄色影院在线免费观看 | 精品久久久久久亚洲综合网站 | 国产精品女同一区二区三区久久夜 | www五月天com| 久久精彩免费视频 | 亚洲精品在线国产 | 99久久精品免费 | 日韩精品三区四区 | 精品一区免费 | 国产精品免费观看国产网曝瓜 | 日韩在线视频播放 | 国产黄色美女 | 国内精品在线一区 | 久久久久免费精品 | 欧美精品久久久久性色 | 国产成人精品一区二区在线观看 | 国产精品18久久久 | 中文字幕在线观看第一区 | 亚洲国产资源 | 99精品视频在线观看 | 91原创在线观看 | 久久视影 | 亚洲综合视频在线观看 | 69精品久久 | 久草网站在线观看 | 国产精品一区二区久久久 | 久久黄色片子 | 四虎5151久久欧美毛片 | 日韩精品免费一区 | 最新中文字幕 | 久久久国产一区二区三区四区小说 | 久久爽久久爽久久av东京爽 | 综合色爱| 在线视频中文字幕一区 | 综合国产在线 | 国产中文字幕大全 | 国产亚洲欧美日韩高清 | 日本黄网站 | 国产免费又爽又刺激在线观看 | 成人午夜免费剧场 | 久久精品视频在线免费观看 | av福利在线播放 | 亚洲综合色视频 | 亚洲va天堂va欧美ⅴa在线 | 天堂素人在线 | 亚洲色图色 | 国产在线播放观看 | 久久免费av电影 | 久久婷婷网 | 狠狠干.com | 国产精品剧情在线亚洲 | 亚洲婷婷综合色高清在线 | 日韩精品视频第一页 | 五月天婷婷免费视频 | 最近2019年日本中文免费字幕 | 99精品免费在线观看 | 日韩av进入 | 久久高清免费观看 | 青草视频在线看 | 亚洲精品在线视频观看 | 久久福利剧场 | 久久久www成人免费精品张筱雨 | 成人精品视频久久久久 | 亚洲一区精品人人爽人人躁 | 成人免费在线视频观看 | 日韩黄色免费在线观看 | 成年人视频在线免费 | 国产老妇av | av电影av在线 | 国产精品永久久久久久久www | 国产在线播放一区 | 亚洲午夜久久久久久久久电影网 | 亚洲乱码国产乱码精品天美传媒 | 日韩成人邪恶影片 | 成年人在线观看视频免费 | 色婷婷国产在线 | 久久婷婷五月综合色丁香 | 91久草视频 | 在线观看免费观看在线91 | 日韩精品欧美专区 | 九九免费在线观看 | 天天狠狠操| 精品在线一区二区 | 亚洲视屏| 久久不射影院 | 三级在线视频观看 |