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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java8 stream 最大值_JDK8-Stream流常用方法

發布時間:2023/12/4 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java8 stream 最大值_JDK8-Stream流常用方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Stream流的使用

流操作是Java8提供一個重要新特性,它允許開發人員以聲明性方式處理集合,其核心類庫主要改進了對集合類的 API和新增Stream操作。Stream類中每一個方法都對應集合上的一種操作。將真正的函數式編程引入到Java中,能 讓代碼更加簡潔,極大地簡化了集合的處理操作,提高了開發的效率和生產力。

同時stream不是一種數據結構,它只是某種數據源的一個視圖,數據源可以是一個數組,Java容器或I/O channel等。在Stream中的操作每一次都會產生新的流,內部不會像普通集合操作一樣立刻獲取值,而是惰性 取值,只有等到用戶真正需要結果的時候才會執行。并且對于現在調用的方法,本身都是一種高層次構件,與線程模型無關。因此在并行使用中,開發者們無需再去操 心線程和鎖了。Stream內部都已經做好了。

如果剛接觸流操作的話,可能會感覺不太舒服。其實理解流操作的話可以對比數據庫操作。把流的操作理解為對數據庫中 數據的查詢操作

集合?=?數據表

元素?=?表中的每條數據

屬性?=?每條數據的列

流API?=?sql查詢

流操作詳解

Stream流接口中定義了許多對于集合的操作方法,總的來說可以分為兩大類:中間操作和終端操作。

中間操作:會返回一個流,通過這種方式可以將多個中間操作連接起來,形成一個調用鏈,從而轉換為另外 一個流。除非調用鏈后存在一個終端操作,否則中間操作對流不會進行任何結果處理。

終端操作:會返回一個具體的結果,如boolean、list、integer等。

1、篩選

對于集合的操作,經常性的會涉及到對于集中符合條件的數據篩選,Stream中對于數據篩選兩個常見的API: ?lter(過濾)、distinct(去重)

1.1基于?lter()實現數據過

該方法會接收一個返回boolean的函數作為參數,終返回一個包括所有符合條件元素的流。

案例:獲取所有年齡20歲以下的學生

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class FilterDemo {

public static void main(String[] args) {

//獲取所有年齡20歲以下的學生

ArrayList students = new ArrayList<>();

students.add(new Student(1,19,"張三","M",true));

students.add(new Student(1,18,"李四","M",false));

students.add(new Student(1,21,"王五","F",true));

students.add(new Student(1,20,"趙六","F",false));

students.stream().filter(student -> student.getAge()<20);

}

}

源碼解析

此處可以看到?lter方法接收了Predicate函數式接口。

首先判斷predicate是否為null,如果為null,則拋出NullPointerException;構建Stream,重寫opWrapsink方法。參數flags:下一個sink的標志位,供優化使用。參數sink:下一個sink,通過此參數將sink構造成單鏈。此時流已經構建好,但是因為begin()先執行,此時是無法確定流中后續會存在多少元素的,所以傳遞-1,代表無法確定。最后調用Pridicate中的test,進行條件判斷,將符合條件數據放入流中。

1.2基于distinct實現數據去重

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class DistinctDemo {

public static void main(String[] args) {

List integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);

integers.stream().distinct().collect(Collectors.toList());

}

}

源碼解析

根據其源碼,我們可以知道在distinct()內部是基于LinkedHashSet對流中數據進行去重,并終返回一個新的流。

2、切片

2.1基于limit()實現數據截取

該方法會返回一個不超過給定長度的流

案例:獲取數組的前五位

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class LimitDemo {

public static void main(String[] args) {

//獲取數組的前五位

List integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);

integers.stream().limit(5);

}

}

源碼解析:

對于limit方法的實現,它會接收截取的長度,如果該值小于0,則拋出異常,否則會繼續向下調用 SliceOps.makeRef()。該方法中this代表當前流,skip代表需要跳過元素,比方說本來應該有4個元素,當跳過元素 值為2,會跳過前面兩個元素,獲取后面兩個。maxSize代表要截取的長度

在makeRef方法中的unorderedSkipLimitSpliterator()中接收了四個參數Spliterator,skip(跳過個數)、limit(截取 個數)、sizeIfKnown(已知流大小)。如果跳過個數小于已知流大小,則判斷跳過個數是否大于0,如果大于則取截取 個數或已知流大小-跳過個數的兩者小值,否則取已知流大小-跳過個數的結果,作為跳過個數。

后對集合基于跳過個數和截取個數進行切割。

2.2基于skip()實現數據跳過

案例:從集合第三個開始截取5個數據

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class LimitDemo {

public static void main(String[] args) {

//從集合第三個開始截取5個數據

List integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);

List collect = integers.stream().skip(3).limit(5).collect(Collectors.toList());

collect.forEach(integer -> System.out.print(integer+" "));

}

}

結果4 4 5 5 6

案例:先從集合中截取5個元素,然后取后3個

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class LimitDemo {

public static void main(String[] args) {

//先從集合中截取5個元素,然后取后3個

List integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);

List collect = integers.stream().limit(5).skip(2).collect(Collectors.toList());

collect.forEach(integer -> System.out.print(integer+" "));

}

}

結果:3 4 4

源碼分析:

在skip方法中接收的n代表的是要跳過的元素個數,如果n小于0,拋出非法參數異常,如果n等于0,則返回當前 流。如果n小于0,才會調用makeRef()。同時指定limit參數為-1.

此時可以發現limit和skip都會進入到該方法中,在確定limit值時,如果limit<0,則獲取已知集合大小長度-跳過的長度。最終進行數據切割。

3、映射

在對集合進行操作的時候,我們經常會從某些對象中選擇性的提取某些元素的值,就像編寫sql一樣,指定獲取表 中特定的數據列

#指定獲取特定列 SELECT?name?FROM?student

在Stream API中也提供了類似的方法,map()。它接收一個函數作為方法參數,這個函數會被應用到集合中每一個 元素上,并終將其映射為一個新的元素。

案例:獲取所有學生的姓名,并形成一個新的集合

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class MapDemo {

public static void main(String[] args) {

//獲取所有學生的姓名,并形成一個新的集合

ArrayList students = new ArrayList<>();

students.add(new Student(1,19,"張三","M",true));

students.add(new Student(1,18,"李四","M",false));

students.add(new Student(1,21,"王五","F",true));

students.add(new Student(1,20,"趙六","F",false));

List collect = students.stream().map(Student::getName).collect(Collectors.toList());

collect.forEach(s -> System.out.print(s + " "));

}

}

結果:張三 李四 王五 趙六

源碼解析:

內部對Function函數式接口中的apply方法進行實現,接收一個對象,返回另外一個對象,并把這個內容存入當前 流中,后返回

4、匹配

在日常開發中,有時還需要判斷集合中某些元素是否匹配對應的條件,如果有的話,在進行后續的操作。在 Stream API中也提供了相關方法供我們進行使用,如anyMatch、allMatch等。他們對應的就是&&和||運算符。

4.1基于anyMatch()判斷條件至少匹配一個元素

anyMatch()主要用于判斷流中是否至少存在一個符合條件的元素,它會返回一個boolean值,并且對于它的操作, 一般叫做短路求值

案例:判斷集合中是否有年齡小于20的學生

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class AnyMatchDemo {

public static void main(String[] args) {

//判斷集合中是否有年齡小于20的學生

ArrayList students = new ArrayList<>();

students.add(new Student(1,19,"張三","M",true));

students.add(new Student(1,18,"李四","M",false));

students.add(new Student(1,21,"王五","F",true));

students.add(new Student(1,20,"趙六","F",false));

if(students.stream().anyMatch(student -> student.getAge() < 20)){

System.out.println("集合中有年齡小于20的學生");

}else {

System.out.println("集合中沒有年齡小于20的學生");

}

}

}

根據上述例子可以看到,當流中只要有一個符合條件的元素,則會立刻中止后續的操作,立即返回一個布爾值,無需遍歷整個流。

源碼解析:

內部實現會調用makeRef(),其接收一個Predicate函數式接口,并接收一個枚舉值,該值代表當前操作執行的是 ANY。

如果test()抽象方法執行返回值==MatchKind中any的stopOnPredicateMatches,則將stop中斷置為true,value 也為true。并終進行返回。無需進行后續的流操作。

4.2基于allMatch()判斷條件是否匹配所有元素

allMatch()的工作原理與anyMatch()類似,但是anyMatch執行時,只要流中有一個元素符合條件就會返回true, 而allMatch會判斷流中是否所有條件都符合條件,全部符合才會返回true

案例:判斷集合所有學生的年齡是否都小于20

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class AllMatchDemo {

public static void main(String[] args) {

//判斷集合所有學生的年齡是否都小于20

ArrayList students = new ArrayList<>();

students.add(new Student(1,19,"張三","M",true));

students.add(new Student(1,18,"李四","M",false));

students.add(new Student(1,21,"王五","F",true));

students.add(new Student(1,20,"趙六","F",false));

if(students.stream().allMatch(student -> student.getAge() < 20)){

System.out.println("集合所有學生的年齡都小于20");

}else {

System.out.println("集合中有年齡大于20的學生");

}

}

}

源碼解析:與anyMatch類似,只是其枚舉參數的值為ALL

5、查找

對于集合操作,有時需要從集合中查找中符合條件的元素,Stream中也提供了相關的API,?ndAny()和 ?ndFirst(),他倆可以與其他流操作組合使用。?ndAny用于獲取流中隨機的某一個元素,?ndFirst用于獲取流中的 第一個元素。至于一些特別的定制化需求,則需要自行實現。

5.1基于?ndAny()查找元素

案例:?ndAny用于獲取流中隨機的某一個元素,并且利用短路在找到結果時,立即結束

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class FindAnyDemo {

public static void main(String[] args) {

//?ndAny用于獲取流中隨機的某一個元素,并且利用短路在找到結果時,立即結束

ArrayList students = new ArrayList<>();

students.add(new Student(1,19,"張三1","M",true));

students.add(new Student(1,18,"張三2","M",false));

students.add(new Student(1,21,"張三3","F",true));

students.add(new Student(1,20,"張三4","F",false));

students.add(new Student(1,20,"張三5","F",false));

students.add(new Student(1,20,"張三6","F",false));

Optional student1 = students.stream().filter(student -> student.getSex().equals("F")).findAny();

System.out.println(student1.toString());

}

}

結果:Optional[Student{id=1, age=21, name='張三3', sex='F', isPass=true}]

此時我們將其循環100次

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class FindAnyDemo {

public static void main(String[] args) {

//?ndAny用于獲取流中隨機的某一個元素,并且利用短路在找到結果時,立即結束

ArrayList students = new ArrayList<>();

students.add(new Student(1,19,"張三1","M",true));

students.add(new Student(1,18,"張三2","M",false));

students.add(new Student(1,21,"張三3","F",true));

students.add(new Student(1,20,"張三4","F",false));

students.add(new Student(1,20,"張三5","F",false));

students.add(new Student(1,20,"張三6","F",false));

for (int i = 0; i < 100; i++) {

Optional student1 = students.stream().filter(student -> student.getSex().equals("F")).findAny();

System.out.println(student1.toString());

}

}

}

結果:

由于數量較大,只截取了部分截圖,全部都是一樣的,不行的小伙伴可以自己測試一下

這時候我們改為串行流在執行一下

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class FindAnyDemo {

public static void main(String[] args) {

//?ndAny用于獲取流中隨機的某一個元素,并且利用短路在找到結果時,立即結束

ArrayList students = new ArrayList<>();

students.add(new Student(1,19,"張三1","M",true));

students.add(new Student(1,18,"張三2","M",false));

students.add(new Student(1,21,"張三3","F",true));

students.add(new Student(1,20,"張三4","F",false));

students.add(new Student(1,20,"張三5","F",false));

students.add(new Student(1,20,"張三6","F",false));

for (int i = 0; i < 100; i++) {

Optional student1 = students.parallelStream().filter(student -> student.getSex().equals("F")).findAny();

System.out.println(student1.toString());

}

}

}

結果:

現在我們通過源碼解析來分析下這是為什么?

根據這一段源碼介紹,?ndAny對于同一數據源的多次操作會返回不同的結果。但是,我們現在的操作是串行的, 所以在數據較少的情況下,一般會返回第一個結果,但是如果在并行的情況下,那就不能確保返回的是第一個了。 這種設計主要是為了獲取更加高效的性能。并行操作后續會做詳細介紹。

傳遞參數,指定不必須獲取第一個元素

在該方法中,主要用于判斷對于當前的操作執行并行還是串行。

在該方法中的wrapAndCopyInto()內部做的會判斷流中是否存在符合條件的元素,如果有的話,則會進行返回。結 果終會封裝到Optional中的IsPresent中。

總結:當為串行流且數據較少時,獲取的結果一般為流中第一個元素,但是當為并流行的時 候,則會隨機獲取。

5.2基于?ndFirst()查找元素

?ndFirst使用原理與findAny類似,只是它無論串行流還是并行流都會返回第一個元素,這里不做詳解

6、歸約

到現在截止,對于流的終端操作,我們返回的有boolean、Optional和List。但是在集合操作中,我們經常會涉及 對元素進行統計計算之類的操作,如求和、求大值、小值等,從而返回不同的數據結果。

6.1基于reduce()進行累積求和

案例:對集合中的元素求和

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class ReduceDemo {

public static void main(String[] args) {

List integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);

Integer reduce = integers.stream().reduce(0, (integer1, integer2) -> integer1 + integer2);

System.out.println(reduce);

}

}

結果:53

在上述代碼中,在reduce里的第一個參數聲明為初始值,第二個參數接收一個lambda表達式,代表當前流中的兩 個元素,它會反復相加每一個元素,直到流被歸約成一個終結果

Integer reduce = integers.stream().reduce(0,Integer::sum);

優化成這樣也是可以的。當然,reduce還有一個不帶初始值參數的重載方法,但是要對返回結果進行判斷,因為如果流中沒有任何元素的話,可能就沒有結果了。具體方法如下所示

List integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);

Optional reduce = integers.stream().reduce(Integer::sum);

if(reduce.isPresent()){

System.out.println(reduce);

}else {

System.out.println("數據有誤");

}

源碼解析:兩個參數的reduce方法

在上述方法中,對于流中元素的操作,當執行第一個元素,會進入begin方法,將初始化的值給到state,state就 是后的返回結果。并執行accept方法,對state和第一個元素根據傳入的操作,對兩個值進行計算。并把終計 算結果賦給state。

當執行到流中第二個元素,直接執行accept方法,對state和第二個元素對兩個值進行計算,并把終計算結果賦 給state。后續依次類推。

可以按照下述代碼進行理解

T?result?=?identity;

for?(T?element?:?this?stream){

result?=?accumulator.apply(result,?element)

}

return?result;

源碼解析:單個參數的reduce方法

在這部分實現中,對于匿名內部類中的empty相當于是一個開關,state相當于結果。

對于流中第一個元素,首先會執行begin()將empty置為true,state為null。接著進入到accept(),判斷empty是否 為true,如果為true,則將empty置為false,同時state置為當前流中第一個元素,當執行到流中第二個元素時, 直接進入到accpet(),判斷empty是否為true,此時empty為false,則會執行apply(),對當前state和第二個元素進 行計算,并將結果賦給state。后續依次類推。

當整個流操作完之后,執行get(), 如果empty為true,則返回一個空的Optional對象,如果為false,則將后計算 完的state存入Optional中。

可以按照下述代碼進行理解:

boolean?flag?=?false;

T?result?=?null;

for?(T?element?:?this?stream)?{

if?(!flag)?{

flag?=?true;

result?=?element;

}else{

result?=?accumulator.apply(result,?element);

}

}

return?flag???Optional.of(result)?:?Optional.empty();

6.2獲取流中元素的最大值、最小值

案例:獲取集合中元素的最大值、最小值

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class MaxDemo {

public static void main(String[] args) {

List integers = Arrays.asList(1, 2, 3, 4, 4, 5, 5, 6, 7, 8, 2, 2, 2, 2);

/**

* 獲取集合中的最大值

*/

//方法一

Optional max1 = integers.stream().reduce(Integer::max);

if(max1.isPresent()){

System.out.println(max1);

}

//方法二

Optional max2 = integers.stream().max(Integer::compareTo);

if(max2.isPresent()){

System.out.println(max2);

}

/**

* 獲取集合中的最小值

*/

//方法一

Optional min1 = integers.stream().reduce(Integer::min);

if(min1.isPresent()){

System.out.println(min1);

}

//方法二

Optional min2 = integers.stream().min(Integer::compareTo);

if(min2.isPresent()){

System.out.println(min2);

}

}

}

結果:

Optional[8]

Optional[8]

Optional[1]

Optional[1]

7、收集器

通過使用收集器,可以讓代碼更加方便的進行簡化與重用。其內部主要核心是通過Collectors完成更加復雜的計算 轉換,從而獲取到終結果。并且Collectors內部提供了非常多的常用靜態方法,直接拿來就可以了。比方說: toList。

/**

* @author 我是七月呀

* @date 2020/12/22

*/

public class CollectDemo {

public static void main(String[] args) {

ArrayList students = new ArrayList<>();

students.add(new Student(1,19,"張三","M",true));

students.add(new Student(1,18,"李四","M",false));

students.add(new Student(1,21,"王五","F",true));

students.add(new Student(1,20,"趙六","F",false));

//通過counting()統計集合總數 方法一

Long collect = students.stream().collect(Collectors.counting());

System.out.println(collect);

//結果 4

//通過count()統計集合總數 方法二

long count = students.stream().count();

System.out.println(count);

//結果 4

//通過maxBy求最大值

Optional collect1 = students.stream().collect(Collectors.maxBy(Comparator.comparing(Student::getAge)));

if(collect1.isPresent()){

System.out.println(collect1);

}

//結果 Optional[Student{id=1, age=21, name='王五', sex='F', isPass=true}]

//通過max求最大值

Optional max = students.stream().max(Comparator.comparing(Student::getAge));

if(max.isPresent()){

System.out.println(max);

}

//結果 Optional[Student{id=1, age=21, name='王五', sex='F', isPass=true}]

//通過minBy求最小值

Optional collect2 = students.stream().collect(Collectors.minBy(Comparator.comparing(Student::getAge)));

if(collect2.isPresent()){

System.out.println(collect2);

}

//結果 Optional[Student{id=1, age=18, name='李四', sex='M', isPass=false}]

//通過min求最小值

Optional min = students.stream().min(Comparator.comparing(Student::getAge));

if(min.isPresent()){

System.out.println(min);

}

//結果 Optional[Student{id=1, age=18, name='李四', sex='M', isPass=false}]

//通過summingInt()進行數據匯總

Integer collect3 = students.stream().collect(Collectors.summingInt(Student::getAge));

System.out.println(collect3);

//結果 78

//通過averagingInt()進行平均值獲取

Double collect4 = students.stream().collect(Collectors.averagingInt(Student::getAge));

System.out.println(collect4);

//結果 19.5

//通過joining()進行數據拼接

String collect5 = students.stream().map(Student::getName).collect(Collectors.joining());

System.out.println(collect5);

//結果 張三李四王五趙六

//復雜結果的返回

IntSummaryStatistics collect6 = students.stream().collect(Collectors.summarizingInt(Student::getAge));

double average = collect6.getAverage();

long sum = collect6.getSum();

long count1 = collect6.getCount();

int max1 = collect6.getMax();

int min1 = collect6.getMin();

}

}

8、分組

在數據庫操作中,經常會通過group by對查詢結果進行分組。同時在日常開發中,也經常會涉及到這一類操作, 如通過性別對學生集合進行分組。如果通過普通編碼的方式需要編寫大量代碼且可讀性不好。

對于這個問題的解決,java8也提供了簡化書寫的方式。通過 Collectors。groupingBy()即可。

//通過性別對學生進行分組

Map> collect = students.stream().collect(Collectors.groupingBy(Student::getSex));

結果 {

F=[Student{id=1, age=21, name='王五', sex='F', isPass=true}, Student{id=1, age=20, name='趙六', sex='F', isPass=false}],

M=[Student{id=1, age=19, name='張三', sex='M', isPass=true}, Student{id=1, age=18, name='李四', sex='M', isPass=false}]

}

8.1多級分組

剛才已經使用groupingBy()完成了分組操作,但是只是通過單一的sex進行分組,那現在如果需求發生改變,還要 按照是否及格進行分組,能否實現?答案是可以的。對于groupingBy()它提供了兩個參數的重載方法,用于完成這 種需求。

這個重載方法在接收普通函數之外,還會再接收一個Collector類型的參數,其會在內層分組(第二個參數)結果,傳 遞給外層分組(第一個參數)作為其繼續分組的依據。

//現根據是否通過考試對學生分組,在根據性別分組

Map>> collect1 = students.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.groupingBy(Student::getPass)));

結果: {

F={

false=[Student{id=1, age=20, name='趙六', sex='F', isPass=false}],

true=[Student{id=1, age=21, name='王五', sex='F', isPass=true}]

},

M={

false=[Student{id=1, age=18, name='李四', sex='M', isPass=false}],

true=[Student{id=1, age=19, name='張三', sex='M', isPass=true}]}

}

8.2多級分組變形

在日常開發中,我們很有可能不是需要返回一個數據集合,還有可能對數據進行匯總操作,比方說對于年齡18歲 的通過的有多少人,未及格的有多少人。因此,對于二級分組收集器傳遞給外層分組收集器的可以任意數據類型, 而不一定是它的數據集合。

//根據年齡進行分組,獲取并匯總人數

Map collect2 = students.stream().collect(Collectors.groupingBy(Student::getAge, Collectors.counting()));

System.out.println(collect2);

結果:{18=1, 19=1, 20=1, 21=1}

//要根據年齡與是否及格進行分組,并獲取每組中年齡的學生

Map> collect3 = students.stream().collect(Collectors.groupingBy(Student::getAge, Collectors.groupingBy(Student::getPass,

Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparing(Student::getAge)), Optional::get))));

System.out.println(collect3.toString());

結果:{

18={false=Student{id=1, age=18, name='李四', sex='M', isPass=false}},

19={true=Student{id=1, age=19, name='張三', sex='M', isPass=true}},

20={false=Student{id=1, age=20, name='趙六', sex='F', isPass=false}},

21={true=Student{id=1, age=21, name='王五', sex='F', isPass=true}}}

總結

以上是生活随笔為你收集整理的java8 stream 最大值_JDK8-Stream流常用方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日本道在线观看 | 凹凸精品熟女在线观看 | 久久综合国产精品 | 亚洲综合日韩在线 | 日本伦理一区二区三区 | 欧美日韩一区二区三区在线 | 久久久久久久久免费 | 青青草综合在线 | 国产精久久 | 尤物视频在线观看免费 | 日韩av大片 | 99riav国产精品| 亚洲人人爽 | 亚洲综合色av | 欧美黄色短片 | 欧美大片大全 | 天天看黄色 | 日韩欧美黄色网址 | av毛片基地| 中文字幕人乱码中文字 | 日韩激情久久 | 99中文字幕在线观看 | wwwxxxx国产 | 欧美不卡在线视频 | 久久久久二区 | 不卡在线视频 | 第四色男人天堂 | 久久avav | 国产肥老妇视频 | 体内精69xxxxxx | 日韩在线不卡一区 | 欧美成人免费观看视频 | 色屁屁一区二区三区视频 | 精品人妻伦一二三区久 | 涩涩涩av | 伊人久久成人 | 久久av资源站 | 可以免费观看av的网站 | 高清乱码毛片 | 狠狠撸在线观看 | 免费观看的av | 99er在线| 福利社91 | 六月激情综合 | 欧洲一区二区 | 欧美成人精品一区二区三区 | 欧美亚洲天堂网 | 东京av男人的天堂 | 影视先锋av资源 | 亚洲涩综合 | 秋霞国产午夜精品免费视频 | 色哟哟一区二区三区四区 | 欧美色图17p | 黄色一区二区视频 | 极品少妇视频 | 激情久久久 | 人人爽人人爽人人片av | 影音先锋在线看 | 亚洲中文无码久久 | 国产视频一区二区不卡 | 暖暖日本在线 | 北条麻妃99精品青青久久 | 国产1区二区 | 亚洲日本不卡 | 毛片毛片毛片毛片毛片 | 欣赏asian国模裸体pics | 日韩va在线观看 | 91精品人妻一区二区三区蜜桃2 | 久久久久久久久免费 | 99中文字幕在线观看 | 中文字幕一区二区人妻电影丶 | 亚洲首页| 欧美精品电影一区二区 | 日韩成人精品一区二区 | 免费av动漫| 四虎影视免费 | 用力挺进新婚白嫩少妇 | 深夜激情网站 | 欧美gv在线观看 | 一二三区免费视频 | 免费观看视频一区二区 | 亚洲熟女一区二区三区 | 爱爱小视频网站 | 欧美日一区二区三区 | 免费在线看视频 | 日本一区久久 | www.狠狠干| 观看av免费| 中国毛片在线观看 | 日韩欧美中文字幕一区二区 | 国产精品欧美精品 | 一区二区三区国产精品 | 黄色喷水网站 | 动漫涩涩免费网站在线看 | 爱蜜臀av| 亚洲va久久久噜噜噜久久天堂 | 视频一区在线播放 | 99久久久国产精品免费蜜臀 | 免费人成在线观看视频播放 |