精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

【如何亮劍】用例子來學習 Stream

開發(fā) 后端
先從一個例子開始,看看為什么在Java8中要引入流(Stream)?比如實現(xiàn)這么一個需求:在學生集合中查找男生的數量。

[[437151]]

本文轉載自微信公眾號「你呀不牛」,作者不牛。轉載本文請聯(lián)系你呀不牛公眾號。

1引言

先從一個例子開始,看看為什么在Java8中要引入流(Stream)?

比如實現(xiàn)這么一個需求:在學生集合中查找男生的數量。

傳統(tǒng)的寫法為:

  1. public long getCountsOfMaleStudent(List<Student> students) { 
  2.     long count = 0; 
  3.     for (Student student : students) { 
  4.         if (student.isMale()) { 
  5.             count++; 
  6.         } 
  7.     } 
  8.     return count

看似沒什么問題,因為我們寫過太多類似的**”樣板”代碼**,盡管智能的IDE通過code template功能讓這一枯燥過程變得簡化,但終究不能改變冗余代碼的本質。

再看看使用流的寫法:

  1. public long getCountsOfMaleStudent(List<Student> students) { 
  2.     return students.stream().filter(Student::isMale).count(); 

一行代碼就把問題解決了!

雖然讀者可能還不太熟悉流的語法特性,但這正是函數式編程思想的體現(xiàn):

  • 回歸問題本質,按照心智模型思考問題。
  • 延遲加載。
  • 簡化代碼。

下面正式進入流的介紹。

2創(chuàng)建流

創(chuàng)建流的方式可以有很多種,其中最常見的方式是通過Collection的Stream()方法或者Arrays的Stream()方法來生成流。比如:

  1. List numbers = Arrays.asList(1, 2, 3); 
  2.  
  3. Stream numberStream = numbers.stream(); 
  4.  
  5. String[] words = new String[]{"one""two"}; 
  6.  
  7. Stream wordsStream = Arrays.stream(words); 

當然Stream接口本身也提供了許多和流相關的操作。

  1. // 創(chuàng)建流 
  2. Stream<Integer> numbers = Stream.of(1, 2, 3); 
  3. // 創(chuàng)建空流 
  4. Stream<String> emptyStream = Stream.empty(); 
  5. // 創(chuàng)建一個元素為“hi”的無限流 
  6. Stream<String> infiniteString = Stream.generate(() -> "hi"); 
  7. // 創(chuàng)建一個從0開始的遞增無限流 
  8. Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE)); 

其中Stream.generate()和Stream.iterate()產生的都是無限流,如果要把他們截取為有限流,可以使用limit()方法, 比如:

  1. Stream<Double> top10 = Stream.generate(Math::random).limit(10); 

另外,可以通過skip()方法跳過元素,concat()方法連接兩個流。

  1. // 3, 4 
  2. Stream<Integer> skipedStream = Stream.of(1, 2, 3, 4).skip(2); 
  3. // hello,world 
  4. Stream<String> concatedStream = Stream.concat(Stream.of("hello"), Stream.of(",world"));  

3常用的流操作

filter

filter()方法的作用就是根據輸入的條件表達式過濾元素。

接口定義如下:

  1. Stream filter(Predicate predicate); 

從中可以看出,輸入參數是一個Predicate,也即是一個條件表達式。

一個例子:

  1. Stream.of("a""1b""c""0x").filter(value -> isDigit(value.charAt(0))); 

過濾出第一個字符是數字的元素。

輸出結果為:

1b, 0x

map

map()的主要作用是通過映射函數轉換成新的數據。接口定義如下:

  1. <R> Stream<R> map(Function<? super T, ? extends R> mapper); 

從中可以看出,輸入參數是一個Function。一個例子:

  1. Stream.of("a""b""c").map(String::toUpperCase); 

把字符串轉換成大寫。輸出結果:

A, B, C

flatMap

flatMap()的作用類似于map(),但它通過Function返回的依然是一個Stream,也即是把多個Stream轉換成一個扁平的Stream。接口定義如下:

  1. <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper); 

一個例子:

  1. Stream<List<Integer>> listStream = Stream.of(asList(1, 2), asList(3, 4)); 
  2. Stream<Integer> integerStream = listStream.flatMap(numbers -> numbers.stream()); 

它把兩個list組成的Stream轉成一個包含全部元素的Stream。輸出:

[1, 2, 3, 4]

4有狀態(tài)的轉換

在前面介紹的函數中,無論是map還是filter,都不會改變流的狀態(tài),也即結果并不依賴之前的元素。除此之外,Java8也提供了有狀態(tài)的轉換,常用的操作是distinct和sorted。

distinct

distinct()的主要作用是去除流中的重復元素。和Oracle的distinct一個作用。舉例如下:

  1. Stream distinctStream = Stream.of("one""one""two""three").distinct(); 

去除字符串中的重復元素,返回結果為:

one, two, three

sorted

sorted()的主要作用是對流按照指定的條件進行排序。接口定義如下:

  1. Stream<T> sorted(Comparator<? super T> comparator); 

從中可以看出,入參是一個Comparator,也即是一個函數式接口。一個例子:

  1. Stream<String> sortedStream = Stream.of("one""two","three").sorted(Comparator.comparing(String::length).reversed()); 

對字符串按照長度進行降序排列。

注意,這里使用了Comparator.comparing方法來簡化調用。

輸出結果為:

[three, one, two]

5Optional類型

在介紹下個主題前,先介紹一個Java8新增的數據結構:Optional。Optional的主要作用是對結果進行了封裝,結果可能有值,也可能沒有值,并且對結果可以進行后續(xù)處理,比如添加默認值,映射其他值,拋出異常等。

下面是常用的操作舉例:

  1. // 生成了一個Optional數據 
  2. Optional<String> maxStrOpt = Stream.of("one""two""three").max(String::compareToIgnoreCase); 
  3. // 如果值存在的情況下,把數據添加到List中 
  4. ArrayList<String> result = new ArrayList<String>();maxStrOpt.ifPresent(result::add); 
  5. // 把結果映射為大寫,然后取出。 
  6. Optional<String> upperResult = maxStrOpt.map(String::toUpperCase);System.out.println(upperResult.get()); 
  7. // 值為空的情況下的后續(xù)處理 
  8. maxStrOpt.orElse("");  
  9. // 添加默認值"" 
  10. maxStrOpt.orElseGet(() -> System.getProperty("user.dir"));  
  11. // 通過表達式返回結果 
  12. maxStrOpt.orElseThrow(RuntimeException::new); // 拋出異常 

6聚合操作

之前介紹的函數都是返回的Stream,根據Stream延遲加載的特性,它是不會真正執(zhí)行的,只有在做了本節(jié)的聚合操作以及后續(xù)章節(jié)介紹的收集操作后,才會真正執(zhí)行。

所謂聚合操作就是把一組數據通過操作聚合為一個結果的過程。

下面介紹常用的聚合操作:

count

count()的作用是統(tǒng)計元素的總數,很多時候需要配合filter一起使用。一個例子:

  1. long count = Stream.of("one""two""three").filter(word->word.contains("o")).count(); 

統(tǒng)計字符流中包含字符o的單詞數量。結果:

2

max/min

max/min()的主要作用是取得元素的最大值/最小值。接口定義如下:

  1. Optional<T> max(Comparator<? super T> comparator); 
  2. Optional<T> min(Comparator<? super T> comparator); 

從中可以看出,入參是一個Comparator函數式結果,返回的是一個Optional。一個例子:

  1. Optional<String> maxStrOpt = Stream.of("one""two""three").max(String::compareToIgnoreCase);System.out.println(maxStrOpt.get()); 

按照字母表比較,統(tǒng)計最大值,結果為:

two

findFirst/findAny

findFirst()的主要作用是找到第一個匹配的結果。findAny()的主要作用是找到找到任意匹配的一個結果。它在并行流中特別有效,因為只要在任何分片上找到一個匹配元素,整個計算就會結束。

返回結果都是Optional。

接口定義如下:

  1. Optional<T> findFirst(); 
  2. Optional<T> findAny(); 

一個例子:

  1. Optional<String> findFirstResult = Stream.of("one""two""three").filter(word -> word.contains("o").findFirst(); 
  2. System.out.println(findFirstResult.get()); 
  3. Optional<String> findAnyResult = Stream.of("one""two""three").filter(word -> word.contains("t").findAny(); 
  4. System.out.println(findAnyResult.get()); 

結果為:

one two

anyMatch/allMatch/noneMatch

如果只關心是否匹配成功,即返回boolean結果,則可以使用anyMatch/allMatch/noneMatch函數。接口定義如下:

  1. boolean anyMatch(Predicate predicate); 
  2.  
  3. boolean allMatch(Predicate predicate); 
  4.  
  5. boolean noneMatch(Predicate predicate); 

其中, anyMatch表示任意匹配(or); allMatch表示全部匹配(and); noneMatch表示不匹配(not)。

一個例子:

  1. boolean anyMatch = Stream.of("one""two""three").anyMatch(word -> word.contains("o")); 
  2.  
  3. boolean allMatch = Stream.of("one""two""three").allMatch(word -> word.contains("o")); 
  4.  
  5. boolean noneMatch = Stream.of("one""two""three").noneMatch(word -> word.contains("o"); 
  6.                                                                 
  7. System.out.println(anyMatch + ", " + allMatch + ", " + noneMatch); 

結果為:

true, false, false

reduce

reduce()主要進行歸約操作,它提供了三種不同的用法。

用法1:接口定義:

  1. Optional<T> reduce(BinaryOperator<T> accumulator); 

它主要接收一個BinaryOperator的累加器,返回Optional類型。

一個例子:

  1. Optional<Integer> sum1 = Stream.of(1, 2, 3).reduce((x, y) -> x + y);System.out.println(sum1.get()); 

對數字流求和,結果為:

6

用法2:接口定義:

  1. T reduce(T identity, BinaryOperator<T> accumulator); 

和上一個方法不一樣的地方是:它提供了一個初始值identity,這樣就保證整個計算結果時不可能為空,所以不再返回Optional,直接返回對應的類型T。

一個例子:

  1. Integer sum2 = Stream.of(1, 2, 3).reduce(10, (x, y) -> x + y);System.out.println(sum2); 

結果為:

16

用法3:

接口定義:

  1. <U > U reduce(U identity, BiFunction < U, ? super T, U > accumulator, BinaryOperator < U > combiner); 

這是最復雜的一種用法,它主要用于把元素轉換成不同的數據類型。accumulator是累加器,主要進行累加操作,combiner是把不同分段的數據組合起來(并行流場景)。

一個例子:

  1. Integer sum3 = Stream.of("on""off").reduce(0, (total, word) -> total + word.length(), (x, y) -> x + y); 
  2.  
  3. System.out.println(sum3); 

統(tǒng)計元素的單詞長度,并累加在一起,結果為:

5

7收集操作 (collect)

collect()方法主要用于把流轉換成其他的數據類型。

轉換成集合

可以通過Collectors.toList()/toSet()/toCollection()方法轉成List,Set,以及指定的集合類型。一個例子:

  1. List<Integer> numbers = asList(1, 2, 3, 4, 5); 
  2. // 轉換成List 
  3. List<Integer> numberList = numbers.stream().collect(toList()); 
  4. // 轉換成Set 
  5. Set<Integer> numberSet = numbers.stream().collect(toSet()); 
  6. // 通過toCollection轉成TreeSet 
  7. TreeSet<Integer> numberTreeSet = numbers.stream().collect(Collectors.toCollection(TreeSet::new)); 

注:

  • 這里對類似Collectors.toList的方法實施了靜態(tài)導入。
  • toList()默認轉成ArrayList,toSet()默認轉成HashSet,如果這兩種數據類型都不滿足要求的話,可以通過toCollectio()方法轉成需要的集合類型。

轉換成值

除了轉成集合外,還可以把結果轉成值。常用的轉換函數包括:

  • Collectors.summarizingInt()/summarizingLong()/summarizingDouble() // 獲取統(tǒng)計信息,進行求和、平均、數量、最大值、最小值。
  • Collectors.maxBy()/minBy() // 求最大值/最小值
  • Collectors.counting() // 求數量
  • Collectors.summingInt()/summingLong()/summingDouble() // 求和
  • Collectors.averagingInt()/averagingDouble()/averagingDouble() // 求平均
  • Collectors.joining() // 對字符串進行連接操作

一個例子:

  1. List<String> wordList = Arrays.asList("one""two""three"); 
  2. // 獲取統(tǒng)計信息,打印平均和最大值 
  3. IntSummaryStatistics summary = wordList.stream().collect(summarizingInt(String::length)); 
  4. System.out.println(summary.getAverage() + ", " + summary.getMax()); 
  5. // 獲取單詞的平均長度 
  6. Double averageLength = wordList.stream().collect(averagingInt(String::length)); 
  7. // 獲取最大的單詞長度 
  8. Optional<String> maxLength = wordList.stream().collect(maxBy(Comparator.comparing(String::length))); 

這些方法的共同特點是:返回的數據類型都是Collector。雖然可以單獨在Collect()方法中使用,但實際卻很少這樣用(畢竟Stream本身也提供了類似的方法),它更常用的用法是配合groupingBy()方法一起使用,以便對分組后的數據進行二次加工。

8分區(qū)操作(partitioningBy)

partitioningBy操作是基于collect操作完成的,它會根據條件對流進行分區(qū)操作,返回一個Map,Key是boolean型,Value是對應分區(qū)的List,也就是說結果只有符合條件和不符合條件兩種。接口定義如下:

  1. public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) 

一個例子:

  1. public Map<Boolean, List<Student>> maleAndFemaieStudents(Stream<Student> students) {     return students.collect(Collectors.partitioningBy(student -> student.isMale())); 

按性別對學生流進行分區(qū),結果保存在Map中。

9分組操作(groupingBy)

groupingBy操作也是基于collect操作完成的,功能是根據條件進行分組操作,他和partitioningBy不同的一點是,它的輸入是一個Function,這樣返回結果的Map中的Key就不再是boolean型,而是符合條件的分組值,使用場景會更廣泛。

接口定義如下:

  1. public static Collector>> groupingBy(Function classifier) 

一個例子

  1. public Map> studentByName(Stream students) { 
  2.  
  3. return students.collect(Collectors.groupingBy(student -> student.getName())); 
  4.  

按照學生的姓名進行分組。之前也提過,groupingBy函數可以配合聚合函數做更復雜的操作。下面介紹幾種常見的使用場景:

按照城市所在的州進行分組,再統(tǒng)計數量。

  1. public Map stateToCount(Stream cities) { 
  2.  
  3. return cities.collect(groupingBy(City::getState, counting())); 
  4.  

按照城市所在的州進行分組,再統(tǒng)計人口總數。

  1. public Map stateToCityPopulation(Stream cities) { 
  2.  
  3. return cities.collect(groupingBy(City::getState, summingInt(City::getPopulation))); 
  4.  

按照城市所在的州進行分組,再找出每州人口最多的城市。

  1. public Map stateToLargestCity(Stream cities) { 
  2.  
  3. return cities.collect(groupingBy(City::getState, maxBy(Comparator.comparing(City::getPopulation)))); 
  4.  

按照城市所在的州進行分組,再找出每州城市名最長的名稱。

  1. public Map> stateToLongestCityName(Stream cities) { 
  2.  
  3. return cities.collect(groupingBy(City::getState, mapping(City::getName, maxBy(Comparator.comparing(String::length))))); 
  4.  

按照城市所在的州進行分組,再按照人口獲取統(tǒng)計信息。利用統(tǒng)計信息可以執(zhí)行求和、平均、數量、最大/最小值

  1. public Map stateToCityPopulationSummary(Stream cities) { 
  2.  
  3. return cities.collect(groupingBy(City::getState, summarizingInt(City::getPopulation))); 
  4.  

按照城市所在的州進行分組,再把每州的城市名連接起來

  1. public Map stateToCityNames(Stream cities) { 
  2.  
  3. return cities.collect(groupingBy(City::getState, reducing("", City::getName, (s, t) -> s.length() == 0 ? t : s + ", " + t))); 
  4.  

按照城市所在的州進行分組,再把每州的城市名連接起來,使用joining函數。

  1. public Map<String, String> stateToCityNames2(Stream<City> cities) { 
  2.     return cities.collect(groupingBy(City::getState, mapping(City::getName, joining(", ")))); 

從以上例子可以看出,groupingBy函數配合聚合函數可以組成表示出很復雜的應用場景。

10基本類型流(IntStream,LongStream,DoubleStream)

在前面介紹的流中,都是使用的Stream配合泛型來標示元素類型的。Java8中還為基本數據類型提供了更直接的流方式,以簡化使用。

對于byte,short,int,char,booelan類型可以使用IntStream;

對于long類型可以使用LongStream;

對于float和Double類型可以使用DoubleStream。

創(chuàng)建基本類型流的例子:

  1. IntStream intStream = IntStream.of(1, 2, 3); 
  2. // 不包含上限10 
  3. IntStream rangeStream = IntStream.range(1, 10); 
  4. // 包含上限10 
  5. IntStream rangeClosedStream = IntStream.rangeClosed(1, 10);   

基本類型流還直接提供了sum, average, max, min等在Stream中并沒有的方法。還有一個mapToInt/mapToLong/mapToDouble方法把流轉成基本類型流。利用這兩個個特性,可以方便執(zhí)行某些操作,再看一個例子。

  1. Stream<String> twoWords = Stream.of("one""two"); 
  2. int twoWordsLength = twoWords.mapToInt(String::length).sum(); 

對原始字符串流統(tǒng)計字符總長度。

11在文件操作中使用流

文件操作也是我們平時用的比較多的一種操作,利用流也可以幫助我們簡化操作。

訪問目錄和過濾

  1. Files.list(Paths.get(".")).forEach(System.out::println);Files.list(Paths.get(".")).filter(Files::isDirectory); 

按擴展名過濾文件

  1. Files.newDirectoryStream(Paths.get("."), path -> path.toString().endsWith("md")).forEach(System.out::println);File[] textFiles = new File(".").listFiles(path -> path.toString().endsWith("txt")); 

訪問子目錄

  1. List<File> allFiles = Stream.of(new File(".").listFiles()).flatMap(file -> file.listFiles() == null ? Stream.of(file) : Stream.of(file.listFiles())).collect(toList()); 

12小結

Stream 是 Java8 中處理集合的關鍵抽象概念,它可以指定對集合進行的操作,可以執(zhí)行非常復雜的查找、過濾和映射數據等操作。使用Stream API 對集合數據進行操作,就類似于使用 SQL 執(zhí)行的數據庫查詢。也可以使用 Stream API 來并行執(zhí)行操作。簡而言之,Stream API 提供了一種高效且易于使用的處理數據的方式。詳細的API可以參見下面腦圖:

 

責任編輯:武曉燕 來源: 你呀不牛
相關推薦

2015-08-21 11:09:21

2022-10-14 06:45:25

grepLinux

2009-03-18 08:49:42

Windows 7微軟操作系統(tǒng)

2016-01-04 10:07:21

2012-08-16 11:19:29

戴爾

2019-04-16 10:15:32

網絡安全網絡安全大會西湖論劍

2013-06-06 13:21:03

傲天動聯(lián)WLAN企業(yè)市場

2011-12-28 15:39:10

打印機評測

2022-11-09 11:17:24

tee命令

2017-03-28 15:16:28

互聯(lián)網

2013-11-11 15:36:49

2013-12-20 15:16:52

云學堂

2020-02-03 11:35:54

華為HMS Core

2010-12-07 14:01:51

2015-06-15 09:52:57

聯(lián)想互聯(lián)網System x

2019-07-18 08:57:09

Java后端Java基礎

2015-09-15 11:53:08

百分點大數據

2009-06-03 17:56:37

戴爾機架服務器Nehalem

2011-03-01 16:31:04

點贊
收藏

51CTO技術棧公眾號

久久要要av| 精品成人免费一区二区在线播放| 国产精品一区二区黑丝| 九九久久久久99精品| 天堂av手机在线| 欧美wwww| 久久久久高清精品| 91人人爽人人爽人人精88v| 青青操视频在线播放| 精品人人人人| 欧美三级中文字幕| 亚洲精品国产suv一区88| 亚洲av无码乱码国产精品久久| 亚洲午夜av| 一本色道久久88综合日韩精品| av亚洲天堂网| 欧美办公室脚交xxxx| 国产精品三级电影| 麻豆av一区| 国产精品一品二区三区的使用体验| 黄色av成人| 尤物99国产成人精品视频| 不卡的一区二区| 欧美123区| 五月综合激情网| 久久久国产精华液999999| 天天操天天干天天爱| 九九视频精品免费| 日本一区二区在线免费播放| 欧美日韩免费做爰视频| 色欧美自拍视频| 精品偷拍一区二区三区在线看| 无码人妻一区二区三区在线视频| 日本在线中文字幕一区二区三区 | 91香蕉视频在线下载| 欧美brazzers| 国产亚洲精品v| 欧美成人免费全部观看天天性色| 欧美人与禽zoz0善交| 日韩精品丝袜美腿| 欧美成人video| 亚洲图片 自拍偷拍| 69堂精品视频在线播放| 精品国产老师黑色丝袜高跟鞋| 久久99国产精品一区| av在线电影观看| 91原创在线视频| 国产精品二区二区三区| 国产福利免费视频| 国产一区在线视频| 成人中心免费视频| 伊人影院中文字幕| 日韩激情视频在线观看| 日本午夜在线亚洲.国产| 中文字字幕在线中文| 亚洲激情影院| 1769国产精品| 日本天堂网在线| 亚洲一区图片| 日韩av片免费在线观看| 区一区二在线观看| 老牛影视一区二区三区| 国产成人精品视频| 综合久久中文字幕| 看片的网站亚洲| 成人精品久久一区二区三区| 国产一区二区在线视频观看| 国产综合色在线| 98国产高清一区| www日本高清视频| 成人免费毛片app| 国内精品一区二区| 欧美视频综合| 中文字幕av一区二区三区| 午夜精品美女久久久久av福利| 97人人在线| 亚洲视频综合在线| 久久久久久久香蕉| 黄视频网站在线观看| 色综合网站在线| 伊人国产在线视频| 精品久久久久久久久久岛国gif| 欧美一级二级三级蜜桃| 国产原创剧情av| 亚洲影院天堂中文av色| 色yeye香蕉凹凸一区二区av| www欧美com| 亚洲成人中文| 国产精品wwww| 国产伦精品一区二区三区四区| 国产精品亚洲午夜一区二区三区| 国内外成人免费视频| h视频在线免费| 亚洲免费观看高清| 久久久久久久久久久视频| av一区在线播放| 日韩欧美国产综合| 男人舔女人下部高潮全视频| 91精品国产自产拍在线观看蜜| 国内精久久久久久久久久人| 中文字幕无码乱码人妻日韩精品| 国产成人综合在线播放| 欧洲亚洲一区| 日本在线视频www鲁啊鲁| 色就色 综合激情| 国产一级二级av| 国产探花一区二区| 欧美激情免费视频| 伊人影院中文字幕| 26uuu精品一区二区三区四区在线 26uuu精品一区二区在线观看 | 天天干在线播放| 精品一二线国产| 免费国产一区| 欧美24videosex性欧美| 欧美日韩一区二区不卡| 亚洲天堂资源在线| 欧美偷拍综合| 日韩在线视频免费观看高清中文| 91浏览器在线观看| 国产精品1024| 影音先锋欧美在线| 亚洲综合电影| 精品久久久久久综合日本欧美| 亚洲天堂最新地址| 中文高清一区| 国产精品国产精品国产专区蜜臀ah| 国产黄色免费在线观看| 婷婷中文字幕综合| 日本一二三四区视频| 不卡中文字幕| 欧美一级免费看| 成人免费公开视频| 亚洲免费在线播放| 亚洲精品综合在线观看| 成人vr资源| 日韩av手机在线看| 久久电影视频| 欧美午夜激情小视频| 91成人在线观看喷潮蘑菇| 91精品国偷自产在线电影 | 日韩欧美在线观看免费| 不卡区在线中文字幕| 成人一区二区av| av在线国产精品| 日韩在线观看成人| 亚洲网站在线免费观看| 日本一区二区三区国色天香| 99精品视频播放| 中文字幕精品影院| 日韩av电影在线网| 国产亚洲依依| 在线观看视频一区二区| 亚洲AV无码成人精品区明星换面| 久久精品伊人| 日韩高清av电影| 成人a在线观看高清电影| 国产一区二区欧美日韩| 成人免费视频国产免费| 久久九九99视频| 亚洲欧美另类动漫| 久久看人人摘| 91亚洲一区精品| 欧洲一区二区三区| 亚洲成人动漫在线播放| 青青草成人av| 国产人妖乱国产精品人妖| 天天爽人人爽夜夜爽| 日韩在线高清| 99久re热视频这里只有精品6| 欧美家庭影院| 日韩高清a**址| 欧美一级黄视频| 亚洲天堂中文字幕| 精品国产乱码久久久久夜深人妻| 99视频+国产日韩欧美| 久久国产精品-国产精品| **欧美日韩在线观看| 色一区av在线| 亚洲免费国产视频| 一本大道综合伊人精品热热| 久久久久久成人网| 国产美女精品一区二区三区| 国产一区二区四区| 久久99影视| 亚洲aaaaaa| 日韩脚交footjobhdboots| 国产午夜精品全部视频在线播放| 亚洲一卡二卡在线观看| 亚洲图片欧美综合| 91激情视频在线观看| 国产盗摄视频一区二区三区| 狠狠97人人婷婷五月| 欧美aaaaaaaaaaaa| 韩国成人av| 亚洲国产伊人| 欧美亚洲另类在线| 福利在线视频网站| 日韩精品免费在线| www黄色网址| 欧美亚洲国产怡红院影院| 久久久久亚洲av无码专区 | 日韩欧美高清dvd碟片| 西西44rtwww国产精品| 国产精品黄色在线观看| 国产在线不卡av| 捆绑变态av一区二区三区| 色欲色香天天天综合网www| 日韩欧美网址| 国产一区二区三区奇米久涩| 日韩一级视频| 日本伊人精品一区二区三区介绍| 手机在线免费av| 中文字幕欧美国内| 香蕉久久一区二区三区| 日韩欧美的一区| 一级做a爱片久久毛片| 欧美午夜视频一区二区| 久久香蕉精品视频| 综合欧美一区二区三区| 精品人妻互换一区二区三区| 盗摄精品av一区二区三区| 午夜视频在线网站| 日韩综合小视频| 国产91在线视频观看| 欧美日韩一区自拍| 亚洲在线色站| 欧美日韩中文一区二区| 精品免费二区三区三区高中清不卡| 久久天堂久久| 国产专区精品视频| 巨胸喷奶水www久久久免费动漫| 欧美亚洲成人免费| www.youjizz.com在线| 欧美激情在线观看视频| mm1313亚洲国产精品美女| 日韩亚洲成人av在线| 福利成人在线观看| 亚洲人成电影网站色| 午夜福利一区二区三区| 亚洲国产小视频在线观看| 亚洲精品视频网| 日韩一区二区三区在线视频| 97久久人国产精品婷婷| 欧美日韩成人综合天天影院| 中文字幕精品一区二区精| 色综合色狠狠天天综合色| 日韩免费不卡视频| 一区二区三区欧美| 亚洲欧美日韩网| 亚洲精品国产欧美在线观看| 岛国av一区二区三区| 欧美亚洲天堂网| 亚洲图片欧美一区| 国产精品500部| 亚洲国产精品一区二区久久| 欧美日韩激情在线观看| 一区二区激情视频| 久久久精品99| 亚洲成人av一区| 日韩精品在线免费视频| 天天av天天翘天天综合网 | 欧美网站大全在线观看| 国产在线一级片| 欧美理论电影在线| 国产激情久久久久久熟女老人av| 日韩一区二区三区高清免费看看| 国产成a人亚洲精v品无码 | 精品人妻一区二区免费| 不卡电影一区二区三区| 毛茸茸多毛bbb毛多视频| 久久久久久99久久久精品网站| 五月天综合视频| 国产精品入口麻豆九色| 欧美成人免费看| 黑人精品xxx一区一二区| 成人a v视频| 欧美丰满一区二区免费视频| 性生活视频软件| 日韩精品视频免费在线观看| 国产一级网站视频在线| 久久九九有精品国产23| 里番在线播放| 日本欧美精品在线| 自拍偷拍亚洲图片| 国产在线精品一区| 欧美自拍偷拍| 高清无码一区二区在线观看吞精| 国产视频一区在线观看一区免费| 日本www.色| 国产99一区视频免费| 亚洲精品理论片| 亚洲欧洲99久久| 青青操免费在线视频| 欧美这里有精品| www.麻豆av| 国产亚洲精品美女久久久久| av片在线观看永久免费| 欧美亚洲另类在线| 成人国产精品久久| 免费99视频| 欧美激情 亚洲a∨综合| 国产精品无码专区av在线播放 | 91官网在线观看| 精品国自产拍在线观看| 国产亚洲成精品久久| 日韩欧美一起| 国产精品一区=区| 久久激情av| 在线国产精品网| 午夜一区不卡| 被黑人猛躁10次高潮视频| 久久男人中文字幕资源站| 久久久久久久久毛片| 在线免费观看不卡av| 欧美自拍第一页| www.日韩欧美| 澳门av一区二区三区| 国产视频在线观看一区| 久久精品影视| 欧美黄色一级片视频| 不卡av电影在线播放| 欧美一区二区三区爽爽爽| 欧美午夜电影一区| 男操女在线观看| 97超级碰碰人国产在线观看| 欧州一区二区三区| 亚洲永久一区二区三区在线| 丝袜美腿亚洲一区| 国产高清自拍视频| 午夜伊人狠狠久久| 精品国产亚洲av麻豆| 精品国产视频在线| 成人在线中文| 日韩精品极品视频在线观看免费| 亚洲午夜久久久久久尤物| 91大神免费观看| 亚洲欧美偷拍三级| 国产精品探花视频| 久久视频在线视频| 91久久青草| 裸体裸乳免费看| 国产在线不卡一卡二卡三卡四卡| 亚洲不卡的av| 欧美日韩国产影片| 色影视在线观看| 国产欧美日韩专区发布| 欧美电影一区| 一级做a免费视频| 综合久久一区二区三区| 亚洲一卡二卡在线观看| 久久午夜a级毛片| 日本免费精品| www.avtt| www.亚洲色图| 青草视频在线观看免费| 亚洲男人天堂手机在线| 亚洲wwww| 亚洲在线观看一区| 国产很黄免费观看久久| 国产真实的和子乱拍在线观看| 亚洲第一福利网| 欧美激情20| 欧洲一区二区在线| 日本免费在线视频不卡一不卡二| 亚洲综合在线一区二区| 一区二区三区成人| 天天综合网在线观看| 97视频网站入口| 国产真实有声精品录音| 日韩一级片播放| 免费日韩一区二区三区| www.在线观看av| 成人性色生活片免费看爆迷你毛片| 国产18无套直看片| 欧美亚日韩国产aⅴ精品中极品| 成人在线观看一区| 91天堂在线观看| 欧美精品一级| 好吊一区二区三区视频| 日韩欧美一区二区三区久久| 91在线网址| 91嫩草在线视频| 亚洲精品极品| 极品人妻一区二区三区| 狠狠做深爱婷婷久久综合一区| 二区在线视频| 91九色单男在线观看| 在线综合视频| 中文字幕 自拍| 日韩午夜激情免费电影| 岛国av在线网站| 一区二区精品在线观看| 国产精品一区专区| 亚洲免费在线观看av| 亚洲精美色品网站| 日韩专区视频网站| 国产精品成人久久电影| 中文字幕免费一区| 国内精品久久久久久久久久久| 欧美中文字幕在线播放|