日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

给大忙人看的Java核心技术笔记(8、Stream)

發(fā)布時(shí)間:2025/3/21 java 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 给大忙人看的Java核心技术笔记(8、Stream) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  流提供了數(shù)據(jù)視圖,讓你可以在比集合更高的概念層上指定操作。使用流只要指定做什么,而不是怎么做。將操作的調(diào)度執(zhí)行留給實(shí)現(xiàn)。

要點(diǎn):

  1、迭代器使用了一種明確的遍歷策略,同時(shí)也阻止了高效的并發(fā)執(zhí)行

  2、你可以從集合、數(shù)組、生成器或迭代器創(chuàng)建流

  3、使用過(guò)濾器filter來(lái)選擇元素,使用map進(jìn)行元素轉(zhuǎn)換

  4、對(duì)于轉(zhuǎn)換流的其他操作還包括limit、distinct、sorted

  5、要從Stream中獲得結(jié)果,請(qǐng)使用規(guī)約操作(reduction operation),如count、max、min、findFirst、findAny。這些方法中的一些會(huì)返回Optional類型值。

  6、Optional類型是作為處理null值而提供的一個(gè)安全替代者。想要安全地使用它,需要借助于ifPersent和orElse方法。

  7、你可以收集集合、數(shù)組、字符串或者map中的Stream結(jié)果。

  8、Collections類的groupingBy方法和partitioningBy方法允許你將流的內(nèi)容劃分成組,然后獲得每個(gè)組的結(jié)果。

  9、針對(duì)基本數(shù)據(jù)類型如int、long、double,java提供了專門的流

  10、并行流自動(dòng)將流操作并行化

1、從迭代到stream

1 //統(tǒng)計(jì)一本書(shū)中所有長(zhǎng)單詞 2 String contents = new String(Files.readAllBytes(Paths.get("alice.txt")), StandardCharsets.UTF_8);//將文件讀入字符串 3 List<String> words = Arrays.asList(contents.split("\PL+"));//拆分成單詞 4 int count = 0; 5 for(String w : words){ 6 if(w.length()>12) count++; 7 } 8 9 long count = words.stream().filter(w->w.length()>12).count();

  用words.parallelStream()就會(huì)使得流類庫(kù)并行地進(jìn)行過(guò)濾和計(jì)數(shù)操作。

  Stream遵循“做什么,而不是怎么去做”的原則。不要指定那個(gè)線程,怎么完成,執(zhí)行順序和執(zhí)行線程都會(huì)自動(dòng)由Stream實(shí)現(xiàn),相比自己定義實(shí)現(xiàn)則會(huì)放棄了優(yōu)化的機(jī)會(huì)

  流表面上與集合相似,允許轉(zhuǎn)換和檢索數(shù)據(jù)。然而兩者卻有明顯不同:

  1、流不存儲(chǔ)元素,他們存儲(chǔ)在底層的集合或者按需生成。

  2、流操作不改變他們的數(shù)據(jù)源。例如,filter方法不會(huì)從一個(gè)新流中刪除元素,而是生成一個(gè)不包含特定元素的新流。

  3、如果可能的話,Stream操作可能是延遲執(zhí)行的。這以為著直到需要結(jié)果的時(shí)候,方法才會(huì)執(zhí)行。

  流的典型工作流程

  1、創(chuàng)建一個(gè)stream

  2、強(qiáng)初始流轉(zhuǎn)換成其他流的中間操作,可能需要多步操作(filter方法返回另一個(gè)流)

  3、應(yīng)用終止操作產(chǎn)生結(jié)果。該操作強(qiáng)迫懶惰操作進(jìn)行執(zhí)行。在這之后流就不會(huì)再應(yīng)用到了(count方法將流歸納為一個(gè)結(jié)果)

2、創(chuàng)建Stream

  用Collection接口的Stream方法將任何集合轉(zhuǎn)化成Stream。用Stream.of方法將一個(gè)數(shù)組轉(zhuǎn)化為Stream。

1 Stream<String> words = Stream.of(contents.split("\\PL+"));//splits方法返回String[]

  用Arrays.stream(array, from, to)方法將數(shù)組的一部分轉(zhuǎn)換成Stream。用Stream.empty方法創(chuàng)建一個(gè)空的流。

  創(chuàng)建無(wú)限Stream的靜態(tài)方法。

    generate方法接受一個(gè)無(wú)參的函數(shù)(Supplier<T>接口的對(duì)象)

1 //創(chuàng)建一個(gè)常量值的Stream 2 Stream<String> echos = Stream.generate(()->"echo"); 3 //創(chuàng)建一個(gè)含有隨機(jī)數(shù)的Stream: 4 Stream<String> randoms = Stream.generate(Math::random);

    interate方法,接受一個(gè)種子值和一個(gè)函數(shù)(UnaryOperator<T>接口的對(duì)象)并會(huì)對(duì)之前的值重復(fù)應(yīng)用該函數(shù)

1 Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO, n-> n.add(BigInteger.ONE)); 2 //Pattern類有一個(gè)方法可以按照正則表達(dá)式對(duì)字符串進(jìn)行分隔 3 Stream<String> words = Pattern.compile("\\PL+").splitAsStream(contents); 4 //靜態(tài)方法Files.lines返回了一個(gè)包含文件中所有行的結(jié)果 5 try(Stream<String> lines = Files.lines(path)){ 6 //對(duì)lines進(jìn)行處理 7 }

3、filter、map、flatMap方法

  filter轉(zhuǎn)換生成一個(gè)匹配一定條件的新流

//將字符串流轉(zhuǎn)換成另一個(gè)只包含長(zhǎng)單詞的流 List<String> words = ...; Stream<String> longWords = word.stream().filter(w->w.length()>12);

  filter的參數(shù)是一個(gè)Predicate<T>對(duì)象(從T到boolean的函數(shù))

  我們經(jīng)常需要將一個(gè)流中的值進(jìn)行某種形式的轉(zhuǎn)換,這是用map方法,并且傳遞給它一個(gè)執(zhí)行轉(zhuǎn)換的函數(shù)

//將單詞轉(zhuǎn)換成小寫(xiě) Stream<Stream> lowercaseWords = words.stream().map(String::toLowerCase); //產(chǎn)生每個(gè)單詞第一個(gè)字母的流 Stream<String> firstLetters = words.stream().map(s -> s.substring(0,1)); public static Stream<String> letters(String s){List<String> result = new ArrayList<>();for(int i=0;i<s.length();i++){result.add(s.substring(i,i+1)); } return result.stream(); } //等同于 Stream<Stream<String>> result = words.stream().map(w->letters(w)) //將返回一個(gè)包含多個(gè)流的流,如果要展開(kāi)為一個(gè)只包含字符串的流則可以使用flatMap方法而不是map方法 Stream<String> flatResult = words.stream().flatMap(w->letters(w)); //在每個(gè)單詞上調(diào)用letters方法,并展開(kāi)結(jié)果

4、提取子流和組合流

  stream.limit(n)會(huì)返回一個(gè)包含n個(gè)元素的新流(如果原始流的長(zhǎng)度小于n,則會(huì)返回原始流)

1 Stream<Double> randoms = Stream.generate(Math::random).limit(100);

  stream.skip(n)正好相反,它會(huì)丟棄前n個(gè)元素。

Stream<String> words = Stream.of(contents.split("\\PL+")).skip(1); //可以使用Stream類中的靜態(tài)方法concat將兩個(gè)流連接起來(lái) Stream<String> combined = Stream.concat(letters("Hello"), letters("World")); //生成流["H","e","l"......] //當(dāng)然第一個(gè)流不是無(wú)限的,否則第二個(gè)流永遠(yuǎn)沒(méi)有機(jī)會(huì)添加到第一個(gè)流后面

5、其他流轉(zhuǎn)換

  distinct: 對(duì)于Stream中包含的元素進(jìn)行去重操作(去重邏輯依賴元素的equals方法),新生成的Stream中沒(méi)有重復(fù)的元素;

  對(duì)于Stream排序來(lái)說(shuō),java 9 提供了多個(gè)sorted方法。其中一個(gè)實(shí)現(xiàn)了Comparable接口的流,一個(gè)接受一個(gè)Comparator對(duì)象

1 //最長(zhǎng)的單詞會(huì)出現(xiàn)在第一個(gè)位置 2 Stream<String> longestFirst = words.stream().sorted(Comparator.comparing(String::length).reversed());

  peek: 生成一個(gè)包含原Stream的所有元素的新Stream,同時(shí)會(huì)提供一個(gè)消費(fèi)函數(shù)(Consumer實(shí)例),新Stream每個(gè)元素被消費(fèi)的時(shí)候都會(huì)執(zhí)行給定的消費(fèi)函數(shù);

  

Object[] powers = Stream.iterate(1.0, p->p*2).peek(e->System.out.println("Fetching" +e)).limit(20).toArray(); //每當(dāng)檢索到一個(gè)元素就會(huì)調(diào)用peek里面的方法,一般用于調(diào)試,可以在peek調(diào)用的方法中設(shè)置斷點(diǎn)。

6、簡(jiǎn)單歸約

  從流中或的返回值,稱為歸納方法(reduction)。規(guī)約是終止操作,可以將流歸納為一個(gè)可以在程序中使用的非流值。

  count:返回流中元素的數(shù)目

  max,min:返回流中的最大值或最小值。

  這些方法會(huì)返回一個(gè)Optional<T>類型的值,他可能是一個(gè)封裝類型的值,或這是沒(méi)有返回值。Optional類型是一種更好的表明缺少返回值的方式。

1 Optional<String> largest = words.max(String::compareToIgnoreCase); 2 System.out.println("largest" +largest.getOrElse(""));

  findFirst方法返回非空集合中的第一個(gè)值,通常與filter方法結(jié)合起來(lái)使用。

1 Optional<String> startsWithQ =words.filter(s -> s.startsWith("Q")).findFirst();

  如果想找到任何一個(gè)匹配的元素,而不必是第一個(gè),則使用findAny方法,該方法在對(duì)流進(jìn)行并行執(zhí)行時(shí)非常有效

  如果只想知道流中是否含有匹配元素,則使用anyMatch方法。這個(gè)方法接受一個(gè)predicate參數(shù),所以不需要使用filter方法

boolean aWordStartsWithQ = words.parallel().anyMatch(s->s.startsWith("Q"));

  如果所有元素都跟predicate匹配的話,allMatch方法將返回true,如果沒(méi)有元素匹配的話,nonematch方法返回true。

  兩個(gè)方法都可以通過(guò)并行執(zhí)行提高速度。

7、Optional類型

  Optional<T>對(duì)象是一個(gè)T類型對(duì)象或者空對(duì)象的封裝。Optional<T>類型是要么指向?qū)ο笠礊閚ull的T類型引用的安全替代者。

1 //封裝的字符串,如果沒(méi)有的話則為空字符串“” 2 String result = optionalString.orElse(""); 3 //也可以調(diào)用代碼來(lái)計(jì)算默認(rèn)值,函數(shù)只有在需要時(shí)才會(huì)被調(diào)用 4 String result = optionalString.orElseGet(()->System.getProperty("user.dir")); 5 //提供了一個(gè)可以產(chǎn)生異常對(duì)象的方法 6 String result = optionalString.orElseThrow(IllegalStateException::new);

  ifPresent方法接受一個(gè)函數(shù),如果Optional值存在的話,他會(huì)被傳遞給函數(shù);否則的話,不進(jìn)行任何處理。

optionalValue.ifPresent(v->Process v);

  如果你希望當(dāng)值存在時(shí)將其添加到一個(gè)集合中,可以調(diào)用:

optionalValue.ifPresent(v->results.add(v)); //或者簡(jiǎn)單點(diǎn) optionalValue.ifPresent(results::add);

  當(dāng)調(diào)用ifPresent方法時(shí),函數(shù)不會(huì)返回任何值。如果想對(duì)函數(shù)結(jié)果進(jìn)行處理,則使用map方法:

  Optional<Boolean> added = optionalValue.map(results::add)

  add方法的值有3種可能性:封裝到Optional中的true或者false;如果optionalValue存在,或者是一個(gè)空的Optional值。

  創(chuàng)建Optional類型值有兩個(gè)靜態(tài)方法:Optional.of(result)和Optional.empty()

1 public static Optional<Double> inverse(Double x){ 2 return x ==0 ? Optional.empty() : Optional.of(1/x); 3 }

ofNullable方法被設(shè)計(jì)為null值和可選值之間的一座橋梁,obj不為null,Optional.ofNullable(obj),則會(huì)返回Optional.of(obj);否則返回Optional.empty()

Stream的flatMap方法,通過(guò)展開(kāi)方法所返回的流,將兩個(gè)方法組合起來(lái)。

  假設(shè)f返回T,g返回U。則可調(diào)用s.f().g()將兩個(gè)方法組合起來(lái),返回T

  如果f返回Optional<T>,g返回Optional<U>,就不能調(diào)用s.f().g()

    可以調(diào)用  Optional<U> result = s.f().flatMap(T::g);

如計(jì)算平方根:

public static Optional<Double> squareRoot(Double x){return x<0? Optional.empty() : Optional.of(Math.sqrt(x)); } //這樣可以計(jì)算反轉(zhuǎn)值得平方根 Optional<Double> result = inverse(x).flatMap(MyMath::squareRoot); //或者 Optional<Double> result = Optional.of(-4.0).flatMap(Demo::inverse).flatMap(Demo::squareRoot);

8、收集結(jié)果

  調(diào)用iterate方法生成一個(gè)能夠訪問(wèn)元素的傳統(tǒng)迭代器。

  調(diào)用forEach方法作用于沒(méi)一個(gè)元素,在并行流上forEach方法可以以任意順序便利元素,但是想按順序處理需要用forEachOrdered方法。

stream.forEach(System.out::println);

  調(diào)用roArray獲得一個(gè)含有流中所有元素的數(shù)組。

1 String[] result = stream.toArray(String[]::new);

  調(diào)用collect方法,傳入Collectors類將流放到目標(biāo)容器中

List<String> result = steam.collect(Collectors.toList()); Set<String> result = stream.collect(Collectors.toSet()); TreeSet<String> result = stream.collect(Collectors.toCollection(TreeSet::new)); //字符串拼接起來(lái) String result = stream.collect(Collectors.joining()); //元素間插入分隔符 String result = stream.collect(Collectors.joining(",")); //如果流包含字符串以外對(duì)象,首先將他們轉(zhuǎn)換成字符串 String result = stream.map(Object::toString).collect(Collectors.joining(","));

  如果想將流規(guī)約為總和、平均值、最大值、最小值,則用summarizing方法

1 //用summarzing(Int|Long|Double)方法返回(Int|Long|Double)SummaryStatistics類型結(jié)果 2 IntSummaryStatistics summary = stream.collect(Collectors.summaringInt(String::length)); 3 double averageWordLength = summary.getAverage(); 4 double maxWordLength = summary.getMax();

9、將結(jié)果收集到Map中

Map<Integer, String> idToName = people.collect(Collectors.toMap(Person::getId, Person::getName)); //如果設(shè)置Map的值為實(shí)際people中的對(duì)象 Map<Integer, String> idToName = people.collect(Collectors.toMap(Person::getId, Function.identity())); //如果多元素?fù)碛邢嗤逆I,會(huì)出異常,則提供第三個(gè)參數(shù),更具已有的值和新值,來(lái)決定鍵的值。

解決鍵沖突問(wèn)題,可以看P270,上網(wǎng)搜索下Collectors.toMap方法。

使用toConcurrentMap方法可以生成一個(gè)并發(fā)的map。

10、分組和分片

  使用groupingBy方法,對(duì)Map進(jìn)行分組

1 Map<String, List<Local>> countryToLocales = locales.collect(Collectors.groupingBy(Locale::getCountry)); 2 //Locale::getCountry是分組的分類函數(shù) 3 List<Locale> swissLocales = countryToLocales.get("CH");

  ※每個(gè)語(yǔ)言環(huán)境都有一個(gè)語(yǔ)言代碼(en)和地區(qū)碼(US)。en_us代表美國(guó)英語(yǔ),en_zh代表中國(guó)英語(yǔ)

  當(dāng)分類函數(shù)是一個(gè)predicate(斷言)函數(shù)時(shí)(返回一個(gè)布爾值的函數(shù)),流元素被分成兩組列表,一組返回true的元素,另一組是返回false的元素。這時(shí)用partitioningBy比使用groupingBy更有效率。

//將所有語(yǔ)言環(huán)境分為英語(yǔ)和使用其他語(yǔ)言 Map<Boolean, List<Locale>> englishAndOtherLocals = locals.collect(Collections.partitioningBy(l->l.getLanguage().equals("en"))); List<Locale> englishLocales = englishAndOtherLocales.get(true);

  調(diào)用groupingByConcurrent方法,將會(huì)得到一個(gè)并發(fā)映射。當(dāng)與并行流一起使用時(shí),可以并發(fā)地插入值。

11、下游收集器

  groupingBy方法產(chǎn)生一個(gè)值為列表的map對(duì)象。如果想以某種方式處理這些列表,則提供一個(gè)下游(downstream)收集器。

  如:想讓map中的值是set類型而不是list類型,則可以使用Collectors.toSet方法:

Map<String, Set<Locale>> countryToLocaleSet = locales.collect(groupingBy(Locale::getCountry, toSet()));//Java 8還提供了以下幾個(gè)收集器用來(lái)將分組元素“歸約”成數(shù)字//counting會(huì)返回所收集元素的總個(gè)數(shù)。 Map<String, Long> countryToLocaleCounts = locales.collect(groupingBy(Locale::getCountry, counting())); //summing(Int|long|Double)接受一個(gè)函數(shù)作為參數(shù),然后將函數(shù)應(yīng)用到downstream元素上,并生成他們的求和。 Map<String, Integer> stateToCityPopulation = cities.collect(groupingBy(City::getState, summingInt(City::getPopulation))); //計(jì)算每個(gè)州下屬所有城市的人口數(shù)//maxBy、minBy接受一個(gè)比較器,產(chǎn)生downstream元素中的最大,最小值 Map<String, City> stateToLargestCity = cities.collect(groupingBy(City::getState, maxBy(Comparator.comparing(City::getPopulation)))); //產(chǎn)生每個(gè)州人口最多的城市//mapping將函數(shù)應(yīng)用到downstream結(jié)果上,但是它需要另一個(gè)收集器處理其結(jié)果。 Map<String, Optional<String>> stateToLongestCityName = cities.collect(groupingBy(City::getState, mapping(City::getName,maxBy(Comparator.comparing(String::length))))); //這里講城市按所屬州進(jìn)行分組,每個(gè)州內(nèi),我們生成每個(gè)城市的名稱并按照其最大長(zhǎng)度進(jìn)行歸約

Mapping方法還未上一節(jié)中,獲取一個(gè)國(guó)家所有語(yǔ)言集合的問(wèn)題提供了一個(gè)更好的解決方案

1 Map<String, Set<String>> countryToLanguages = locales.collect(groupingBy(Locale::getDisplayCountry, mapping(Locale::getDisplayLanguage, toSet())));

  上一節(jié)使用的是toMap而不是groupingBy。在這種形式中,不必?fù)?dān)心單獨(dú)集合的合并問(wèn)題。如果grouping活著mapping函數(shù)的返回類型為int、long、double則你可以將元素收集到一個(gè)summary statistics對(duì)象中

Map<String, IntSummaryStatistics>stateToCityPopulationSummary = cities.collect(groupingBy(City::getState, summarizingImt(Vity::getPopulation))); //就可以從summary statistic對(duì)象中獲取函數(shù)值得總和,總數(shù)、平均、最大小值

  ※組合收集器功能強(qiáng)大,但是會(huì)導(dǎo)致非常復(fù)雜的表達(dá)式。應(yīng)該只在通過(guò)groupingBy或者partitioningBy來(lái)處理“downstream”map值時(shí),才使用它們。其他情況下,只需要對(duì)流直接應(yīng)用map、reduce、count、max、min方法即可

12、歸約操作

  reduce方法是用來(lái)計(jì)算流中某個(gè)值的一種通用機(jī)制,最簡(jiǎn)單的形式是使用一個(gè)二元函數(shù),從前兩個(gè)元素開(kāi)始,不斷作用到流中的其他元素上。

1 //求和 2 List<Integer> values = ...; 3 Optional<Integer> sum = values.stream().reduce((x,y)->x+y); 4 //可以用reduce(Integer::sum)代替

  reduce方法含有一個(gè)歸約操作P,那么歸約操作將生成v0 P v1 P V2.....,其中,vi P vi+1 表示函數(shù)調(diào)用 p(vi,vi+1)。操作滿足結(jié)合率,即與你組合元素的順序無(wú)關(guān)。

  有許多結(jié)合操作:sum求和、product乘積、string concatenation字符串拼接、maximum最大值、minimum最小值、set union集合并集、intersection交集。

  減法就不是結(jié)合操作

  通常存在標(biāo)識(shí)e是的 x P (y P z),可以使用該元素作為計(jì)算的起點(diǎn)。例如對(duì)加法來(lái)說(shuō)起點(diǎn)就是0(標(biāo)識(shí))。

1 //帶標(biāo)識(shí)的reduce 2 List<Integer> values = ...; 3 Integer sum = values.stream().reduce(0 , (x,y)->x+y); 4 //如果流為空則返回標(biāo)識(shí)值0

  如果有一個(gè)對(duì)象流,想得到這些對(duì)象上某個(gè)屬性的和,如求一個(gè)流中所有字符串的總長(zhǎng)度,就不能用reduce方法的簡(jiǎn)單形式((T,T)->T)應(yīng)為參數(shù)和返回值類型是一樣的,需要提供一個(gè)累加器函數(shù)(total, word) -> total +word.length()該函數(shù)會(huì)被重復(fù)調(diào)用形成累加值。但是當(dāng)開(kāi)始并行計(jì)算時(shí),會(huì)出現(xiàn)多個(gè)累加值,需要將他們累加起來(lái)。

1 int result = words.reduce(0, (total, word) -> total + word.length(),(total1, total2) ->total1+total2);

  在實(shí)際中,不會(huì)大量地使用聚合方法。簡(jiǎn)單的方法是映射到一個(gè)數(shù)字流,使用它的方法進(jìn)行求和、求最大值、最小值。在上述例子中可以調(diào)用words.mapToInt(String::length).sum()。這種方式簡(jiǎn)單高效,不涉及自動(dòng)裝箱。

  有時(shí)候reduce方法還不夠通用。假如想要將結(jié)果收集到一個(gè)BitSet(位組)中。如果收集操作是并行的,那么不能直接將元素放進(jìn)單個(gè)BitSet中,因?yàn)锽itSet對(duì)象不是線程安全的。所以不能使用reduce方法。每部分需要從自己的空集合開(kāi)始,而reduce僅允許提供一個(gè)標(biāo)識(shí)值,作為代替,可以使用collect方法,他接受三個(gè)參數(shù)

  1、一個(gè)提供者,創(chuàng)建目標(biāo)類型的實(shí)例方法,如HashSet的構(gòu)造函數(shù)

  2、一個(gè)累加器,將元素添加到目標(biāo)的方法,如add方法

  3、一個(gè)合并器,將兩個(gè)對(duì)象合并成一個(gè)的方法,如addAll方法。

BitSet result = stream.collect(BitSet::new, BitSet::set, BitSet::or);

13、

?

轉(zhuǎn)載于:https://www.cnblogs.com/Greekjone/p/5649063.html

總結(jié)

以上是生活随笔為你收集整理的给大忙人看的Java核心技术笔记(8、Stream)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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

主站蜘蛛池模板: 97超级碰碰人妻中文字幕 | 3d动漫精品h区xxxxx区 | 天天人人精品 | 久久久久久久久影院 | 国产成人欧美一区二区三区91 | 国产精品国产成人国产三级 | 国产精品久久久网站 | 亚洲aa在线 | 麻豆国产一区二区三区四区 | 131mm少妇做爰视频 | 日韩少妇一区 | www.xxx.国产 | 精品网站 | 中文字av| 99精品视频免费在线观看 | 亚洲日日骚 | 99国产精品99久久久久久 | 欧美久久久精品 | 香蕉久久国产 | 一本色道综合久久欧美日韩精品 | 日本xx片| 制服丝袜av在线 | 色人阁婷婷 | 色播五月激情五月 | 午夜影视福利 | 亚洲乱色熟女一区二区三区 | 日韩精品视频在线免费观看 | 欧美日韩激情视频在线观看 | 成人av高清在线观看 | 日韩成人av影院 | 久久精品国产亚洲av久一一区 | 高hhhhh| 女性裸体无遮挡胸 | 一级全黄裸体免费观看视频 | 97久久久久久久久久 | 蜜色影院 | 久久人人爽人人爽人人 | 激情久久婷婷 | 波多野结衣家庭主妇 | 日人视频| 一区二区国产视频 | 淫欲少妇 | 日韩欧美手机在线 | 午夜试看120秒| 久久丫精品 | 欧美在线一区视频 | 久久免费久久 | 精品91在线 | 乱熟女高潮一区二区在线 | 免费毛片av | 婷婷色视频 | 免费看黄的网址 | a黄色片| 一二三区av | 情侣av | 国产丝袜在线播放 | 日韩精品国产一区二区 | 操操综合网 | 伊人资源网 | 欧美一区二区三区公司 | 亚洲一区二三区 | 日韩色网站 | 国产操女人 | 日日热| 日韩操比| 高清一区二区三区四区五区 | 国产区一区二区三 | 麻豆疯狂做受xxxx高潮视频 | 海角社区在线视频播放观看 | 91亚洲精品久久久蜜桃 | 成人激情久久 | 97网站 | 久久视频中文字幕 | av色网站| 另类天堂网 | 亚洲中文字幕在线观看 | 图片区偷拍区小说区 | 欧洲国产精品 | 肥老熟妇伦子伦456视频 | 国产在线日韩 | 亚洲精品在线观看av | 久久久一级片 | 日日夜夜天天干 | 国产女人精品 | 欧美视频性 | 精品三级 | 不卡的中文字幕 | 91视频网址入口 | www.美色吧.com | 国产在线一区二区三区 | 成人美女免费网站视频 | 三级不卡视频 | 尤物视频最新网址 | 国产一伦一伦一伦 | 久久久久xxxx| 黄色高清网站 | 国产精品久久久久野外 | 六月婷婷激情 | 欧美aⅴ在线观看 |