国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

HashMap鏈表樹化閾值深度解析:為什么是8而不是7或9?

開發 前端
在JDK 8之前,HashMap完全基于數組+鏈表實現。當發生哈希沖突時,新元素會被添加到鏈表末尾。隨著元素增多,鏈表可能變得很長,導致查詢效率從O(1)退化為O(n)。

在Java集合框架中,HashMap作為最常用的數據結構之一,其性能優化一直是開發者關注的焦點。JDK 8引入了一項重要優化:當哈希桶中的鏈表長度超過一定閾值時,會將鏈表轉換為紅黑樹。這個閾值被設定為8,這一數字背后蘊含著深刻的設計思想和數學原理。本文將深入剖析這一設計決策的技術細節,通過源碼分析、數學證明和性能測試,全面解析為什么選擇8作為樹化閾值。

一、HashMap基礎結構與樹化背景

1.1 HashMap底層實現演進

在JDK 8之前,HashMap完全基于數組+鏈表實現。當發生哈希沖突時,新元素會被添加到鏈表末尾。隨著元素增多,鏈表可能變得很長,導致查詢效率從O(1)退化為O(n)。

// JDK 7中的HashMap.Entry實現
static class Entry<K,V> implements Map.Entry<K,V> {
    final K key;
    V value;
    Entry<K,V> next;
    int hash;
    
    Entry(int h, K k, V v, Entry<K,V> n) {
        value = v;
        next = n;
        key = k;
        hash = h;
    }
}

JDK 8引入了紅黑樹優化,當鏈表長度達到閾值時轉換為樹結構:

// JDK 8中的Node和TreeNode
static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
    
    // 構造函數...
}

static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
    TreeNode<K,V> parent;  // 紅黑樹鏈接
    TreeNode<K,V> left;
    TreeNode<K,V> right;
    TreeNode<K,V> prev;    // 刪除后需要取消鏈接
    boolean red;
    
    // 樹操作方法...
}

1.2 樹化的觸發條件

HashMap中樹化的條件并非單一因素決定,而是綜合考慮鏈表長度和哈希桶數組大小:

public class HashMap<K,V> extends AbstractMap<K,V> 
    implements Map<K,V>, Cloneable, Serializable {
    
    // 樹化閾值 - 當鏈表長度達到此值時轉換為紅黑樹
    static final int TREEIFY_THRESHOLD = 8;
    
    // 取消樹化閾值 - 當樹節點數小于此值時轉換回鏈表
    static final int UNTREEIFY_THRESHOLD = 6;
    
    // 最小樹化容量 - 哈希表容量至少達到此值才會樹化
    static final int MIN_TREEIFY_CAPACITY = 64;
    
    final void treeifyBin(Node<K,V>[] tab, int hash) {
        int n, index; Node<K,V> e;
        // 檢查哈希表容量是否達到最小樹化要求
        if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
            resize(); // 先擴容而不是立即樹化
        else if ((e = tab[index = (n - 1) & hash]) != null) {
            // 執行樹化操作
            TreeNode<K,V> hd = null, tl = null;
            do {
                TreeNode<K,V> p = replacementTreeNode(e, null);
                if (tl == null)
                    hd = p;
                else {
                    p.prev = tl;
                    tl.next = p;
                }
                tl = p;
            } while ((e = e.next) != null);
            if ((tab[index] = hd) != null)
                hd.treeify(tab); // 將鏈表轉換為紅黑樹
        }
    }
}

二、樹化閾值的數學基礎:泊松分布

2.1 哈希沖突的概率模型

HashMap設計者使用泊松分布來模擬哈希沖突的概率。在理想的哈希函數下,元素在哈希桶中的分布應該接近均勻分布,但實際上由于哈希函數的局限性,沖突不可避免。

泊松分布的概率質量函數為:

其中λ是每個桶中元素的期望數量,在HashMap中約為0.5(負載因子0.75時)。

2.2 概率計算與閾值選擇

HashMap源碼中的注釋詳細解釋了基于泊松分布的概率計算:

/**
 * 由于樹節點的大小大約是普通節點的兩倍,因此我們僅在桶包含足夠多的節點時才使用樹節點(參見TREEIFY_THRESHOLD)。
 * 當桶中的節點數變得太小時,它們會被轉換回普通的桶。
 * 在具有良好分布的用戶哈希碼的情況下,很少使用樹桶。
 * 
 * 理想情況下,在隨機哈希碼下,桶中節點的頻率遵循泊松分布,其中參數的平均值約為0.5,默認大小閾值為0.75。
 * 忽略方差,列表大小k的預期出現次數為(exp(-0.5) * pow(0.5, k) / factorial(k))。
 * 
 * 0:    0.60653066
 * 1:    0.30326533
 * 2:    0.07581633
 * 3:    0.01263606
 * 4:    0.00157952
 * 5:    0.00015795
 * 6:    0.00001316
 * 7:    0.00000094
 * 8:    0.00000006
 * 更多: 小于千萬分之一
 */

讓我們通過代碼驗證這些概率值:

public class PoissonDistributionAnalysis {
    
    /**
     * 計算泊松分布概率
     * @param lambda 期望值(HashMap中約為0.5)
     * @param k 事件發生次數
     * @return 概率值
     */
    public static double poissonProbability(double lambda, int k) {
        return Math.exp(-lambda) * Math.pow(lambda, k) / factorial(k);
    }
    
    /**
     * 計算階乘
     */
    public static long factorial(int n) {
        if (n <= 1) return 1;
        long result = 1;
        for (int i = 2; i <= n; i++) {
            result *= i;
        }
        return result;
    }
    
    public static void main(String[] args) {
        double lambda = 0.5; // HashMap中的期望值
        
        System.out.println("鏈表長度\t出現概率");
        System.out.println("----------------------");
        
        for (int k = 0; k <= 10; k++) {
            double probability = poissonProbability(lambda, k);
            System.out.printf("%d\t%.8f", k, probability);
            
            // 添加特殊標記
            if (k == 7) System.out.print(" ← 接近樹化閾值");
            if (k == 8) System.out.print(" ← 樹化閾值");
            if (k == 9) System.out.print(" ← 超過閾值");
            
            System.out.println();
        }
        
        // 計算長度>=8的概率
        double cumulativeProbability = 0.0;
        for (int k = 8; k <= 20; k++) {
            cumulativeProbability += poissonProbability(lambda, k);
        }
        System.out.printf("\n鏈表長度≥8的總概率: %.10f", cumulativeProbability);
        System.out.println(" (約千萬分之六)");
    }
}

運行結果:

鏈表長度    出現概率
----------------------
0    0.60653066
1    0.30326533
2    0.07581633
3    0.01263606
4    0.00157952
5    0.00015795
6    0.00001316
7    0.00000094 ← 接近樹化閾值
8    0.00000006 ← 樹化閾值
9    0.00000000 ← 超過閾值
10    0.00000000

鏈表長度≥8的總概率: 0.0000000618 (約千萬分之六)

2.3 閾值選擇的數學意義

從數學角度看,選擇8作為閾值基于以下考慮:

1. 概率極低:鏈表長度達到8的概率約為0.00000006,即千萬分之六

2. 平衡點:在7和9之間,8提供了最佳的性能平衡

3. 實用性:在實際應用中,如此低的概率意味著在正常情況下幾乎不會發生樹化

三、性能分析與權衡

3.1 鏈表與紅黑樹的性能對比

紅黑樹雖然能提供O(log n)的查詢性能,但節點內存開銷和操作復雜度都高于鏈表:

// 性能測試對比
public class PerformanceBenchmark {
    
    private static final int ITERATIONS = 100000;
    
    public static void main(String[] args) {
        // 鏈表性能測試
        long linkedListTime = testLinkedList();
        System.out.println("鏈表平均查詢時間: " + linkedListTime + " ns");
        
        // 紅黑樹性能測試  
        long treeTime = testRedBlackTree();
        System.out.println("紅黑樹平均查詢時間: " + treeTime + " ns");
        
        // 內存占用對比
        compareMemoryUsage();
    }
    
    private static long testLinkedList() {
        LinkedList<Integer> list = new LinkedList<>();
        for (int i = 0; i < 8; i++) {
            list.add(i);
        }
        
        long startTime = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            list.contains(7); // 查找最后一個元素,最壞情況
        }
        return (System.nanoTime() - startTime) / ITERATIONS;
    }
    
    private static long testRedBlackTree() {
        TreeSet<Integer> tree = new TreeSet<>();
        for (int i = 0; i < 8; i++) {
            tree.add(i);
        }
        
        long startTime = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            tree.contains(7);
        }
        return (System.nanoTime() - startTime) / ITERATIONS;
    }
    
    private static void compareMemoryUsage() {
        // 估算內存占用
        int linkedListMemory = 8 * (16 + 8 + 8); // 8個節點,每個節點約32字節
        int treeMemory = 8 * (16 + 8 + 8 + 8 + 8 + 1); // 樹節點額外開銷
        
        System.out.println("鏈表內存估算: " + linkedListMemory + " bytes");
        System.out.println("紅黑樹內存估算: " + treeMemory + " bytes");
        System.out.println("樹節點內存開銷增加: " + 
            ((double)(treeMemory - linkedListMemory) / linkedListMemory * 100) + "%");
    }
}

3.2 閾值8的性能優勢

選擇8作為閾值在性能上具有明顯優勢:

1. 避免過早樹化:如果閾值設為7,會頻繁觸發樹化,增加不必要的內存和計算開銷

2. 防止鏈表過長:如果閾值設為9,在極端情況下鏈表可能過長影響性能

3. 最佳轉折點:在長度為8時,紅黑樹的O(log n)性能開始明顯優于鏈表的O(n)

四、源碼級別的深入分析

4.1 樹化過程的詳細實現

讓我們深入分析HashMap中樹化的完整過程:

final void treeify(Node<K,V>[] tab) {
    TreeNode<K,V> root = null;
    // 遍歷鏈表,將每個節點轉換為樹節點
    for (TreeNode<K,V> x = this, next; x != null; x = next) {
        next = (TreeNode<K,V>)x.next;
        x.left = x.right = null;
        
        // 建立紅黑樹
        if (root == null) {
            x.parent = null;
            x.red = false; // 根節點為黑色
            root = x;
        } else {
            K k = x.key;
            int h = x.hash;
            Class<?> kc = null;
            
            // 在樹中尋找插入位置
            for (TreeNode<K,V> p = root;;) {
                int dir, ph;
                K pk = p.key;
                if ((ph = p.hash) > h)
                    dir = -1;
                else if (ph < h)
                    dir = 1;
                else if ((kc == null &&
                          (kc = comparableClassFor(k)) == null) ||
                         (dir = compareComparables(kc, k, pk)) == 0)
                    dir = tieBreakOrder(k, pk); // 打破平局
                
                TreeNode<K,V> xp = p;
                if ((p = (dir <= 0) ? p.left : p.right) == null) {
                    x.parent = xp;
                    if (dir <= 0)
                        xp.left = x;
                    else
                        xp.right = x;
                    root = balanceInsertion(root, x); // 平衡插入
                    break;
                }
            }
        }
    }
    moveRootToFront(tab, root); // 確保根節點在桶的第一個位置
}

4.2 紅黑樹平衡操作

紅黑樹的平衡是通過復雜的旋轉和重新著色實現的:

static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root,
                                            TreeNode<K,V> x) {
    x.red = true; // 新插入的節點總是紅色
    
    for (TreeNode<K,V> xp, xpp, xppl, xppr;;) {
        if ((xp = x.parent) == null) {
            x.red = false; // 根節點必須為黑色
            return x;
        }
        else if (!xp.red || (xpp = xp.parent) == null)
            return root;
        
        if (xp == (xppl = xpp.left)) {
            if ((xppr = xpp.right) != null && xppr.red) {
                // 情況1:叔叔節點是紅色
                xppr.red = false;
                xp.red = false;
                xpp.red = true;
                x = xpp;
            }
            else {
                if (x == xp.right) {
                    // 情況2:x是右孩子,需要左旋轉
                    root = rotateLeft(root, x = xp);
                    xpp = (xp = x.parent) == null ? null : xp.parent;
                }
                if (xp != null) {
                    // 情況3:x是左孩子,需要右旋轉并重新著色
                    xp.red = false;
                    if (xpp != null) {
                        xpp.red = true;
                        root = rotateRight(root, xpp);
                    }
                }
            }
        }
        else {
            // 對稱的情況處理...
        }
    }
}

五、為什么不是7或9?

5.1 排除閾值7的理由

如果閾值設為7,會帶來以下問題:

1. 過度樹化:鏈表長度7的概率是8的15倍左右,會導致頻繁的樹化操作

2. 內存浪費:紅黑樹節點內存開銷是鏈表節點的約2倍

3. 性能下降:對于短鏈表,遍歷可能比樹查找更快

// 閾值7 vs 8的概率對比
public class ThresholdComparison {
    public static void main(String[] args) {
        double lambda = 0.5;
        
        double prob7 = poissonProbability(lambda, 7);
        double prob8 = poissonProbability(lambda, 8);
        double prob9 = poissonProbability(lambda, 9);
        
        System.out.println("長度7的概率: " + prob7);
        System.out.println("長度8的概率: " + prob8); 
        System.out.println("長度9的概率: " + prob9);
        
        System.out.println("7比8高 " + (prob7 / prob8) + " 倍");
        System.out.println("7比9高 " + (prob7 / prob9) + " 倍");
    }
    
    private static double poissonProbability(double lambda, int k) {
        return Math.exp(-lambda) * Math.pow(lambda, k) / factorial(k);
    }
    
    private static long factorial(int n) {
        long result = 1;
        for (int i = 2; i <= n; i++) {
            result *= i;
        }
        return result;
    }
}

5.2 排除閾值9的理由

閾值9的問題同樣明顯:

1. 風險容忍度:在哈希攻擊場景下,長度為9的鏈表性能已經明顯下降

2. 邊際收益遞減:從8增加到9帶來的性能提升有限

3. 實際需求:在正常使用情況下,長度8已經足夠罕見

5.3 閾值8的黃金平衡

閾值8在各方面達到了最佳平衡:

概率合理性:千萬分之六的概率在工程上可接受

性能優化:在真正需要時提供O(log n)性能保障

資源效率:避免不必要的內存和計算開銷

六、實際應用場景與測試驗證

6.1 哈希攻擊防護

樹化機制的一個重要應用場景是防護哈希碰撞攻擊:

public class HashAttackProtection {
    
    public static void testHashCollision() {
        HashMap<WeakKey, String> map = new HashMap<>();
        
        // 創建大量具有相同哈希碼的鍵
        List<WeakKey> keys = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            WeakKey key = new WeakKey(i, 123); // 所有鍵具有相同哈希碼
            keys.add(key);
            map.put(key, "value" + i);
        }
        
        // 測試查詢性能
        long startTime = System.nanoTime();
        for (WeakKey key : keys) {
            map.get(key);
        }
        long duration = System.nanoTime() - startTime;
        
        System.out.println("哈希沖突場景查詢時間: " + duration + " ns");
        System.out.println("桶結構: " + getBucketStructure(map));
    }
    
    static class WeakKey {
        final int id;
        final int hash; // 固定哈希碼
        
        WeakKey(int id, int hash) {
            this.id = id;
            this.hash = hash;
        }
        
        @Override
        public int hashCode() {
            return hash; // 故意制造哈希沖突
        }
        
        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
            WeakKey weakKey = (WeakKey) obj;
            return id == weakKey.id;
        }
    }
    
    private static String getBucketStructure(HashMap<?, ?> map) {
        // 通過反射獲取內部結構信息(實際中不推薦)
        try {
            Field tableField = HashMap.class.getDeclaredField("table");
            tableField.setAccessible(true);
            Object[] table = (Object[]) tableField.get(map);
            
            for (Object node : table) {
                if (node != null) {
                    int length = getChainLength(node);
                    if (length >= 8) {
                        return "紅黑樹 (長度: " + length + ")";
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "鏈表";
    }
    
    private static int getChainLength(Object node) {
        int length = 0;
        while (node != null) {
            length++;
            try {
                Field nextField = node.getClass().getDeclaredField("next");
                nextField.setAccessible(true);
                node = nextField.get(node);
            } catch (Exception e) {
                break;
            }
        }
        return length;
    }
}

6.2 性能基準測試

通過實際測試驗證不同閾值選擇的性能影響:

public class ThresholdBenchmark {
    
    private static final int TEST_SIZE = 100000;
    
    public static void main(String[] args) {
        System.out.println("測試不同鏈表長度下的性能表現:");
        System.out.println("長度\t鏈表查詢\t樹查詢\t優勢比");
        System.out.println("----------------------------------------");
        
        for (int length = 1; length <= 15; length++) {
            long listTime = testLinkedList(length);
            long treeTime = testRedBlackTree(length);
            double ratio = (double) listTime / treeTime;
            
            System.out.printf("%d\t%d ns\t%d ns\t%.2f", 
                length, listTime, treeTime, ratio);
            
            if (length == 8) System.out.print(" ← 當前閾值");
            System.out.println();
        }
    }
    
    private static long testLinkedList(int length) {
        LinkedList<Integer> list = new LinkedList<>();
        for (int i = 0; i < length; i++) {
            list.add(i);
        }
        
        long startTime = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            list.contains(length - 1); // 查找最后一個元素
        }
        return (System.nanoTime() - startTime) / 10000;
    }
    
    private static long testRedBlackTree(int length) {
        TreeSet<Integer> tree = new TreeSet<>();
        for (int i = 0; i < length; i++) {
            tree.add(i);
        }
        
        long startTime = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            tree.contains(length - 1);
        }
        return (System.nanoTime() - startTime) / 10000;
    }
}

七、其他相關設計考量

7.1 取消樹化閾值6的設計

HashMap不僅設置了樹化閾值8,還設置了取消樹化閾值6:

static final int UNTREEIFY_THRESHOLD = 6;

這種設計避免了在閾值附近頻繁的樹化-取消樹化振蕩:

1. ** hysteresis現象**:使用不同的閾值提供穩定性

2. 性能考慮:避免頻繁的結構轉換開銷

3. 工程實踐:在系統設計中常見的防抖動策略

7.2 最小樹化容量要求

HashMap還設置了最小樹化容量,防止在小表中過早樹化:

static final int MIN_TREEIFY_CAPACITY = 64;

這種設計確保了:

  • ? 只有在哈希表足夠大時才進行樹化
  • ? 小表優先通過擴容解決沖突
  • ? 避免在小規模場景下的過度優化

結論

HashMap選擇8作為鏈表轉紅黑樹的閾值,是基于深刻的數學原理、性能分析和工程實踐的完美結合。這一設計決策體現了以下幾個關鍵點:

1. 數學嚴謹性:基于泊松分布的概率計算,確保在正常情況下樹化極少發生

2. 性能最優化:在鏈表性能開始顯著下降的臨界點引入樹結構

3. 資源效率:平衡了內存開銷和計算性能的權衡

4. 工程實用性:考慮了實際應用場景和極端情況下的表現

閾值8的選擇不是任意的,而是經過精心計算和實踐驗證的最佳平衡點。它既提供了對哈希碰撞攻擊的有效防護,又避免了在正常使用場景下的不必要的性能開銷。這種細致入微的設計正是Java集合框架成熟性和專業性的體現,也為我們在日常開發中的性能優化提供了寶貴的參考范例。

通過深入理解這一設計決策背后的原理,我們不僅能夠更好地使用HashMap,還能從中學習到系統設計和性能優化的寶貴經驗,這些經驗可以應用于我們日常開發的各個方面。

責任編輯:武曉燕 來源: 程序員秋天
相關推薦

2020-08-19 16:36:53

HashMap紅黑樹閾值

2019-09-24 09:33:53

MySQLB+樹InnoDB

2013-03-25 10:14:18

NginxApache

2019-04-19 11:56:48

框架AI開發

2021-08-14 09:04:58

TypeScriptJavaScript開發

2012-10-10 16:52:21

CentOSDebianUbuntu

2021-10-30 19:57:00

HTTP2 HTTP

2020-09-15 09:23:19

C++WindowsC#

2017-09-11 19:58:06

PostgreSQLMySQL數據庫

2020-06-02 14:17:55

QWER排列鍵盤打印機

2025-07-31 03:00:00

數據湖BLMLLM

2021-02-26 05:30:25

元素For-Each代碼

2023-11-02 08:20:54

SocketZygoteAndroid

2021-03-26 11:50:28

Linuxexals

2021-06-30 12:47:12

標簽HTML分辨率

2023-03-01 10:42:58

gRPC服務端設置

2021-12-02 09:20:33

TCPLinux三次握手

2016-10-11 11:13:15

Linus Torva

2023-01-11 12:14:50

NeoVimVim開發

2024-03-22 12:29:03

HashMap線程
點贊
收藏

51CTO技術棧公眾號

欧美精品日日鲁夜夜添| 亚洲最大av网站| 超碰在线公开| 精品视频久久久久久久| 欧美aa免费在线| 亚洲社区在线观看| 国产精品日本一区二区三区在线 | 免费视频国产一区| 成人国产亚洲精品a区天堂华泰| 国产精品v亚洲精品v日韩精品| 欧美精品免费观看二区| 国产一区二区在线电影| 国产一级不卡毛片| 天天综合色天天综合色h| 国产激情在线| 色七七影院综合| 欧美亚洲激情| 日韩欧美精品久久| 久久久精品tv| 国产日本在线| 自拍偷拍亚洲精品| 久草在线成人| 亚洲mv在线看| 亚洲三级在线免费| av免费在线观看网址| 伊人一区二区三区久久精品| 精品淫伦v久久水蜜桃| 精品一卡二卡三卡四卡日本乱码| 国产乱码精品一区二区三| 国产福利电影网| 精品乱码亚洲一区二区不卡| 日韩福利视频一区| 亚洲一区二区三区午夜| 亚洲摸摸操操av| 9765激情中文在线| 国产精品美女主播| 岛国av在线一区| 久久手机免费观看| 九九热最新视频//这里只有精品 | 成人中文在线| www.九色.com| 在线视频综合导航| 亚洲精品一区在线| 神马影院一区二区| 亚洲一二三四在线| 国产69精品久久久久9999人| 国产精品亚洲综合| 18成人在线观看| 色综合桃花网| 91成人理论电影| 国产欧美日韩亚州综合| 国内在线视频| www.久久久.com| 国产91aaa| 97久久精品人人爽人人爽蜜臀 | 欧美日韩aaaaa| 日韩三级毛片| av日韩在线看| 3d动漫精品啪啪| 欧美在线免费看视频| 凹凸国产熟女精品视频| 欧美一级欧美三级在线观看| 国产欧美一区二区三区精品观看| 青草青青在线视频| 亚洲电影第1页| 亚洲小说区图片区| 可以看美女隐私的网站| 日韩在线观看免费| 久久精品国产一区二区三区免费看| 青青操视频在线| 茄子视频成人在线| 久久久久久日产精品| 日韩电影网站| 日本一区二区三区www| 色婷婷久久99综合精品jk白丝| 色爱综合av| 一区二区三区国产免费| 亚洲天堂2020| 精品一区二区免费在线观看| 麻豆视频网站在线观看| 成人欧美视频在线| 一本色道**综合亚洲精品蜜桃冫| 国产精品午夜一区二区三区| 免费高清成人| 高清欧美性猛交xxxx| 91麻豆免费视频| 亚洲精品三区| 黄色国产精品视频| 久久国产一区二区三区| www.日韩精品| 亚洲欧美综合久久久久久v动漫| 免费看毛片的网址| xxxx欧美18另类的高清| 97国产一区二区| 精品国产第一国产综合精品| 成人免费观看视频在线观看| www.亚洲人.com| 91在线小视频| 99re8这里有精品热视频8在线| 欧美午夜aaaaaa免费视频| 欧美精品在线极品| 久久人人爽人人爽| 伦理一区二区三区| avlululu| 成人乱色短篇合集| 欧美中文字幕久久| 男女精品网站| 9i看片成人免费高清| 女人天堂av手机在线| 久久久久亚洲精品国产| 一区二区三区视频在线观看| 亚洲成av人电影| 精品176二区| 色乱码一区二区三区熟女| 伊人一区二区三区久久精品 | 久久久久久三级| 26uuu国产精品视频| 红桃视频成人在线观看| 91精品国产成人观看| 岛国成人毛片| 亚州欧美一区三区三区在线| 在线性视频日韩欧美| 国产亚洲欧美一级| 国产真实有声精品录音| 欧美日韩激情视频一区二区三区| 免费久久一级欧美特大黄| 日韩电影第一页| 久久精品综合网| 日本不卡高清| 日本一级理论片在线大全| 伊人久久在线观看| 欧美成人精品三级在线观看| 亚洲一卡二卡三卡四卡无卡久久| 亚洲精选久久| 免费日韩中文字幕| 国产精品夜色7777狼人| 欧美一区二区在线免费观看| 国产精品1024久久| 免费看日本一区二区| 免费av不卡| 国产无套内射久久久国产| 国产精品亚洲视频在线观看| 日韩一区二区三区电影在线观看 | 伊人成人在线| 欧美精品总汇| 成全电影大全在线观看| 999成人精品视频线3| 91香蕉视频黄| 国产亚洲精品91在线| 久久本道综合色狠狠五月| 欧美国产综合| 国内精品久久久久国产盗摄免费观看完整版| 亚洲区小说区图片区qvod按摩| 色婷婷精品视频| 99久久激情| 国产美女一区| 91影院在线观看| 亚洲一区二区成人在线观看| 久久久久久电影| 不卡av在线免费观看| 国产精品一区久久久久| 国产精品99久久不卡二区| 国产精品夜夜嗨| 久久aⅴ国产欧美74aaa| 欧美激情一二三区| 中文字幕日韩av综合精品| 久久人妻无码一区二区| 三级黄视频在线观看| 国产黄色片在线播放| 日韩伦理一区二区| 亚洲精品欧洲| 欧美日韩午夜在线| 国产97色在线| 99re6在线| 北岛玲heyzo一区二区| 欧美日韩一区二区国产| 中文字幕中文字幕在线一区 | 中文字幕亚洲一区二区va在线| 亚洲国产精品久久久久秋霞不卡| 国产在线日韩在线| 久久久久久77777| 美女黄色成人网| 欧美一区二区三区视频在线| 超薄丝袜一区二区| 亚洲影院污污.| 欧美xnxx| 麻豆freexxxx性91精品| 精品国产一区二区三区久久久| 成人免费毛片嘿嘿连载视频| 欧美在线首页| 成人知道污网站| 岛国在线视频网站| 成年人在线免费观看| 亚洲综合日韩欧美| 色一情一乱一乱一区91| 国内精品**久久毛片app| 羞羞色国产精品| 久久精品国产91精品亚洲| 亚洲成年人在线播放| 在线观看一区二区精品视频|