Java流式編程


演示代碼
package stream;

import lombok.Data;

import java.util.*;
import java.util.stream.Collectors;

public class StreamLearn {
    static List<User> list = new ArrayList<User>() {
        {
            add(new User(1l, "張三", 10, "清華大學"));
            add(new User(2l, "李四", 12, "清華大學"));
            add(new User(3l, "王五", 15, "清華大學"));
            add(new User(4l, "趙六", 12, "清華大學"));
            add(new User(4l, "趙六", 12, "清華大學"));
            add(new User(5l, "田七", 25, "北京大學"));
            add(new User(6l, "小明", 16, "北京大學"));
            add(new User(7l, "小紅", 14, "北京大學"));
            add(new User(8l, "小華", 14, "浙江大學"));
            add(new User(9l, "小麗", 17, "浙江大學"));
            add(new User(10l, "小何", 10, "浙江大學"));
        }
    };

    public static void main(String[] args) {

        List<User> users = list.stream().filter(user -> "清華大學".equals(user.getSchool())).distinct().collect(Collectors.toList());
        users.forEach(user -> System.out.println(user.getName() + ","));
        System.out.println("=====================================");

        List<User> collect = list.stream().filter(user -> user.getAge() % 2 == 0).limit(2).collect(Collectors.toList());
        collect.forEach(user -> {
            System.out.println(user);
        });
        System.out.println("=====================================");

        List<User> collect1 = list.stream().sorted((s1, s2) -> s2.getAge() - s1.getAge()).collect(Collectors.toList());  //默認是從小到大排序,
        collect1.forEach(user -> System.out.println(user));
        System.out.println("=====================================");

        List<User> collect2 = list.stream().skip(2).collect(Collectors.toList());
        collect2.forEach(user -> System.out.println(user));
        System.out.println("=====================================");

        List<Object> collect3 = list.stream().filter(user -> "清華大學".equals(user.getSchool())).map(User::getName).collect(Collectors.toList());
        collect3.forEach(userName -> System.out.println(userName));
        System.out.println("=====================================");

        int sum = list.stream().filter(user -> "清華大學".equals(user.getSchool())).mapToInt(User::getAge).sum();
        System.out.println("學校是清華大學的年齡總和" + sum);
        System.out.println("=====================================");

        String[] strings = {"hello", "world"};
        List<String> collect4 = Arrays.asList(strings).stream().map(s -> s.split("")).flatMap(Arrays::stream).distinct().collect(Collectors.toList());
        collect4.forEach(s -> System.out.print(s));
        System.out.println("=====================================");

        boolean b = list.stream().anyMatch(user -> user.getAge() > 15);
        boolean c = list.stream().noneMatch(user -> user.getAge() == 18);
        System.out.println(b);
        System.out.println(c);
        System.out.println("=====================================");

        Optional<User> any = list.stream().filter(user -> user.getAge() > 10).findAny();
        Optional<User> first = list.stream().filter(user -> user.getAge() > 10).findFirst();
        User user = any.get();
        System.out.println(user);
        System.out.println(first.get());
        System.out.println("=====================================");

        Integer reduce = list.stream().filter(student -> "清華大學".equals(student.getSchool())).map(User::getAge).reduce(0, (a, d) -> a + d);
        Integer reduce1 = list.stream().filter(student -> "清華大學".equals(student.getSchool())).map(User::getAge).reduce(0, Integer::sum);
        Integer integer = list.stream().filter(student -> "清華大學".equals(student.getSchool())).map(User::getAge).reduce(Integer::sum).get();
        System.out.println(reduce);
        System.out.println(reduce1);
        System.out.println(integer);
        System.out.println("=====================================");

        Integer age = list.stream().collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge())).get().getAge();
        Integer age1 = list.stream().collect(Collectors.minBy((s1, s2) -> s1.getAge() - s2.getAge())).get().getAge();
        Integer collect5 = list.stream().collect(Collectors.maxBy(Comparator.comparing(User::getAge))).get().getAge();
        Integer collect6 = list.stream().collect(Collectors.minBy(Comparator.comparing(User::getAge))).get().getAge();
        System.out.println(age);
        System.out.println(age1);
        System.out.println(collect5);
        System.out.println(collect6);
        System.out.println("=====================================");

        Integer sumAge = list.stream().collect(Collectors.summingInt(User::getAge));
        System.out.println(sumAge);
        Double collect7 = list.stream().collect(Collectors.averagingDouble(User::getAge));
        IntSummaryStatistics collect8 = list.stream().collect(Collectors.summarizingInt(User::getAge));
        System.out.println(collect7);
        System.out.println(collect8);
        System.out.println("=====================================");

        String collect9 = list.stream().map(User::getName).collect(Collectors.joining(","));
        System.out.println(collect9);
        System.out.println("======================================");

        System.out.println("分組");
        Map<String, List<User>> collect11 = list.stream().collect(Collectors.groupingBy(User::getSchool));
        Map<String, Map<Integer, Long>> collect21 = list.stream().collect(Collectors.groupingBy(User::getSchool, Collectors.groupingBy(User::getAge, Collectors.counting())));
        Map<String, Map<Integer, Map<String, Long>>> collect41 = list.stream().collect(Collectors.groupingBy(User::getSchool, Collectors.groupingBy(User::getAge, Collectors.groupingBy(User::getName,Collectors.counting()))));
        Map<String, Long> collect31 = list.stream().collect(Collectors.groupingBy(User::getSchool, Collectors.counting()));
        System.out.println("collect1 = " + collect11);
        System.out.println("collect2 = " + collect21);
        System.out.println("collect3 = " + collect31);
        System.out.println("collect4 = " + collect41);


    }

}

@Data
class User {
    private Long id;       //主鍵id
    private String name;   //姓名
    private Integer age;   //年齡
    private String school; //學校

    public User(Long id, String name, Integer age, String school) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.school = school;
    }
}

https://www.cnblogs.com/gaopengfirst/p/10813803.html

在Java1.8之前還沒有stream流式算法的時候,我們要是在一個放有多個User對象的list集合中,將每個User對象的主鍵ID取出,組合成一個新的集合,首先想到的肯定是遍歷,如下:

1
2
3
4
List<Long> userIdList =  new  ArrayList<>();
for  (User user: list) {
      userIdList.add(user.id);
}

或者在1.8有了lambda表達式以后,我們會這樣寫:

1
2
List<Long> userIdList =  new  ArrayList<>();
list.forEach(user -> list.add(user.id));

在有了stream之后,我們還可以這樣寫:

1
List<Long> userIdList = list.stream().map(User::getId).collect(Collectors.toList());  

一行代碼直接搞定,是不是很方便呢。那么接下來。我們就一起看一下stream這個流式算法的新特性吧。

由上面的例子可以看出,java8的流式處理極大的簡化了對於集合的操作,實際上不光是集合,包括數組、文件等,只要是可以轉換成流,我們都可以借助流式處理,類似於我們寫SQL語句一樣對其進行操作。java8通過內部迭代來實現對流的處理,一個流式處理可以分為三個部分:轉換成流、中間操作、終端操作。如下圖:

以集合為例,一個流式處理的操作我們首先需要調用stream()函數將其轉換成流,然后再調用相應的中間操作達到我們需要對集合進行的操作,比如篩選、轉換等,最后通過終端操作對前面的結果進行封裝,返回我們需要的形式。

這里我們先創建一個User實體類:

1
2
3
4
5
6
7
8
9
10
11
12
class  User{
private  Long id;        //主鍵id
private  String name;    //姓名
private  Integer age;    //年齡
private  String school;  //學校
public  User(Long id, String name, Integer age, String school) {
    this .id = id;
    this .name = name;
    this .age = age;
    this .school = school;
}
此處省略get、set方法。。。

初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<User> list =  new  ArrayList<User>(){
     {
         add( new  User(1l, "張三" , 10 "清華大學" ));
         add( new  User(2l, "李四" , 12 "清華大學" ));
         add( new  User(3l, "王五" , 15 "清華大學" ));
         add( new  User(4l, "趙六" , 12 "清華大學" ));
         add( new  User(5l, "田七" , 25 "北京大學" ));
         add( new  User(6l, "小明" , 16 "北京大學" ));
         add( new  User(7l, "小紅" , 14 "北京大學" ));
         add( new  User(8l, "小華" , 14 "浙江大學" ));
         add( new  User(9l, "小麗" , 17 "浙江大學" ));
         add( new  User(10l, "小何" , 10 "浙江大學" ));
     }
};

1. 過濾  

1.1 filter

我們希望過濾賽選處所有學校是清華大學的user:

System.out.println("學校是清華大學的user");
List<User> userList1 = list.stream().filter(user -> "清華大學".equals(user.getSchool())).collect(Collectors.toList());
userList1.forEach(user -> System.out.print(user.name + '、'));

控制台輸出結果為:

1
2
學校是清華大學的user
張三、李四、王五、趙六、

1.2 distinct

去重,我們希望獲取所有user的年齡(年齡不重復)

1
2
3
System.out.println( "所有user的年齡集合" );
List<Integer> userAgeList = list.stream().map(User::getAge).distinct().collect(Collectors.toList());
System.out.println( "userAgeList = "  + userAgeList);

map在下面會講到,現在主要是看distinct的用法,輸出結果如下:

1
2
所有user的年齡集合
userAgeList = [ 10 12 15 25 16 14 17 ]

1.3 limit 

返回前n個元素的流,當集合的長度小於n時,則返回所有集合。

如獲取年齡是偶數的前2名user:

1
2
3
System.out.println( "年齡是偶數的前兩位user" );
List<User> userList3 = list.stream().filter(user -> user.getAge() %  2  ==  0 ).limit( 2 ).collect(Collectors.toList());
userList3.forEach(user -> System.out.print(user.name +  '、' ));

輸出結果為:

1
2
年齡是偶數的前兩位user
張三、李四、

1.4 sorted

排序,如現在我想將所有user按照age從大到小排序:

1
2
3
System.out.println( "按年齡從大到小排序" );
List<User> userList4 = list.stream().sorted((s1,s2) -> s2.age - s1.age).collect(Collectors.toList());
userList4.forEach(user -> System.out.print(user.name +  '、' ));

輸出結果為:

1
2
按年齡從大到小排序
田七、小麗、小明、王五、小紅、小華、李四、趙六、張三、小何、

1.5 skip

跳過n個元素后再輸出

如輸出list集合跳過前兩個元素后的list

1
2
3
System.out.println( "跳過前面兩個user的其他所有user" );
List<User> userList5 = list.stream().skip( 2 ).collect(Collectors.toList());
userList5.forEach(user -> System.out.print(user.name +  '、' ));

輸出結果為:

1
2
跳過前面兩個user的其他所有user
王五、趙六、田七、小明、小紅、小華、小麗、小何、

2 映射

2.1 map

就是講user這個幾個精簡為某個字段的集合

如我現在想知道學校是清華大學的所有學生的姓名:

1
2
3
System.out.println( "學校是清華大學的user的名字" );
List<String> userList6 = list.stream().filter(user ->  "清華大學" .equals(user.school)).map(User::getName).collect(Collectors.toList());
userList6.forEach(user -> System.out.print(user +  '、' ));  

輸出結果如下:

1
2
學校是清華大學的user的名字
張三、李四、王五、趙六、

除了上面這類基礎的map,java8還提供了mapToDouble(ToDoubleFunction<? super T> mapper),mapToInt(ToIntFunction<? super T> mapper),mapToLong(ToLongFunction<? super T> mapper),這些映射分別返回對應類型的流,java8為這些流設定了一些特殊的操作,比如查詢學校是清華大學的user的年齡總和:

1
2
3
System.out.println( "學校是清華大學的user的年齡總和" );
int  userList7 = list.stream().filter(user ->  "清華大學" .equals(user.school)).mapToInt(User::getAge).sum();
System.out.println(  "學校是清華大學的user的年齡總和為: " +userList7);

輸出結果為:

1
2
學校是清華大學的user的年齡總和
學校是清華大學的user的年齡總和為:  49

1.2 flatMap

flatMap與map的區別在於 flatMap是將一個流中的每個值都轉成一個個流,然后再將這些流扁平化成為一個流 。舉例說明,假設我們有一個字符串數組String[] strs = {"hello", "world"};,我們希望輸出構成這一數組的所有非重復字符,那么我們用map和flatMap 實現如下:

1
2
3
4
5
String[] strings = { "Hello" "World" };
List l11 = Arrays.stream(strings).map(str -> str.split( "" )).map(str2->Arrays.stream(str2)).distinct().collect(Collectors.toList());
List l2 = Arrays.asList(strings).stream().map(s -> s.split( "" )).flatMap(Arrays::stream).distinct().collect(Collectors.toList());
System.out.println(l11.toString());
System.out.println(l2.toString());  

輸出結果如下:

1
2
[java.util.stream.ReferencePipeline$Head @4c203ea1 , java.util.stream.ReferencePipeline$Head @27f674d ]
[H, e, l, o, W, r, d]  

由上我們可以看到使用map並不能實現我們現在想要的結果,而flatMap是可以的。這是因為在執行map操作以后,我們得到是一個包含多個字符串(構成一個字符串的字符數組)的流,此時執行distinct操作是基於在這些字符串數組之間的對比,所以達不到我們希望的目的;flatMap將由map映射得到的Stream<String[]>,轉換成由各個字符串數組映射成的流Stream<String>,再將這些小的流扁平化成為一個由所有字符串構成的大流Steam<String>,從而能夠達到我們的目的。

3 查找

3.1 allMatch

用於檢測是否全部都滿足指定的參數行為,如果全部滿足則返回true,例如我們判斷是否所有的user年齡都大於9歲,實現如下:

1
2
3
System.out.println( "判斷是否所有user的年齡都大於9歲" );
Boolean b = list.stream().allMatch(user -> user.age > 9 );
System.out.println(b);

輸出結果為:

1
2
判斷是否所有user的年齡都大於 9
true

3.2 anyMatch

anyMatch則是檢測是否存在一個或多個滿足指定的參數行為,如果滿足則返回true,例如判斷是否有user的年齡大於15歲,實現如下:

1
2
3
System.out.println( "判斷是否有user的年齡是大於15歲" );
Boolean bo = list.stream().anyMatch(user -> user.age > 15 );
System.out.println(bo);

輸出結果為:

1
2
判斷是否有user的年齡是大於 15
true

3.3 noneMatch  

noneMatch用於檢測是否不存在滿足指定行為的元素,如果不存在則返回true,例如判斷是否不存在年齡是15歲的user,實現如下:

1
2
3
System.out.println( "判斷是否不存在年齡是15歲的user" );
Boolean boo = list.stream().noneMatch(user -> user.age ==  15 );
System.out.println(boo);

輸出結果如下:

1
2
判斷是否不存在年齡是 15 歲的user
false

3.4 findFirst

findFirst用於返回滿足條件的第一個元素,比如返回年齡大於12歲的user中的第一個,實現如下:

1
2
3
4
System.out.println( "返回年齡大於12歲的user中的第一個" );
Optional<User> first = list.stream().filter(u -> u.age >  10 ).findFirst();
User user = first.get();
System.out.println(user.toString());

輸出結果如下:

1
2
返回年齡大於 12 歲的user中的第一個
User{id= 2 , name= '李四' , age= 12 , school= '清華大學' }

3.5 findAny

findAny相對於findFirst的區別在於,findAny不一定返回第一個,而是返回任意一個,比如返回年齡大於12歲的user中的任意一個:

1
2
3
4
System.out.println( "返回年齡大於12歲的user中的任意一個" );
Optional<User> anyOne = list.stream().filter(u -> u.age >  10 ).findAny();
User user2 = anyOne.get();
System.out.println(user2.toString());

輸出結果如下:

1
2
返回年齡大於 12 歲的user中的任意一個
User{id= 2 , name= '李四' , age= 12 , school= '清華大學' }

4 歸約

4.1 reduce

現在我的目標不是返回一個新的集合,而是希望對經過參數化操作后的集合進行進一步的運算,那么我們可用對集合實施歸約操作。java8的流式處理提供了reduce方法來達到這一目的。

比如我現在要查出學校是清華大學的所有user的年齡之和:

//前面用到的方法
Integer ages = list.stream().filter(student -> "清華大學".equals(student.school)).mapToInt(User::getAge).sum();
System.out.println(ages);
System.out.println("歸約 - - 》 start ");
Integer ages2 = list.stream().filter(student -> "清華大學".equals(student.school)).map(User::getAge).reduce(0,(a,c)->a+c);
Integer ages3 = list.stream().filter(student -> "清華大學".equals(student.school)).map(User::getAge).reduce(0,Integer::sum);
Integer ages4 = list.stream().filter(student -> "清華大學".equals(student.school)).map(User::getAge).reduce(Integer::sum).get();
System.out.println(ages2);
System.out.println(ages3);
System.out.println(ages4);
System.out.println("歸約 - - 》 end ");

輸出結果為:

49
歸約 - - 》 start
49
49
49
歸約 - - 》 end

5 收集

前面利用collect(Collectors.toList())是一個簡單的收集操作,是對處理結果的封裝,對應的還有toSet、toMap,以滿足我們對於結果組織的需求。這些方法均來自於java.util.stream.Collectors,我們可以稱之為收集器。

收集器也提供了相應的歸約操作,但是與reduce在內部實現上是有區別的,收集器更加適用於可變容器上的歸約操作,這些收集器廣義上均基於Collectors.reducing()實現。

5.1 counting 

計算個數

如我現在計算user的總人數,實現如下:

1
2
3
4
5
System.out.println( "user的總人數" );
long  COUNT = list.stream().count(); //簡化版本
long  COUNT2 = list.stream().collect(Collectors.counting()); //原始版本
System.out.println(COUNT);
System.out.println(COUNT2);

輸出結果為:

1
2
3
user的總人數
10
10

5.2 maxBy、minBy

計算最大值和最小值

如我現在計算user的年齡最大值和最小值:

1
2
3
4
5
6
7
8
9
System.out.println( "user的年齡最大值和最小值" );
Integer maxAge =list.stream().collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge())).get().age;
Integer maxAge2 = list.stream().collect(Collectors.maxBy(Comparator.comparing(User::getAge))).get().age;
Integer minAge = list.stream().collect(Collectors.minBy((S1,S2) -> S1.getAge()- S2.getAge())).get().age;
Integer minAge2 = list.stream().collect(Collectors.minBy(Comparator.comparing(User::getAge))).get().age;
System.out.println( "maxAge = "  + maxAge);
System.out.println( "maxAge2 = "  + maxAge2);
System.out.println( "minAge = "  + minAge);
System.out.println( "minAge2 = "  + minAge2);

輸出結果為:

1
2
3
4
5
user的年齡最大值
maxAge =  25
maxAge2 =  25
minAge =  10
minAge2 =  10

5.3 summingInt、summingLong、summingDouble

總和

如計算user的年齡總和:

1
2
3
System.out.println( "user的年齡總和" );
Integer sumAge =list.stream().collect(Collectors.summingInt(User::getAge));
System.out.println( "sumAge = "  + sumAge);

輸出結果為:

1
2
user的年齡總和
sumAge =  145

5.4 averageInt、averageLong、averageDouble

平均值

如計算user的年齡平均值:

1
2
3
System.out.println( "user的年齡平均值" );
double  averageAge = list.stream().collect(Collectors.averagingDouble(User::getAge));
System.out.println( "averageAge = "  + averageAge);

輸出結果為:

1
2
user的年齡平均值
averageAge =  14.5

5.5 summarizingInt、summarizingLong、summarizingDouble

一次性查詢元素個數、總和、最大值、最小值和平均值

1
2
3
4
5
6
System.out.println( "一次性得到元素個數、總和、均值、最大值、最小值" );
long  l1 = System.currentTimeMillis();
IntSummaryStatistics summaryStatistics = list.stream().collect(Collectors.summarizingInt(User::getAge));
long  l111 = System.currentTimeMillis();
System.out.println( "計算這5個值消耗時間為"  + (l111-l1));
System.out.println( "summaryStatistics = "  + summaryStatistics);

輸出結果為:

1
2
3
一次性得到元素個數、總和、均值、最大值、最小值
計算這 5 個值消耗時間為 3
summaryStatistics = IntSummaryStatistics{count= 10 , sum= 145 , min= 10 , average= 14.500000 , max= 25 }

5.6 joining

字符串拼接

如輸出所有user的名字,用“,”隔開

1
2
3
System.out.println( "字符串拼接" );
String names = list.stream().map(User::getName).collect(Collectors.joining( "," ));
System.out.println( "names = "  + names);

輸出結果為:

1
2
字符串拼接
names = 張三,李四,王五,趙六,田七,小明,小紅,小華,小麗,小何

5.7 groupingBy

分組

如將user根據學校分組、先按學校分再按年齡分、每個大學的user人數、每個大學不同年齡的人數:

1
2
3
4
5
6
7
8
9
System.out.println( "分組" );
Map<String, List<User>> collect1 = list.stream().collect(Collectors.groupingBy(User::getSchool));
Map<String, Map<Integer, Long>> collect2 = list.stream().collect(Collectors.groupingBy(User::getSchool, Collectors.groupingBy(User::getAge, Collectors.counting())));
Map<String, Map<Integer, Map<String, Long>>> collect4 = list.stream().collect(Collectors.groupingBy(User::getSchool, Collectors.groupingBy(User::getAge, Collectors.groupingBy(User::getName,Collectors.counting()))));
Map<String, Long> collect3 = list.stream().collect(Collectors.groupingBy(User::getSchool, Collectors.counting()));
System.out.println( "collect1 = "  + collect1);
System.out.println( "collect2 = "  + collect2);
System.out.println( "collect3 = "  + collect3);
System.out.println( "collect4 = "  + collect4);

輸出結果為:

1
2
3
4
5
分組
collect1 = {浙江大學=[User{id= 8 , name= '小華' , age= 14 , school= '浙江大學' }, User{id= 9 , name= '小麗' , age= 17 , school= '浙江大學' }, User{id= 10 , name= '小何' , age= 10 , school= '浙江大學' }], 北京大學=[User{id= 5 , name= '田七' , age= 25 , school= '北京大學' }, User{id= 6 , name= '小明' , age= 16 , school= '北京大學' }, User{id= 7 , name= '小紅' , age= 14 , school= '北京大學' }], 清華大學=[User{id= 1 , name= '張三' , age= 10 , school= '清華大學' }, User{id= 2 , name= '李四' , age= 12 , school= '清華大學' }, User{id= 3 , name= '王五' , age= 15 , school= '清華大學' }, User{id= 4 , name= '趙六' , age= 12 , school= '清華大學' }]}
collect2 = {浙江大學={ 17 = 1 10 = 1 14 = 1 }, 北京大學={ 16 = 1 25 = 1 14 = 1 }, 清華大學={ 10 = 1 12 = 2 15 = 1 }}
collect3 = {浙江大學= 3 , 北京大學= 3 , 清華大學= 4 }
collect4 = {浙江大學={ 17 ={小麗= 1 },  10 ={小何= 1 },  14 ={小華= 1 }}, 北京大學={ 16 ={小明= 1 },  25 ={田七= 1 },  14 ={小紅= 1 }}, 清華大學={ 10 ={張三= 1 },  12 ={李四= 1 , 趙六= 1 },  15 ={王五= 1 }}}

5.8 partitioningBy  

分區,分區可以看做是分組的一種特殊情況,在分區中key只有兩種情況:true或false,目的是將待分區集合按照條件一分為二,java8的流式處理利用ollectors.partitioningBy()方法實現分區。

如按照是否是清華大學的user將左右user分為兩個部分:

1
2
3
System.out.println( "分區" );
Map<Boolean, List<User>> collect5 = list.stream().collect(Collectors.partitioningBy(user1 ->  "清華大學" .equals(user1.school)));
System.out.println( "collect5 = "  + collect5);

輸出結果為:

 
1
2
分區
collect5 = { false =[User{id= 5 , name= '田七' , age= 25 , school= '北京大學' }, User{id= 6 , name= '小明' , age= 16 , school= '北京大學' }, User{id= 7 , name= '小紅' , age= 14 , school= '北京大學' }, User{id= 8 , name= '小華' , age= 14 , school= '浙江大學' }, User{id= 9 , name= '小麗' , age= 17 , school= '浙江大學' }, User{id= 10 , name= '小何' , age= 10 , school= '浙江大學' }],  true =[User{id= 1 , name= '張三' , age= 10 , school= '清華大學' }, User{id= 2 , name= '李四' , age= 12 , school= '清華大學' }, User{id= 3 , name= '王五' , age= 15 , school= '清華大學' }, User{id= 4 , name= '趙六' , age= 12 , school= '清華大學' }]}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM