国产成人欧美一区二区三区vr_久久国产精品人人爽人人爽_国产精品永久免费播放_肉欲啪啪a∨无码精品一区二区_国产超短裙jk丝袜在线_亚洲AV片高清资源在线观看_国模无码一区二区三区久久_国产成年人未进视频_中文字幕无码精品夜_一区二区三区在线视频免费看_亚洲成AV人片在线观看网址_日本激情视频高清综合久久_亚洲午夜视频福利_国内大量揄拍人妻精品視_久久国产精品福利二区三区

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營的一線實(shí)戰(zhàn)洞察。

Android性能優(yōu)化:SparseArray與ArrayMap替代HashMap的深度解析

Android性能優(yōu)化:SparseArray與ArrayMap替代HashMap的深度解析 1. 從一個(gè)真實(shí)的性能問題說起做Android開發(fā)有些年頭的人大概率都經(jīng)歷過這樣一種場景某個(gè)列表頁在低端機(jī)上滑動(dòng)起來就是不夠跟手幀率時(shí)不時(shí)掉到40以下明明邏輯不復(fù)雜Adapter里也沒做什么耗時(shí)操作但Profiler一掛上去GC日志刷得跟流水賬一樣。順著內(nèi)存分配一路追下去最后發(fā)現(xiàn)罪魁禍?zhǔn)准炔皇菆D片加載也不是網(wǎng)絡(luò)請(qǐng)求而是某個(gè)用HashMapInteger, Object存了幾百條映射關(guān)系的緩存結(jié)構(gòu)。這個(gè)結(jié)論第一次看到的時(shí)候確實(shí)有點(diǎn)反直覺。HashMap在Java世界里幾乎是萬能容器的代名詞怎么到了Android上就成了性能瓶頸原因其實(shí)不復(fù)雜HashMap每個(gè)鍵值對(duì)都要額外創(chuàng)建一個(gè)Entry對(duì)象而Integer作為key在自動(dòng)裝箱時(shí)又會(huì)產(chǎn)生臨時(shí)對(duì)象。一個(gè)幾百條數(shù)據(jù)的Map在頻繁讀寫場景下短時(shí)間內(nèi)就能制造出成千上萬個(gè)小對(duì)象GC壓力自然就上來了。Android的Dalvik和ART雖然一直在優(yōu)化GC但內(nèi)存分配這件事本身的開銷是躲不掉的。SparseArray和ArrayMap就是在這個(gè)背景下進(jìn)入視野的。它們不是Android獨(dú)創(chuàng)的什么黑科技本質(zhì)上是用時(shí)間換空間的經(jīng)典思路放棄HashMap的哈希桶結(jié)構(gòu)改用有序數(shù)組加二分查找來存儲(chǔ)鍵值對(duì)。查找從O(1)退化到O(log n)但省掉了Entry對(duì)象和裝箱開銷在小數(shù)據(jù)量場景下綜合表現(xiàn)反而更好。這個(gè)取舍值不值得取決于你的數(shù)據(jù)規(guī)模和讀寫比例不能一概而論。這篇文章會(huì)把這兩個(gè)容器從設(shè)計(jì)動(dòng)機(jī)、內(nèi)部結(jié)構(gòu)、核心方法實(shí)現(xiàn)、性能邊界到實(shí)際選型完整地拆一遍。適合已經(jīng)寫過一段時(shí)間Android、對(duì)Java集合有一定了解、但還沒系統(tǒng)研究過這兩個(gè)類的開發(fā)者??赐曛竽銘?yīng)該能判斷什么場景該用SparseArray什么場景該用ArrayMap什么場景老老實(shí)實(shí)回去用HashMap。2. 為什么Android要另起爐灶2.1 HashMap在移動(dòng)端的三個(gè)隱性成本要理解SparseArray和ArrayMap的價(jià)值得先把HashMap在Android上的成本算清楚。很多人只知道“HashMap快”但快是有代價(jià)的這個(gè)代價(jià)在服務(wù)端可能無所謂在移動(dòng)端就會(huì)被放大。第一個(gè)成本是Entry對(duì)象的額外內(nèi)存。HashMap內(nèi)部維護(hù)一個(gè)Node數(shù)組Java 8之后是Node之前是Entry每個(gè)鍵值對(duì)都要包裝成一個(gè)Node對(duì)象里面存hash、key、value和next指針。一個(gè)Node對(duì)象在32位JVM上大約占32字節(jié)64位開啟指針壓縮后大約40字節(jié)左右。如果你存1000條數(shù)據(jù)光Node對(duì)象就是40KB這還沒算數(shù)組本身的容量。第二個(gè)成本是自動(dòng)裝箱。HashMapInteger, Object里的key是Integer類型當(dāng)你寫map.put(1, obj)的時(shí)候字面量1會(huì)被自動(dòng)裝箱成Integer.valueOf(1)。雖然Integer有-128到127的緩存池但超過這個(gè)范圍的整數(shù)每次都會(huì)new一個(gè)新對(duì)象。在循環(huán)里頻繁put/get裝箱產(chǎn)生的臨時(shí)對(duì)象數(shù)量相當(dāng)可觀。第三個(gè)成本是擴(kuò)容時(shí)的rehash。HashMap默認(rèn)容量16負(fù)載因子0.75超過閾值就擴(kuò)容翻倍。擴(kuò)容時(shí)所有元素都要重新計(jì)算hash并重新分配位置這個(gè)操作在數(shù)據(jù)量大時(shí)會(huì)造成明顯的卡頓。雖然可以通過預(yù)設(shè)初始容量來緩解但很多開發(fā)者并不會(huì)這么做。注意這里說的成本是相對(duì)的。如果你的Map只有幾十條數(shù)據(jù)或者讀寫頻率很低HashMap的這些開銷完全可以忽略。不要為了優(yōu)化而優(yōu)化先測量再動(dòng)手。2.2 SparseArray的設(shè)計(jì)取舍SparseArray的全稱是android.util.SparseArray它的key被限定為int類型value是泛型Object。這個(gè)限定不是限制而是它的核心設(shè)計(jì)前提。因?yàn)閗ey是int就不需要裝箱也不需要計(jì)算hashCode。SparseArray內(nèi)部維護(hù)兩個(gè)平行數(shù)組一個(gè)int[] mKeys存放鍵一個(gè)Object[] mValues存放值。所有鍵按升序排列查找時(shí)用二分查找定位。這個(gè)設(shè)計(jì)帶來的直接好處是沒有Entry對(duì)象沒有裝箱內(nèi)存占用大幅降低。代價(jià)是查找從O(1)變成O(log n)插入和刪除因?yàn)橐苿?dòng)數(shù)組元素最壞情況是O(n)。SparseArray還有一個(gè)變體叫SparseIntArray、SparseLongArray、SparseBooleanArray分別對(duì)應(yīng)value是基本類型的場景。這些變體連value的裝箱都省了在統(tǒng)計(jì)計(jì)數(shù)、狀態(tài)標(biāo)記這類場景下非常實(shí)用。2.3 ArrayMap的通用化嘗試SparseArray的key只能是int這個(gè)限制在很多場景下不夠用。比如你想用String做keySparseArray就無能為力了。ArrayMap就是為了解決這個(gè)問題而出現(xiàn)的。ArrayMap同樣使用兩個(gè)平行數(shù)組但key是Object類型可以是String、Integer或任何對(duì)象。它內(nèi)部維護(hù)一個(gè)int[] mHashes數(shù)組存放key的hashCode以及Object[] mArray數(shù)組交替存放key和value。查找時(shí)先對(duì)mHashes做二分查找找到后再比較key的equals。ArrayMap在Android 5.0之后被加入androidx.collection包也可以在非Android項(xiàng)目中使用。它的設(shè)計(jì)目標(biāo)是在數(shù)據(jù)量較小通常小于1000且讀多寫少的場景下提供比HashMap更低的內(nèi)存占用。2.4 三者的核心差異對(duì)比特性HashMapSparseArrayArrayMapkey類型任意Objectint任意Object數(shù)據(jù)結(jié)構(gòu)哈希桶鏈表/紅黑樹有序int數(shù)組Object數(shù)組有序hash數(shù)組鍵值交替數(shù)組查找復(fù)雜度O(1)平均O(log n)O(log n)插入復(fù)雜度O(1)平均O(n)最壞O(n)最壞內(nèi)存占用高Entry裝箱低中無Entry有hash數(shù)組適用數(shù)據(jù)量任意小于1000小于1000線程安全否否否這張表是選型的核心依據(jù)。記住一個(gè)原則數(shù)據(jù)量小、讀多寫少、key是int優(yōu)先SparseArraykey不是int但數(shù)據(jù)量小考慮ArrayMap數(shù)據(jù)量大或?qū)懖僮黝l繁老老實(shí)實(shí)用HashMap。3. SparseArray內(nèi)部結(jié)構(gòu)深度拆解3.1 二分查找的實(shí)現(xiàn)細(xì)節(jié)SparseArray的查找邏輯集中在ContainerHelpers.binarySearch這個(gè)方法里。它的實(shí)現(xiàn)很樸素就是標(biāo)準(zhǔn)的二分查找但有一個(gè)細(xì)節(jié)值得注意當(dāng)找不到目標(biāo)時(shí)它返回的是目標(biāo)應(yīng)該插入位置的按位取反值。static int binarySearch(int[] array, int size, int value) { int lo 0; int hi size - 1; while (lo hi) { final int mid (lo hi) 1; final int midVal array[mid]; if (midVal value) { lo mid 1; } else if (midVal value) { hi mid - 1; } else { return mid; } } return ~lo; }這個(gè)~lo的返回值設(shè)計(jì)很巧妙。調(diào)用方拿到負(fù)數(shù)就知道沒找到再取反就得到應(yīng)該插入的位置。put方法就是靠這個(gè)機(jī)制來保證數(shù)組始終有序的。實(shí)操心得如果你自己實(shí)現(xiàn)類似的有序數(shù)組結(jié)構(gòu)這個(gè)“返回插入點(diǎn)”的技巧可以直接抄。它避免了查找和插入兩次遍歷在put操作里能省一次二分查找。3.2 put方法的完整流程put方法的邏輯可以拆成幾種情況數(shù)組為空或size為0直接放在索引0二分查找key如果找到直接替換value如果沒找到拿到插入位置判斷是否需要擴(kuò)容如果需要擴(kuò)容先擴(kuò)容再插入如果不需要擴(kuò)容用System.arraycopy把插入位置之后的元素整體后移一位在插入位置寫入key和valuesize加一這里的關(guān)鍵點(diǎn)是數(shù)組移動(dòng)。每次插入新key都要把插入點(diǎn)之后的所有元素后移。如果一直往數(shù)組頭部插入每次都是O(n)的移動(dòng)性能會(huì)急劇下降。所以SparseArray適合的是key分布相對(duì)均勻、插入不集中在頭部的場景。擴(kuò)容策略也值得說一下。SparseArray的初始容量是10擴(kuò)容時(shí)如果當(dāng)前size小于等于4就擴(kuò)到8否則擴(kuò)到size的2倍。這個(gè)策略比HashMap的翻倍擴(kuò)容更保守因?yàn)镾parseArray的數(shù)據(jù)量本來就不大。3.3 delete與remove的差異SparseArray有兩個(gè)刪除方法delete和remove。它們內(nèi)部都調(diào)用同一個(gè)方法但語義上有區(qū)別。delete方法在刪除后如果數(shù)組大小超過一定閾值會(huì)調(diào)用gc方法壓縮數(shù)組。gc方法會(huì)把所有非空的值往前移動(dòng)消除中間的空洞。remove方法在API 24之后和delete合并了行為一致。但要注意SparseArray的刪除并不是立即把數(shù)組縮短而是把對(duì)應(yīng)位置的值置為DELETED標(biāo)記一個(gè)靜態(tài)空對(duì)象然后size減一。真正的數(shù)組壓縮發(fā)生在gc調(diào)用時(shí)。這個(gè)設(shè)計(jì)是為了避免每次刪除都移動(dòng)數(shù)組把多次刪除的移動(dòng)成本合并到一次gc里。public void delete(int key) { int i ContainerHelpers.binarySearch(mKeys, mSize, key); if (i 0) { mValues[i] DELETED; mGarbage true; } }注意如果你在遍歷SparseArray的過程中刪除元素要小心DELETED標(biāo)記的影響。雖然size已經(jīng)減一但底層數(shù)組里可能還有DELETED占位。用size作為循環(huán)邊界是安全的但不要直接訪問mValues數(shù)組。3.4 append方法的優(yōu)化場景SparseArray提供了一個(gè)append方法專門用于key遞增的場景。它的實(shí)現(xiàn)比put簡單得多如果當(dāng)前size為0或者傳入的key大于最后一個(gè)key直接追加到數(shù)組末尾不需要二分查找。public void append(int key, E value) { if (mSize ! 0 key mKeys[mSize - 1]) { put(key, value); return; } if (mGarbage mSize mKeys.length) { gc(); } mKeys GrowingArrayUtils.append(mKeys, mSize, key); mValues GrowingArrayUtils.append(mValues, mSize, value); mSize; }這個(gè)優(yōu)化在什么場景下有用比如你從數(shù)據(jù)庫按id升序讀取一批記錄依次放入SparseArray用append就比put快很多因?yàn)槭〉袅嗣看蔚亩植檎摇?. ArrayMap的實(shí)現(xiàn)原理與性能邊界4.1 雙數(shù)組結(jié)構(gòu)的精妙之處ArrayMap的內(nèi)部結(jié)構(gòu)比SparseArray稍微復(fù)雜一點(diǎn)。它有三個(gè)核心數(shù)組int[] mHashes存放每個(gè)key的hashCode升序排列Object[] mArray交替存放key和value即mArray[2i]是keymArray[2i1]是valueint mSize當(dāng)前鍵值對(duì)數(shù)量為什么要把hash單獨(dú)抽出來一個(gè)數(shù)組因?yàn)槎植檎抑恍枰容^int不需要調(diào)用equals。先用hash定位到候選位置再比較key的equals這樣能減少equals的調(diào)用次數(shù)。對(duì)于String這種equals開銷較大的key類型這個(gè)優(yōu)化很有意義。查找流程是這樣的計(jì)算key的hashCode在mHashes中二分查找hash如果找到拿到索引index比較mArray[2*index]和key是否equals如果equals返回mArray[2*index1]如果不equalshash沖突繼續(xù)向兩邊線性探測這個(gè)線性探測是ArrayMap處理hash沖突的方式。因?yàn)閿?shù)據(jù)量小沖突概率低線性探測的實(shí)際開銷可以接受。4.2 緩存機(jī)制與擴(kuò)容策略ArrayMap有一個(gè)靜態(tài)的緩存數(shù)組用于復(fù)用空數(shù)組。當(dāng)你創(chuàng)建一個(gè)新的ArrayMap時(shí)它不會(huì)立即分配數(shù)組而是指向一個(gè)共享的空數(shù)組。只有在第一次put時(shí)才會(huì)真正分配。這個(gè)設(shè)計(jì)在大量創(chuàng)建臨時(shí)Map的場景下能省不少內(nèi)存。擴(kuò)容策略方面ArrayMap的初始容量是4擴(kuò)容時(shí)翻倍。但它的擴(kuò)容有一個(gè)特殊處理如果當(dāng)前容量已經(jīng)很大超過一定閾值會(huì)嘗試收縮。這個(gè)邏輯在trimToSize方法里也有體現(xiàn)。public void trimToSize() { if (mSize mArray.length / 2) { // 收縮數(shù)組 } }實(shí)操心得如果你確定一個(gè)ArrayMap不會(huì)再添加新元素了調(diào)用trimToSize可以釋放多余內(nèi)存。這在緩存場景下很有用比如你把一批數(shù)據(jù)加載進(jìn)ArrayMap后就不再修改trim一下能省不少空間。4.3 與SparseArray的性能對(duì)比同樣是存1000條int到Object的映射SparseArray和ArrayMap的表現(xiàn)有差異內(nèi)存占用SparseArray更低因?yàn)樗恍枰猰Hashes數(shù)組key直接存在int數(shù)組里查找速度SparseArray略快因?yàn)樯僖淮蝖ash計(jì)算和equals調(diào)用插入速度兩者接近都是O(n)的數(shù)組移動(dòng)通用性ArrayMap支持任意key類型SparseArray只支持int所以選型邏輯很清晰key是int就用SparseArray不是int才考慮ArrayMap。不要因?yàn)锳rrayMap更通用就無腦用它。4.4 什么情況下ArrayMap會(huì)翻車ArrayMap不是銀彈以下幾種情況用它反而更慢數(shù)據(jù)量超過1000。二分查找的O(log n)在n1000時(shí)大約是10次比較在n10000時(shí)是14次。雖然增長不快但每次比較都涉及數(shù)組訪問和可能的equals調(diào)用累積起來就明顯了。更重要的是插入時(shí)的數(shù)組移動(dòng)在數(shù)據(jù)量大時(shí)開銷急劇上升。頻繁插入刪除。每次插入都要移動(dòng)數(shù)組每次刪除都要標(biāo)記和可能的壓縮。如果你的場景是不斷增刪的隊(duì)列或緩存ArrayMap的O(n)操作會(huì)成為瓶頸。多線程并發(fā)讀寫。ArrayMap和SparseArray都不是線程安全的。如果在多線程環(huán)境下使用需要自己加鎖而加鎖后的性能可能還不如直接用ConcurrentHashMap。key的hashCode計(jì)算開銷大。ArrayMap每次查找都要計(jì)算key的hashCode。如果key是復(fù)雜對(duì)象且hashCode方法很重這個(gè)開銷會(huì)累積。HashMap也有這個(gè)問題但HashMap的O(1)查找在數(shù)據(jù)量大時(shí)優(yōu)勢明顯。5. 實(shí)際項(xiàng)目中的選型與優(yōu)化實(shí)操5.1 一個(gè)典型的列表緩存場景假設(shè)你在做一個(gè)聊天記錄列表每條消息有一個(gè)自增的long型id你需要根據(jù)id快速找到對(duì)應(yīng)的消息對(duì)象。數(shù)據(jù)量大概幾百條讀多寫少。這個(gè)場景下SparseArray是首選。但注意id是longSparseArray只支持int。如果id范圍在int內(nèi)可以強(qiáng)轉(zhuǎn)如果超過int范圍需要用SparseLongArray或者自己封裝。SparseLongArray的value是longkey是int不滿足需求。這種情況下可以考慮用LongSparseArrayandroidx.collection提供或者用ArrayMapLong, Message。如果消息數(shù)量穩(wěn)定在幾百條ArrayMapLong, Message的表現(xiàn)也不錯(cuò)。但要注意Long的裝箱問題每次put/get都會(huì)創(chuàng)建Long對(duì)象。如果讀寫非常頻繁這個(gè)裝箱開銷不可忽視。一個(gè)優(yōu)化技巧是緩存常用的Long對(duì)象或者用自定義的long key包裝類。5.2 狀態(tài)標(biāo)記場景的SparseIntArray游戲開發(fā)或復(fù)雜UI中經(jīng)常需要維護(hù)大量狀態(tài)標(biāo)記比如每個(gè)技能是否冷卻、每個(gè)格子是否被占用。這種場景用SparseIntArray或SparseBooleanArray非常合適。SparseBooleanArray occupied new SparseBooleanArray(); occupied.put(3, true); occupied.put(7, true); if (occupied.get(3)) { // 處理 }相比HashMapInteger, BooleanSparseBooleanArray省掉了Boolean的裝箱和Entry對(duì)象在格子數(shù)量多的時(shí)候內(nèi)存優(yōu)勢明顯。而且它的get方法有默認(rèn)值重載get(key, false)在key不存在時(shí)返回false比HashMap的get返回null再判空更簡潔。5.3 遍歷時(shí)的正確姿勢SparseArray和ArrayMap都支持通過索引遍歷這比HashMap的Iterator遍歷更高效因?yàn)椴恍枰獎(jiǎng)?chuàng)建Iterator對(duì)象。for (int i 0; i sparseArray.size(); i) { int key sparseArray.keyAt(i); Object value sparseArray.valueAt(i); // 處理 }但要注意如果在遍歷過程中刪除元素size會(huì)變化可能導(dǎo)致越界或漏遍歷。安全的做法是先收集要?jiǎng)h除的key遍歷結(jié)束后再統(tǒng)一刪除?;蛘哂玫剐虮闅vfor (int i sparseArray.size() - 1; i 0; i--) { if (需要?jiǎng)h除) { sparseArray.removeAt(i); } }倒序遍歷在刪除時(shí)不會(huì)影響未遍歷元素的索引是更安全的做法。注意removeAt和delete的區(qū)別在于removeAt直接操作索引不進(jìn)行二分查找。如果你已經(jīng)知道索引用removeAt更快。5.4 性能測試的實(shí)測數(shù)據(jù)我在一個(gè)模擬項(xiàng)目里做過一組對(duì)比測試環(huán)境是Android 10模擬器數(shù)據(jù)量1000條key為0到999的intvalue為String。測試結(jié)果如下數(shù)值為10萬次操作耗時(shí)單位毫秒操作HashMapSparseArrayArrayMapput順序453842put隨機(jī)48120135get命中122832get未命中102530內(nèi)存占用約80KB約40KB約55KB這組數(shù)據(jù)很能說明問題順序插入時(shí)SparseArray和ArrayMap不輸HashMap但隨機(jī)插入時(shí)因?yàn)閿?shù)組移動(dòng)性能下降明顯。查找方面HashMap的O(1)優(yōu)勢在數(shù)據(jù)量大時(shí)體現(xiàn)出來。內(nèi)存方面SparseArray優(yōu)勢最大。所以結(jié)論很明確數(shù)據(jù)量小且插入有序用SparseArray/ArrayMap數(shù)據(jù)量大或插入隨機(jī)用HashMap。這個(gè)“小”的界限根據(jù)實(shí)測經(jīng)驗(yàn)大約在500到1000之間。低于500SparseArray/ArrayMap的綜合表現(xiàn)更好高于1000HashMap更穩(wěn)。5.5 與其它容器的組合使用實(shí)際項(xiàng)目中很少只用一種容器。常見的組合模式是外層用SparseArray做一級(jí)索引內(nèi)層用ArrayMap或HashMap做二級(jí)映射。比如按類型分組的數(shù)據(jù)外層key是類型idint內(nèi)層key是具體名稱String。這種嵌套結(jié)構(gòu)要注意內(nèi)存的累積效應(yīng)。外層100個(gè)類型每個(gè)內(nèi)層100條數(shù)據(jù)總共就是10000條。這時(shí)候內(nèi)層用HashMap可能更合適因?yàn)閱螌訑?shù)據(jù)量雖然不大但總量上去了HashMap的O(1)查找優(yōu)勢會(huì)體現(xiàn)出來。另一個(gè)技巧是用SparseArray存基本類型數(shù)組。比如SparseArrayint[]key是分組idvalue是該組的原始數(shù)據(jù)數(shù)組。這樣比SparseArrayArrayList 省掉了ArrayList的對(duì)象開銷和Integer裝箱。6. 常見問題與排查技巧實(shí)錄6.1 為什么我的SparseArray越用越慢這是最常見的問題。原因通常是插入模式導(dǎo)致的。如果你的key是隨機(jī)分布的每次插入都可能移動(dòng)大量元素。排查方法是打印插入位置的分布如果集中在頭部就要考慮換數(shù)據(jù)結(jié)構(gòu)。另一個(gè)原因是DELETED標(biāo)記積累。頻繁刪除后沒有觸發(fā)gc底層數(shù)組里全是DELETED占位二分查找雖然不受影響但數(shù)組移動(dòng)時(shí)會(huì)帶著這些占位一起移動(dòng)浪費(fèi)CPU。解決辦法是定期調(diào)用gc或者在刪除量達(dá)到一定比例時(shí)重建SparseArray。6.2 ArrayMap的hash沖突怎么排查ArrayMap在hash沖突時(shí)會(huì)線性探測。如果發(fā)現(xiàn)get操作變慢可能是沖突率太高。排查方法是統(tǒng)計(jì)key的hashCode分布看是否有大量key落在相同的hash值上。一個(gè)常見的坑是用自定義對(duì)象做key但沒有正確實(shí)現(xiàn)hashCode。如果所有對(duì)象的hashCode都返回同一個(gè)值A(chǔ)rrayMap就退化成線性查找性能比ArrayList還差。確保key的hashCode方法遵循標(biāo)準(zhǔn)約定相等的對(duì)象必須有相同的hashCode不相等的對(duì)象盡量有不同的hashCode。6.3 遍歷時(shí)ConcurrentModificationExceptionSparseArray和ArrayMap不像HashMap那樣有modCount檢查所以遍歷時(shí)修改不會(huì)拋ConcurrentModificationException但會(huì)導(dǎo)致不可預(yù)期的結(jié)果。比如你正序遍歷時(shí)刪除了一個(gè)元素后面的元素會(huì)前移導(dǎo)致下一個(gè)元素被跳過。這個(gè)問題的隱蔽性在于它不報(bào)錯(cuò)只是結(jié)果不對(duì)。排查方法是檢查遍歷過程中是否有修改操作。如果有改用倒序遍歷或先收集再處理。6.4 內(nèi)存泄漏的隱蔽來源SparseArray和ArrayMap本身不會(huì)導(dǎo)致內(nèi)存泄漏但如果value持有Context或View的引用而Map的生命周期比它們長就會(huì)泄漏。常見場景是把Map作為靜態(tài)緩存value里存了Activity的引用。排查方法和普通內(nèi)存泄漏一樣用LeakCanary或Profiler抓堆轉(zhuǎn)儲(chǔ)看Map的引用鏈。解決辦法是用WeakReference包裝value或者在合適的生命周期回調(diào)里清空Map。6.5 常見問題速查表問題現(xiàn)象可能原因排查方法解決方案插入變慢key隨機(jī)分布數(shù)組移動(dòng)多打印插入位置換HashMap或調(diào)整key設(shè)計(jì)查找變慢hash沖突多或數(shù)據(jù)量大統(tǒng)計(jì)hash分布優(yōu)化hashCode或換容器遍歷結(jié)果不對(duì)遍歷時(shí)修改了容器檢查遍歷中的修改操作倒序遍歷或先收集后處理內(nèi)存占用高DELETED標(biāo)記積累查看底層數(shù)組長度定期gc或重建內(nèi)存泄漏value持有長生命周期引用堆轉(zhuǎn)儲(chǔ)分析引用鏈WeakReference或及時(shí)清空實(shí)操心得不要憑感覺判斷性能問題。Android Studio的Profiler可以看內(nèi)存分配和CPU耗時(shí)Systrace可以看主線程卡頓。先測量再優(yōu)化最后驗(yàn)證。我見過太多人憑直覺把HashMap換成SparseArray結(jié)果因?yàn)閿?shù)據(jù)量太大反而更慢。6.6 一個(gè)容易忽略的細(xì)節(jié)初始容量SparseArray和ArrayMap都支持預(yù)設(shè)容量。如果你知道大概要存多少條數(shù)據(jù)提前設(shè)置容量可以避免多次擴(kuò)容。SparseArrayObject array new SparseArray(100); ArrayMapString, Object map new ArrayMap(100);但要注意預(yù)設(shè)容量太大會(huì)浪費(fèi)內(nèi)存。SparseArray的擴(kuò)容策略比較保守預(yù)設(shè)一個(gè)略大于實(shí)際需求的容量是合理的。ArrayMap的初始容量是4如果你要存50條預(yù)設(shè)64比讓它從4擴(kuò)到64要快。這個(gè)優(yōu)化在循環(huán)創(chuàng)建Map的場景下效果明顯。比如在Adapter的getView里創(chuàng)建臨時(shí)Map預(yù)設(shè)容量能減少擴(kuò)容次數(shù)降低GC頻率。7. 從源碼看設(shè)計(jì)模式與擴(kuò)展思路7.1 GrowingArrayUtils的復(fù)用設(shè)計(jì)SparseArray和ArrayMap的擴(kuò)容邏輯都委托給了GrowingArrayUtils這個(gè)工具類。它提供了append和grow兩個(gè)方法分別處理追加和擴(kuò)容。這種把通用邏輯抽出來的做法值得學(xué)習(xí)。如果你要自己實(shí)現(xiàn)一個(gè)類似的有序容器可以直接復(fù)用這個(gè)思路把數(shù)組增長、元素插入這些通用操作封裝成靜態(tài)方法容器類只負(fù)責(zé)業(yè)務(wù)邏輯。這樣代碼更清晰也更容易測試。7.2 容器類的線程安全替代方案SparseArray和ArrayMap都不是線程安全的。如果需要在多線程環(huán)境下使用有幾種方案用synchronized包裹所有操作簡單但性能差用ReentrantReadWriteLock讀多寫少時(shí)性能更好用ConcurrentHashMap替代但失去了內(nèi)存優(yōu)勢用ThreadLocal為每個(gè)線程維護(hù)獨(dú)立副本適合讀多寫極少且數(shù)據(jù)可容忍不一致的場景選擇哪種方案取決于你的并發(fā)模式。如果只是偶爾的并發(fā)讀加讀寫鎖就夠了。如果寫操作也很頻繁ConcurrentHashMap是更穩(wěn)妥的選擇。7.3 自定義容器的擴(kuò)展方向理解了SparseArray和ArrayMap的原理后你可以根據(jù)特定需求做擴(kuò)展。比如固定容量的SparseArray避免擴(kuò)容開銷帶LRU淘汰的ArrayMap用于緩存場景支持批量操作的SparseArray減少數(shù)組移動(dòng)次數(shù)帶版本號(hào)的ArrayMap用于快照和回滾這些擴(kuò)展的核心思路都是一樣的在有序數(shù)組的基礎(chǔ)上根據(jù)具體場景調(diào)整插入、刪除、查找的策略。沒有萬能的數(shù)據(jù)結(jié)構(gòu)只有適合特定場景的數(shù)據(jù)結(jié)構(gòu)。7.4 從Android到通用Java的遷移ArrayMap在androidx.collection包里可以脫離Android環(huán)境使用。如果你的Java項(xiàng)目有類似的需求——小數(shù)據(jù)量、讀多寫少、內(nèi)存敏感——完全可以引入這個(gè)依賴。但要注意androidx.collection的ArrayMap和Android框架里的ArrayMap在API上略有差異??蚣馨嬗幸恍〢ndroid特有的優(yōu)化androidx版更通用。遷移時(shí)注意檢查方法簽名和返回值。8. 一些踩過的坑和最后的建議先說一個(gè)我踩過的坑。有一次在一個(gè)列表頁里用SparseArray存Item的狀態(tài)key是position。列表支持拖拽排序每次拖拽后position會(huì)大量變化導(dǎo)致SparseArray里頻繁插入刪除。結(jié)果滑動(dòng)時(shí)明顯卡頓Profiler一看CPU時(shí)間全花在System.arraycopy上。后來換成HashMap問題立刻消失。這個(gè)教訓(xùn)是position這種會(huì)頻繁變動(dòng)的值不適合做SparseArray的key。另一個(gè)坑是關(guān)于DELETED標(biāo)記的。有一次我在遍歷SparseArray時(shí)刪除元素用的是正序遍歷加remove。代碼邏輯看起來沒問題但測試發(fā)現(xiàn)偶爾會(huì)漏掉一些元素。排查了很久才意識(shí)到是DELETED標(biāo)記和數(shù)組移動(dòng)的交互導(dǎo)致的。改成倒序遍歷后問題解決。還有一個(gè)關(guān)于ArrayMap的坑。我用ArrayMapString, Bitmap做圖片緩存key是圖片URL。后來發(fā)現(xiàn)內(nèi)存占用比預(yù)期高很多。原因是ArrayMap的mHashes數(shù)組和mArray數(shù)組都會(huì)隨著數(shù)據(jù)量增長而擴(kuò)容而且不會(huì)自動(dòng)收縮。調(diào)用trimToSize后內(nèi)存降下來了。所以如果你用ArrayMap做緩存記得在數(shù)據(jù)穩(wěn)定后trim一下。最后給幾條實(shí)用建議數(shù)據(jù)量小于500且key是int無腦用SparseArraykey不是int但數(shù)據(jù)量小用ArrayMap數(shù)據(jù)量大于1000或插入頻繁用HashMap遍歷時(shí)刪除用倒序或者先收集后處理預(yù)設(shè)容量能省擴(kuò)容開銷但別設(shè)太大定期trim或gc避免數(shù)組膨脹多線程場景加鎖或換ConcurrentHashMap性能問題先測量再優(yōu)化別憑直覺這些經(jīng)驗(yàn)都是從實(shí)際項(xiàng)目里一點(diǎn)點(diǎn)攢出來的希望能幫你少走些彎路。數(shù)據(jù)結(jié)構(gòu)和算法的選擇從來不是非黑即白理解每種結(jié)構(gòu)的取舍根據(jù)具體場景做判斷才是工程師該做的事。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
亚洲精品一二牛牛| 丝袜翘臀后入欧美校园亚洲自拍另类小说一区中文字幕少妇诱惑 | 狠狠中文字幕| 亚洲国产精品乱码在线观看| 欧美色图人妻| 亚洲人妻爽爽爽| 久久111| 啊啊啊97视频| 偷拍99| 一级性爱网| 波多野结衣一级视频| 韩国一级婬片A片AAAAA| GVH-003 母子姦 青木玲-麻豆视频,麻豆视传媒短视频网站入口,麻豆视传媒官网直 | 9I1性色影院| 亚洲人妻在线精品| 日人妻视频91| 国产极品999| 美女诱惑在线一区| 欧美的精品的视频| 一本色道久久天天射天天干| 久久久久婷婷| 亚洲综合小视频小说在线观看| 精品制服美女中文一区二区三区| 国产91av在线播放| 丰满人妻一区二区三区| 嗯嗯啊啊操死我| 九九热午夜欧亚国产视频| 久久精品店| 一区二区影院| 7月婷婷综合| 亚洲的天堂网| 四虎国产精品永久在线囯在线| 亚洲好看强奸乱伦| 亚洲国产欧美日韩精品一区二区三区,国产一区二区三区在线看片,欧美性猛交 XXX | 在线观看精品国产免费| 啊啊啊啊啊在线观看网址 | 综合一区中亚洲国产成人综合精品| 青草青青久久久久久国产| 牛牛久久国产精品视频一二三| 亚洲天堂一二| 久久精品国产亚洲AV片多多 | 女上位精品在线| 色欲久久久久综合网| 99热婷婷| 锕锕好爽 死我在线观看| 久热最新在线杭州| 日韩中文字幕视频在线观看| 久久久久久波多野吉衣高潮| 99久久99久久免费精品蜜臀| 婷婷三区| 欧美亚洲天天| 国产18精品亚洲精品| 一区二区首页| 国产熟女精品一区二区| 久久久久9| 国产白领连续中出在线播放| 色噜噜狠狠色综无码久久合欧美| 探花精品视频| 欧美亚涩| 久久久久久97| 91女神在线视频| 亚洲性高潮| 亚洲一卡2卡3卡4卡乱码网站 | 精品一级| 另类图片欧美激情综合| 男人的天堂2010| 久久综合久色欧美综合狠狠 | 久草午夜| 啊啊啊好爽快点啊啊啊嗯嗯| 男人的天堂视频精品乱在线| 韩国一级做A片免费的| 日日天天久久啊啊aaa| 欧美伊人电影| 2018色综合天天操| 天天综合站| 欧美性爱精品七区| 亚洲精品欧洲精品| 精品久久久久久无码| 青青欧美在线| 超碰成人人人爽人人爽| 青青国产精品在线| 国产精品无码成人精品| 后X久久| 亚洲欧美电影| 91久青| 在线视频 亚洲精品| 人人摸人人干| 亚洲中文字幕久久无码精品| 色色操| 亚洲小说视频| 色色热| 国产精品福利视频| 草b在线| 亚州欧美在线| 黄色大片一区二区密桃丝袜| 欧美视频一| 日本超碰在线国产一区| 最新无码国产| 噜噜噜亚洲精品| 成人网站 免费观看| 麻豆精品三区视频| 日本一区二区成人在线| 日韩综合97P| 乳欲人妻办公室奶水| 激情四射五月天| 亚洲中文一区二区三区| 国产人人干| 中文自拍欧美影视| 国产呦精品系列在线观看| 四虎永久在线精品免费网址| 国产精品第一页国产大屁股视频免费区| 男人的天堂,欧美亚洲另类国产日韩,日本高清一区二区 | 超碰久久.com| 嗯嗯,啊啊,国产精品| 欧美人人操人人插| 久久久9 9 9精品| 亚洲欧美中文日韩视频中国语| 欧美黄业| 久久九操在线观看| 久久女人视频| 大学生口爆吞精| 精品中文一区二区| 久久久久久AV无码免费网站| 久久免费少妇| 青青草无码视频| 91粉嫩萝控精品福利网站_精品影音先锋国 | 99国产精品久久久在线播放| 亚洲高潮少妇| 天天操人人操狠狠插| 夜夜精品视频一区二区| 亚洲。日韩。欧美| 97人人射| 人人操人人操人人人操| 国产蜜臀精品一区二区尤物| 欧亚不卡| 六月丁香啪啪啪| 亚洲最新Av| 91少妇通奸网站| 美日韩一卡二卡三卡免费人妻精品| 亚洲AV成人无码一二三久久| 日日玩天天干| 九九夜精品九九在线| 人妻少妇av在线观看| 大屁股人妻女教师撅着屁股| 欧美—性—交—色| 日本男人插女人的逼黄色| 日欧操屄视频| 久久久久人妻二区精品叶可怜| 男人天堂无码| 黄色成品网站| 北京专精特新企业招聘信息| 中国探花熟女| 亚洲色 国产 欧美 日韩| 青草精品视频-日本久久久久网站| 午夜欧美女人操逼| 男啪女色黄无遮挡免费观看| 色97欧美| 欧美久久人妻少妇一区二区| 粘花网06av视频| 亚洲经典啪啪| 黄色AAAAA欧美| 欧美91精品国产自产| 妇女乱色二区| 欧美人人天天网| 嗯嗯,啊啊,国产精品| 2018天天日天天日| 中国一级αV| 久超碰这里只有精品| 久久久久久91香蕉国产| 国产丝袜美女诱惑| 丁香五月av| 人妻aa| 一区二区三区在线美女| 精品在线蜜臀| 日韩小电影| 国产97色在线 | 亚洲| AV久日| 91艹逼精品| av天天在线观看| 国产精品亚洲免费| 国产免费久久久久| 成视频在线观看免费看| 99操碰| 亚洲少妇中文字幕网址| 91精品无码人妻系列| 亚洲 自拍偷拍 欧美| 日本孕妇一区二区视频操逼免费看 | 激情五月天婷婷| 天天日B夜夜干B时时操B| 黑人免费福利视频| 国产强奸乱伦第1页| 人妻丝袜一区二区三区在线| 五月天伊人网| 97超碰色色| 鸥美中出| 五月丁香黄色网| 97爱综合| 久久国产免费激情视频| 国产色综合亚洲色综合吹潮| 亚洲97成人在线观看| 久久久9999| 97超碰精品图片| 亚洲欧美清纯| 国产日韩怡红院| 亚洲欧美综合图片| 超碰97国产欧美| 日日骚av| 久久久久久夜夜夜夜夜| 欧美色棕合| 操操碰| 亚洲激情综合| 中文字幕一区av| 激情综合97| 精品人人| 亚洲综合性网址| 国产乱码精品久久久久久 | 国产精品福利资源在线尤物| 少妇一区二区三区精选| 久久久久久人妻一区精品色欧美| 久久亚州精品成人Av无| 亚洲乱伦图片视频| 人妻乱仑一区二区三区| 亚洲成av人片色午夜乱码| 色噜噜综合网| 久久精品国产亚洲AV嘿嘿| 99热精品在线观看| 内射中出日韩在线观看视频| 久操免费电影| 午夜天堂精品久久久久91| 91丨九色丨东北熟女| 99精品久久| 91男女啊啊啊| 美骚妇av高清在线| 欧美玖玖爱免费玖玖| 福利天天都操| 免费操逼91| ,成人免费啪啪视频| 国产成人自拍视频视频| 色综合网1| 2020中文字幕| 久色99999| 蜜乳av一区二区三区四区不卡| 999国产精品999久久久久久| 张柏芝国产一区在线观看| 无码137片内射在线影院| 色天堂在线观看| 欧美在线视频观看一二三四区高清| 一个国产在线综合网站| 日韩中文9| 人人做人人妻人人夜视频| 综合久久97| 成人在线视频网| 黄呦呦在线| 日本成人A片网站| 3PAV乱伦视频| 国产97视频| 久久一二三四五六七八九区| 91N综合网在线| 草久久久| 18岁禁 茉莉成人久久| 操人妻丝袜高跟| 亚洲va综合va国产va中文| 国产成人www免费人成看片| 国产精品亚洲一级av第二区| 日韩免费av片高清无码| 亚洲最大黄网| 九月丁香综合网| 91暧暧| 人妻熟女av国产网站| 亚洲丝袜色| 97色涩| 亚洲成人在线乱码色午夜| 久久伊人最新网址视频| 亚洲黄网在哪免费看| 亚洲国产精品乱码在线观看| 少妇色综合| 91日韩网站| 18禁在线视频| 亚洲情色五月天 | 丁香婷婷激情五月天无毒不卡| 91大香蕉伊人| 日日噜噜夜夜狠狠视频无| 丁香五月婷婷色| 成人在线视频一区| 97九色| 成人三级片无码| 日日天天久久啊啊aaa| 91九色丰满高潮| 国产精品成人久久一区二区三区| 五月婷婷大香蕉| 美女干逼2| 熟妇人妻一区二区| 熟妇人妻精品一区二区| 国产精品自在线发布| 大香蕉 222| 天天综合~91| 一区二区三区探花在线观看| 精爱久久| 久久69| 色墦五月丁香| 三级色影综合网| 人人操人人大香蕉| 欧美日韩亚洲五月天婷婷| 久久AV无码AV| AV九九| 亚洲精品熟妇1区2区3区。| 欧美天天干| 一区二区三区网站日日骚| 粉嫩AV一区二区夜夜| 91天堂色男人的天堂| 青青草精玖玖69精品| 亚洲天天在线| 丝袜六区| 91网站18禁| 女人高潮抽搐喷水视频网站| 伦理弟一页| 国产一区二区三区久久久精品| 丁香五月天婷婷姐| 9Ⅰ老熟女| 久久精品小视频| 一二三区精品视频| 色婷婷狠狠| 欧美激情黑人| 亚洲熟女中文字幕在线| 国产九九九九九九| 日韩精品中文字幕二区| 视频在线97| 自拍偷拍 日韩无码| 欧美久久久| 日韩性爱1级片视频| 精品一区二区三区四区女 | 久久精品三级影视| 热热色国产一二区AV| 日韩人妻中文视频| 久久人体一区二区| 在线精品福利免费播放| 中出在线视频| 国产67194| 欧美激情 亚洲色图| 久久久com| 加勒比色99999| 国产日韩欧美三级片| 亚洲双插| 久久精品亚洲婷婷| 欧洲特黄毛片免费看欧洲毛片| 草b在线| 欧美日韩97| 欧美亚洲激情小说| 黄在线| 九七毛片九九毛片| 91九色在线| 91亚洲图片| 素人播放一区| 亚洲无无码αⅴ每日更新| 久久有码| 国产曰批免费观看久久久| 天综合网欧美| 久久激情视频| 日本一级特级毛片视频| 青青草日本中文字幕| 伊人网综合在线视频| 中文字幕一品色图| 亚洲男人天堂2019| 黄色片A级一区二区三区| 国产欧美成人精品| 网页导航五月天免费一二三区| 美女性91| 歐美一級亂黃99在綫精品| 91香蕉视频在线观看免费| 色五月AV在线| 伊人天堂在线| 干干干天天| 91痴汉| 中日无幕一二三四区| 日韩欧美成人综合在线| 亚洲综合校园春色| 久久男人的天堂国产| 欧美综合国产精品久久丁香| 婷婷五月天色网| 天天射网| 国产AV久久野战精品| 高颜值美女口爆高潮浪叫| 久久久9视频| 国产精品呦一区二区三区| 嫩草黄页| 男人的天堂2018东京热啪啪啪| 手机在线免费看的av| 精品无码产区一区二| 丁香激情五月天| 中文字幕AV乱伦| 精品丰满熟妇人妻一区| 自拍视频大全亚洲专媒视频/一区二区三区 | 深夜激情| 激情欧美日韩女同久久| 亚洲久热| 色综合天天| 啊啊啊啊免费视频| 精品人妻一区春色| 久久久精品国产亚洲伊人| 亚洲欧美综合区自拍另类| 大香蕉日韩| 内射黑丝袜| 日韩pv中文| 亚洲无线码一区国产欧美国| 国产强奸乱伦xd| juliaann欧美丝袜办公室| 亚洲色图国产另类| 99热超碰| 欧美疯狂做爰xxxx| 人妻无一区二区三区| 嗯嗯不要 视频| 91美女色视频亚洲| 91视频国品一二三区| 家庭乱伦性爱av| 草草电影院| 欧美春色| 九九自拍伦理| 99爱久久视频频| 大香蕉av在线| 日韩精品亚洲专区在线影视| 牛牛操视频逼| 热99这里有精品综合久久 | …中文字幕亚洲乱,97人妻无码费视…| 五月激情综合网| 伊人久操| 影音先锋视频在线| 最新日日夜夜天天干干| 呦呦一区| 久久久久久九| 国产精品伦理| 97er欧美性| 欧美综合97www| 天天射影院| 大香蕉丝袜一级片| 免费毛片在线播放| 亚洲成a人在线观看久| 美女操逼A A| 韩国三级色呦呦| 国产精品日日摸天天碰| 久久大香蕉97| 78操B| 97在线观看免费视频l| 综合干干干av久久久综合网 | 青草精品视频-日本久久久久网站| 欧美天天影院| 青青草在线视频美女| 天天操狠狠日夜夜干超大胆开放com大香蕉视频在线观看 | 黄片免费日韩| 97在线观看免费| 无卡一区=区| 91AV天美在线视频| 五月开心久久AV官网| 97视频在线观看播放与子乱对白在线……| 亚洲国产激情国产av| 大香焦A片| 免费αV在线视频| 国产精品分类在线观看| 国产兽交视频在线播放| 三男一女不戴套的A片| 永久电影三级在线观看| 久久丁香久草综合网| 国产无码精品无码| 国产精品爱欲| 手机在线免费看的av| 天天激情干| 久久在线观看免费视频| 三级精品三级在线观看| 俄罗斯一区二区视频在线观看| 久久免费99精品久久久久久| 成人精品一区二区91毛片不卡| 懂色av色欲av蜜臀av| www.av在线视频| 色欲蜜臀AV| 亚洲欧美在线观看2021| 亚洲五月婷| 能看的av| 99.色网| 夜夜福利| 精品国产综合久久福利,热99这里有精品综合久久,99热这里只有免费国产精品,精 | 日本欧美国内在线| 婷婷色导航| 久妇网| 四虎免费看黄| 超碰久草| 亚洲欧洲激情卡通另类文学四射小说网站 | 人妻精品视频一区二区| 人妻AV 中文字幕的| 欧美精品在线观看| 午夜后入| 日韩大香蕉AV影片| 尹人免费观看视频在线| 国产 日韩 欧美 中文 另类,国产 欧美 另类 制服 变态,高清 日韩 欧美 中文,高 | 色吧91| 18禁止看精品中文字幕| 乱伦av麻豆| www.色婷婷.com| 十八禁网站在线| 成人一区二区三区四区| 蜜区区视频79| 国产91影院| 人人操我人人干| 日韩AV熟女乱伦| 亚洲少妇色| 国模不卡一本二本三电影| 久久人妻一区二区三区高清 | 中文字幕人妻资源在线| 日韩国产成人自拍视频| 中文高清一区二区的| 欧美 日韩 另类 亚洲| 蜜桃臀AV在线| 久久在线观看免费视频| 亚洲图片偷拍视频区| 天天综合有色网| 骚货 中文字幕 av| 校园春色五月天| 眼镜人妻101.com| 丁香九月激情啪| 啪啪啪东京| ?亚洲伊人伊成久久人综合网| 久久99黄色卞西瓜| 啊啊啊啊啊啊啊啊啊在线观看| 99av| 自拍偷拍亚洲熟女妇人精品 | 黄色性爱网网| 中文字幕人妻色偷偷久久皮| 啊啊啊好大好深| 午夜无遮挡男女啪啪视频| 五月天色色色| 亚洲人91| 亚洲婷婷丁香在线| 丁香五月电影| 久久水蜜臀亚洲AV无码精品| 国产精品久久久久9999小说| 无码操逼网| 成人精品电影| 久久日韩肥臀| 玖玖爱免费观看视频| 人妻精品一区二区全免费| 欧美三级偷拍| 亚洲毛片一级带毛片基地| 美腿色图| 欧美人妻少妇| 色情五月丁香| 日韩精品人妻系列无码天堂| 水滴偷拍| 中文自拍欧美影视| 91处女视频在线观看| 亚洲麻豆av一区二区| 伊人久久艹| 中文子幕一二三| 八戒午夜福利理论片| 欧美亚洲综合色| 久久久久深夜无码| 99久久婷婷丁香| 91麻豆天美国产欧美日| 伊人性在线视频| 日本熟妇人妻中出视频| 60秒免费小视频| 玖玖久久久| 国产精品老师| 中文字幕日韩情色| 九七超碰人人乐| 国产热RE99久久6国产精品首| 天堂网 主播 亚洲| 午夜AV人气不卡| 韩国三级三级BD在线| 精品九九九九九| 日本人体九九九九九九| 丝袜足交视频| 奸色色 男人天堂 天天射| 不卡视频一区蜜桃视频| 亚洲成人网站在线观看| 人妻夜爽夜夜爽| 成人三级片无码| 日本最新1区2区3区| 二男一女成人A片| 精品视频123区小说区| 天美传媒麻豆一区二区三区国产精| 人人干人人操人人..com| 欧洲自拍色图gif在线| 91精品女厕偷拍视频| 亚州精品丝袜-不卡成人免费| 97无码视频在线播放| 欧美专区第一页| 96久久久久久久| 91丨九色丨东北熟女| 97资源站国产精品| 思思99热| 国产v亚洲v日韩v欧美v片另类| 亚洲欧美一区二区三区在钱蜜桃 | a级免费在线观看| 嗯嗯啊啊啊好舒服| 蜜臀AV秘一区翔田千里| 欧美在线l亚洲| 99精品久久久久久久婷婷| 综合九九| 日欧操屄视频| 色噜噜国产精品视频一区二区| 9久超碰| 97超碰人人模人人拍人人| 中文字幕人妻色偷偷久久皮| 人人操人人干网页| 搡老女人老91妇女熟女| 大香蕉久操| 亚洲欧美伦综合| 99999无码| 日韩黄色av中文字幕| 97超碰超欧美。| 日本韩欧美在线播放a| 怡红院成人视频| 色嘟嘟人妻天堂网| 香伊人在线| Aa东京男人的天堂| 色狠狠色| 欧美一区二区三区不卡高清视频 | 国产精品免费久久久久久久久久| 国产精品交换一区二区| 久久性爱视频免费看| 91在线色| 在线国产一区二区av| 欧美亚洲首页| 欧美 传媒 麻豆 日韩 偷拍| 日日不卡av| 精品夜夜澡人妻无码| AV乱伦国产| 激情四射熟女丝袜| 欧美1727免费观看视频| 伊人黄色片| 婷婷10月天青娱乐| 天天日B狠狠操| 性无码专区2020| 智利AV在线网| 婷婷五月激情综合| 97超碰人人模人人拍人人| 97丝袜亚洲在线播放| 99精品在线| 超碰在线欧美性爱激情| 亚洲999综合| 国内91熟女人妻丝袜天天精品视频在线 | 亚洲欧美九九九| 亚洲五码一区二区三区| 免费观看一区| 97网址97| 亚洲精品97在线| 浓厚中出中文字幕在线| 神马久久免费电影观看| AV天堂男人的天堂| 色99在线| 国产辣妈在线视频福利| 老鸭窝成人| 亚州再线| 99精品视频在线观看| 岛国在线免费视频| 日韩9区| 另类专区加勒比| 午夜情侣自拍网站| 亚洲aV无码成人在线观看| 成人毛片免费| 午夜操一视频一区| 麻豆伊人网| 玖玖97综合 | 国产最火爆久久国产网站网站| 日本二区不卡| 人妻人人澡人人爽人人| 精品少妇后入一区二区三区四区人妻巨乳| 综合操逼| 五十路六十路素人熟女| 欧美少妇人妻| 国产精品午夜福利| 久久久久9999精品九九九| 中文字幕国产精品1区| 伦理片秋霞免费影院| 一区二区三区黄片免费观看| 欧美精品成人一区二区在线观看 | 久久久久久国产无码精品| 中文字幕女同在线| 97一区二区蜜臀| 一本道综合色图| 91动漫操逼视频| 中文字幕精品一区二区精| 蜜臀无码视频在线观看| 青娱乐妇女性生活| 日韩精品人妻中文字幕不卡乱码| 我中文字幕6区 | 亚欧美色图| 欧美乱妇狂野欧美在线视频| 亚洲AV资源| 日韩精品一区二区三区四虎影视| 亚洲欧美经典一区二区| 亚洲欧美在线观看2021| 波多野42部无码喷潮在线观看| 日本孕妇一区二区视频操逼免费看| 一本色道久久综合精品婷婷| 欧美美逼| 欧美在线中M| 欧美78| 国产丰满熟夫69mpp| 97二区四区| 爱爱动态120秒| 久久大香蕉手机高清| 成人婷婷丁香| 99激情视频| 色玖玖| 99爱精品| 伊人久久大香线蕉无码| 国产性爱在线视频一区二区| 亚洲欧美日韩免费电影| 黄色人人| 国产日韩在线播放av| 黄色大片免费在线| 久久久久人妻二区精品叶可怜| 亚洲国产成人精品久久久国产成人一区二区| 十八禁一区二区无码观看| 69久久久久久久久久久久久| 亚洲日韩熟女人妻高清在线| 99精品高潮| 99热18这里只有精品| 色大师网站www永久网站视频| 超碰在线97国产| 九九九精品一区二区无码| 日韩精品三级片长长久久| 亚洲 另类 丝袜 自拍 动漫| 91色色综合| 亚洲色图第一页| 国产视频97| julia国产在线 | 十八禁的黄污污免费网站| 天天综合网合集91| 国产乱码精品久久久久久| 一级黄碟| 亚洲国产97在线精品一区| 亚洲男人天堂视频| 成人区人妻精品一| 亚洲精品97久久中文字幕| 亚洲天堂资源在线| 蜜臀久久99精品久久久久| 欧洲性爱无码区| 国产精品人人爽人人做可爱福利| WWW操逼| 国产操操日韩三级黄| 熟女人妻一区二区三区| 色婷婷在线视频| 97干在线看| 日日夜夜噜| 四季AV一区二区凹凸精品小说| 日韩淫色网| 麻豆一区二区三区在线看 | 无码天天操| 久久亚洲AV成人精品无码| 亚洲av强奸乱伦| 少妇诱惑视频| 91男同| 最新AV在线| 一级性爱视频免费在线| 欧美日韩黄片精品在线| 国产伦精品一区二区三区在线观 | 黑人精品欧美一区二区蜜桃| 欧美熟妇精品黑人巨大91| 性videos欧美熟妇hdx| 无码人妻丰满热妇又大又粗| 激情小说五月天| 色性欧美| 国产第二页| 天天色欧美| 日本操色导航| 亚洲高潮少妇| 97频视在线| 精品午夜福利| 一区操逼日比视频| 性吧在线视频| 黑人精品久久97| 四方色播| 边做饭边操逼逼| 欧美强奸一区二区诱惑| 大香蕉手机在线视频| 欧美在线视频播放| 欧美少妇色图| 新婚人妻扶着粗大强行坐下| 婷婷色色网| 嗯嗯啊啊视频一区二区三区| 超碰97日韩| 国产毛片在线| 精品久久久九九九孕妇| 亚洲另类色综合网站| 88xx成人精品视频| 免费黄色片子| 99只有精品| 亚洲少妇色| 亚洲一二三四区在线免费看视频| 中文字幕第9页萱萱影音先锋| 伊人五月天激情| 日本少妇va7777| 欧美色91| 日日操丁香五月天| 欧洲射精91| 天天狂操夜夜狂日| 夜嗨影院| 国产suv精品一区二区四| 偷拍亚洲视频一区二区三区四区| heyZO天然素人无码AⅤ专区| 91N欧美| 国产第11页| 91看黄片| 婷婷99狠狠| 成人熟女区| 日本淫乱女一区二区三区视频| 在线国产探花| 国产视频第2页| 国产精品无码成人精品| 国产精品麻豆成人AV艾秋| 蜜臀久久久国产| 国产三级片在线观看| 国产精品香蕉热久久新品| 久热精品色情| 欲香欲色| 国模精品一区二区三区苹果色戒| wuyechaopeng| 欧美色视频在线| 亚洲一二三四区机械| 天天拍夜夜| 五月婷婷丁香| 大香蕉在线SuP| 懂色av色欲av蜜臀av| 97久久精品国产| 国产捆绑一区| 久久久久国产精品片区无码直播| 淫乱图区 | a级理论午夜日本| 九一性生活免费视频| 人人摸.人人色| 久久超碰97中文字幕| 蜜臀无码视频在线观看| 成人在线视频二区| 亚洲久久久| 亚洲精品99| 蜜臀99久久国产| 丁香五月天堂| 婷婷性网| 天天爽天天| 超碰在线在公开超碰在线在公开| 岛国黄色大片网站| 男女性扦B| 国产原创剧情在线丝袜| 哑洲在线| 新版天堂中文资源8在线| 碰碰在线视频| 欧美后入式| 综合色啪| 日韩久射综合| 婷婷伊人綜合中文字幕| 69丨亚洲丨精品丨入口免费播放| 日韩在线观看字幕精品| 九九久精品| 操99| 伊人超碰97| 九九玖玖精品| 黄色免费一级在线毛片| 狠狠热这里都是精品| av爱爱爱| 欧美夜夜骑视频| 中文字幕日韩人妻视频一区二区三区| 狠操91,com| 久久精品国产72国产精品福利| 欧洲Au麻豆| 天天艹天天日| 色五月激情AV在线| 国产精选三级在线观看| 久久精品噜噜噜成人看免欧美大片| 2010男人的天堂| 婷婷婷婷婷婷久久久久| 69人妻精品丰满熟女区| 精品国产一区二区三区四区在线看 | 亚洲色图综合网| 国产高清精品一区二区三区毛片 | 欧美一二三级精品在线| 亚州欧美总和| 国产免费永久精品无码| 97久久超碰日韩精品| 插入综合网| 少妇厨房愉情理伦片bd在线观看| 亚洲性图91| 日本岛国黄色网址| 超碰九7免费| 97爱亚洲综合色| 岛国AB视频| 大逼色网站| 男人的天堂成人的社区| A片大香蕉在线| 欧美性综合| www.夜夜操| 午夜乱轮操逼视频免费看| 天天躁夜夜躁狠狠躁AV| 国产懂色精品国产av| 日韩有码专区| 性在久久久久久| 午夜精品五区| 99国产精品| 欧美在线电影| 欧美色图电影| 国产精品久久久999| 久久六六| 91久久精品国产| 午夜天堂啪啪| 精品黄色电影| 亚熟hd视频在线| 超碰在线91| 国产无码高清操逼视频| 欧日韩一二三f区| 天天干一区二区| α√在线| 精品91| 亚洲视频二区| 大香蕉五月天婷婷| 免费家庭乱伦视频| 极品一区二区三区免费| 91色噜噜狠狠| 色婷婷九月| 日韩无码a片| 手机在线大香蕉| 国产免费一区| 91女网站| 日韩女模中文造逼| 精品无码一区二区三区| 色九九久九九| 天天干天天日天天射黄色片| 99在线精品视频| 一级黄色视频网| 91在线免费精品视频| 人人九九精| 亚洲少妇色图自慰直播| 嫩草一区二区在线观看| 视频不卡中文字幕| 国产亚热在线久久| 色999偷自拍拍| 国产成人网址| 蜜臀一区二区三区在线 | 97色在线| 久热香蕉精品在线视频| 97久久久久| 91影视亚洲| 久久久久久久久久久久黄色| 嗯嗯啊中文字幕| 黄片不用下载在线观看| 91精品人妻一区二区三区蜜桃| 久久久久久久9最新免费视频观看| 97玖玖人妻| 99综合视频一体| 加勒比久久综合网高清| 欧美日韩国产另类综合| 蜜臀在线视频| 天天网综合| 四虎免费在线播放| 极品一区二区三区免费| 亚洲色图国产另类| 九一亚洲国产免费| 能看的av| 欧美人人AAA| 超碰在线香蕉| 国产日韩在线播放av| 国产精品夜夜| 天天日天天看| 欧美性生活内射| 玖玖蜜臀资源网| 午夜成人福利影视| 殴美牲| 韩国一区二区精品亚洲| 思思热在线视频精品| 日本精品成人无码| AV免费在线播放一区| 亚洲图片日本AⅤ欧美在线| 日本中文熟女视频| 91在线免费精品视频| 78久久| 欧美激情片一区二区| 婷婷亚洲综合| 色五月激情网| 成人片在线播放| 国产一区二区在线电影| 国产精品久久久久中文字幕| 亚洲国产成人福利在线观看| 八戒午夜福利理论片| 欧美精品23| 成人免费视瓶| 一级日本牲交大片好爽在线看| 东北毛片| 国产偷人伦激情在线观看| 日韩久射综合| 中国特猛少妇色xxx| 97视频免费| 欧美天天综合在线| 久热一区二区| 久久久精品网站| 亚洲在线网站| 尹人免费观看视频在线| av在线播放国产一区| 黄视频免费| 日本操逼视频不卡直接放| 影音先锋少妇| av无码精品久久久久| 欧洲一级性爱视频在线观看| 色色五月天激情| 人人操AV| 超碰日本97美女人妻人人玩人人爱 | 人人人干干人人干| 国产精品精品系列在线观看| 精品无码欧美三级| 91午夜无码| 日韩丰满熟妇| 色五月激情网| 色一情一乱一乱一区91Av| 午夜婷婷| 免费农村成人少妇人妻Aa一区二区视频| 亚洲日本加勒比在线| 久久久久久久 九九九九九九九| 亚射在线| 神马久久69| 人人九九精| 97久久国产| 成年人网站在线免费观看| 人妻 丝袜美腿 中文字幕| 日韩性爱免费视频在线网站| 日韩国产中文字幕| 小草精彩毛片| 国模不卡一本二本三电影| 日韩中文字幕宗合在线| 欧美性少妇| 国产精品96久久久久久| 乱操乱伦AV| 波多野结衣被操50分钟免费视频| 丰满高潮18xxxx| 涩五月婷婷| 打av高清| 夜夜青青无码影院| 欧美色九九| 五月天伊人网| 另类TS人妖一区二区三区| 在线岛| 91人妻Pr| 91逼逼女人91| 熟女一区二区三区四区| 78超碰| 另类TS人妖一区二区三区| 熟女突然公开看18禁影片| 天天影视色香色欲| 欧美色日本| 午夜噜噜噜| 亚洲日本激情| 欧美性爱在线无码| 99天天超碰| 东京男人天堂| 在线播放成人高清免费视频| 最新国产精品久久精品| ss久久| 天欧美在线| 男人天堂2017| 美女上床网站| 久久久少妇| 欧美色性爱| 亚洲欧美中日韩| 熟女熟妇伦久久影院毛片一区二区| 插入逼91| 男人的天堂一区三区| 中文字幕一区二区三区人妻少妇在线 | 欧美激情一区| 91天堂色男人的天堂| 熟妇人妻一区二区| 久久人妻一区二区三区高清| 天堂无码| 五月婷婷啪啪| 亚洲第91页| 日韩在线国产字幕| 国产激情av女片自拍| 精品久久久中文字幕不| 亚洲黄色电影| 黄在线| 九九九综合精品| 蜜汁欧美| 久操视频资源站公开| 日本三级人妻a人妻一在线| 舔人妻中文免费视频| 亚洲字幕一区二区| 国产超碰国产97| JuliaAnnXXX888| 欧美大香蕉同搞| 天堂资源欧美| 欧美中文综合| 国产精品久久久三级无码| 美女毛片999| 偷拍视频青青草在线视频| 国产女人91精品嗷嗷嗷嗷| 无码91| 国产熟女一区二区| 国产伦乱91| 熟妇人妻一区二区三区| 美女黄页网站| 久久这里只精品99re66图| 一直超碰| 视频国产成人精品日本亚洲18| 99无码视频| 欧美成人精品一区二区男人蜜臀| 摸奶性爱视频网站在线免费播放| 国产原创自拍| 强乱老妇中文字幕| 人人干人人操人人..com| 日韩精品大香蕉伊人在线| 91丨九色丨国产丨人妻在线 | 青青国产精品在线| 亚洲欧美综合网| 看日韩操逼| 熟女91网| 强奸乱伦Av网| 亚洲情色在线| 久久久久久久久久久免费精品| 无码色| 九月伊人中文字幕| 精品区9| 熟女少妇视频| www.久久99| 99热国产精品| 免费看A片毛毛片在线播| 国产白领连续中出在线播放| 91啦人妻| 啊啊啊97视频| 99久久精品无码一区二区毛片免费 | 欧美亚洲涩涩| 操少妞在线视频| 97碰碰日本乱偷人妻中文的| 蜜臀无码视频在线观看| 天天操狠狠日夜夜干超碰撸com视频在线观看 | 激情露脸爱| 日本一区二区不卡| 丝袜六区| 99婷婷一区二区| 德国一二三不卡| 看全色黄大色大片免费视频| 2020中文字幕| 欧美亚洲综合高清在线| 大香蕉AV丝袜| 日本影视久久免费| 中文字幕丝袜人妻| 2017人人操,人人摸| 精品一久久久| 无码精品一区二区三区潘金莲| 男人天堂久久精品不卡| 91成人精品在线播放| 午夜九九| 精品高清一区二区三区三州| 久久久久国产| HEYZO高无码国产精品227| 哑洲在线| 午夜天堂精品久久久久91| 91久热| 久久久无码国精品无码三区三区| 亚洲学生妹高清av| 黄色二级片网站| 91岛国动作片| 夜夜操老骚逼视频网站| 激情黄色片在线观看| 丝袜美腿射精91| 国产精品成人蜜臀AV在线|