【java】集合流式編程總結


在具體的介紹之前,先總結一波常用的寫法,有基礎的可以直接拿來用,沒有基礎的可以先跳過,看完下面的基礎再回來看

List<User> userList = new ArrayList<>();
    userList.addAll(Arrays.asList(
        new User(1, 11, "張三"),
        new User(1, 11, "張三"),
        new User(2, 22, "李四"),
        new User(1, 33, "王五"),
        new User(2, 44, "趙六"),
        new User(2, 44, "趙六")));
    //----------------------------------------------中間操作----------------------------------------------
    //【filter】從列表中篩選出性別為女的數據
    List<User> filterUsage = userList.stream().filter(s->s.getSex() == 2).collect(Collectors.toList());
    //結果:[User(sex=2, age=22, name=李四), User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六)]
    System.out.println(filterUsage);
    //【distinct】從列表中去重
    List<User> distinctUsage = userList.stream().distinct().collect(Collectors.toList());
    //結果:[User(sex=1, age=11, name=張三), User(sex=2, age=22, name=李四), User(sex=1, age=33, name=王五), User(sex=2, age=44, name=趙六)]
    System.out.println(distinctUsage);
    //【sorted】按照年齡字段從大到小重新排序 (從小到大就是s1.getAge()-s2.getAge())
    List<User> sortedUsage = userList.stream().sorted((s1,s2)->s2.getAge()-s1.getAge()).collect(Collectors.toList());
    //結果:[User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六), User(sex=1, age=33, name=王五), User(sex=2, age=22, name=李四), User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三)]
    System.out.println(sortedUsage);
    //【limit】獲取前兩條數據
    List<User> limitUsage = userList.stream().limit(2).collect(Collectors.toList());
    //結果:[User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三)]
    System.out.println(limitUsage);
    //【skip】跳過前兩條,之后獲取前三條數據
    List<User> skipUsage = userList.stream().skip(2).limit(3).collect(Collectors.toList());
    //結果:[User(sex=2, age=22, name=李四), User(sex=1, age=33, name=王五), User(sex=2, age=44, name=趙六)]
    System.out.println(skipUsage);
    //【map】獲取所有人的姓名
    List<String> mapUsage = userList.stream().map(User::getName).collect(Collectors.toList());
    //結果:[張三, 張三, 李四, 王五, 趙六, 趙六]
    System.out.println(mapUsage);
    //【flatMap】

    //【Collectors工具類一些常用方法】
    //【groupingBy】分組
    // 將集合中的數據按照姓名分組
    Map<String, List<User>> groupingByUsage = userList.stream().collect(Collectors.groupingBy(s -> s.getName()));
    //結果:{李四=[User(sex=2, age=22, name=李四)], 張三=[User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三)],
    //      王五=[User(sex=1, age=33, name=王五)], 趙六=[User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六)]}
    System.out.println(groupingByUsage);
    // 將集合中的數據按照姓名+性別分組
    Map<String, List<User>> groupingByUsage2 = userList.stream().collect(Collectors.groupingBy(s -> s.getName() + "#" + s.getSex()));
    //結果:{張三#1=[User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三)], 李四#2=[User(sex=2, age=22, name=李四)],
    //      趙六#2=[User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六)], 王五#1=[User(sex=1, age=33, name=王五)]}
    System.out.println(groupingByUsage2);
    //【maxBy】獲取集合中年齡最大的對象信息
    User maxByUsage = userList.stream().collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge())).get();
    //結果:User(sex=2, age=44, name=趙六)
    System.out.println(maxByUsage);
    //【minBy】獲取集合中年齡最小的對象信息
    User minByUsage = userList.stream().collect(Collectors.minBy((s1, s2) -> s1.getAge() - s2.getAge())).get();
    //結果:User(sex=1, age=11, name=張三)
    System.out.println(minByUsage);
    //【joining】拼接集合中所有的用戶名稱---直接拼接
    String joiningUsage = userList.stream().map(User::getName).collect(Collectors.joining());
    //結果:張三張三李四王五趙六趙六
    System.out.println(joiningUsage);
    //拼接中間加上逗號
    String joiningUsage2 = userList.stream().map(User::getName).collect(Collectors.joining(","));
    //結果:張三,張三,李四,王五,趙六,趙六
    System.out.println(joiningUsage2);
    //拼接中間加上逗號,兩邊加上前后綴
    String joiningUsage3 = userList.stream().map(User::getName).collect(Collectors.joining(",","[","]"));
    //結果:[張三,張三,李四,王五,趙六,趙六]
    System.out.println(joiningUsage3);
    //【counting】獲取集合中對象的數量
    Long countingUsage = userList.stream().collect(Collectors.counting());
    //結果:6
    System.out.println(countingUsage);
    //【summingInt】獲取集合中所有對象年齡的和
    int summingIntUsage = userList.stream().collect(Collectors.summingInt(User::getAge));
    //結果:165
    System.out.println(summingIntUsage);
    //【averagingInt】獲取集合中所有對象年齡的平均值
    Double averagingIntUsage = userList.stream().collect(Collectors.averagingInt(User::getAge));
    //結果:27.5
    System.out.println(averagingIntUsage);
    //【summarizingInt】獲取集合中所有對象的數量/和/最大值/最小值/平均值等信息
    IntSummaryStatistics summarizingIntUsage = userList.stream().collect(Collectors.summarizingInt(User::getAge));
    //結果:IntSummaryStatistics{count=6, sum=165, min=11, average=27.500000, max=44}
    System.out.println(summarizingIntUsage);

    //----------------------------------------------最終操作----------------------------------------------

    //【collect】
    //這里不做演示,上面的所有例子中都有用到
    //【reduce】將集合中的所有性別字段的值按照相加的規則求乘積
    Integer reduceUsage = userList.stream().map(User::getSex).reduce((s1, s2) -> s1 * s2).get();
    //結果:8
    System.out.println(reduceUsage);
    //【count】求集合中對象的數量
    long countUsage = userList.stream().count();
    //結果:6
    System.out.println(countUsage);
    //【forEach】遍歷出所有的對象的名稱
    Consumer<String> action = System.out::println;
    //結果:張三 張三 李四 王五 趙六 趙六
    userList.stream().map(User::getName).forEach(action);
    //【max&min】獲取集合中所有對象中年齡的最大值和最小值
    Integer maxUsage = userList.stream().map(User::getAge).max(Integer::compareTo).get();
    //結果:44
    System.out.println(maxUsage);
    Integer minUsage = userList.stream().map(User::getAge).min(Integer::compareTo).get();
    //結果:11
    System.out.println(minUsage);
    //【Matching -> allMatch、anyMatch、noneMatch】
    //allMatch:只有當流中所有的元素,都匹配指定的規則,才會返回true
    boolean allMatchUsage = userList.stream().map(User::getAge).allMatch(e -> e >= 44);
    //結果:false
    System.out.println(allMatchUsage);
    //anyMatch:只要流中有任意的數據,滿足指定的規則,都會返回true
    boolean anyMatchUsage = userList.stream().map(User::getAge).anyMatch(e -> e <= 11);
    //結果:true
    System.out.println(anyMatchUsage);
    //noneMatch:只有當流中所有的元素,都不滿足指定的規則,才會返回true
    boolean noneMatchUsage = userList.stream().map(User::getAge).noneMatch(e -> e < 11);
    //結果:true
    System.out.println(noneMatchUsage);
    //【find--> findFirst、findAny】【parallelStream並行流、stream串行流】
    //findFirst:從流中獲取開頭第一個元素
    User user = userList.stream().findFirst().get();
    //結果:User(sex=1, age=11, name=張三)
    System.out.println(user);
    User user2 = userList.parallelStream().findFirst().get();
    //結果:User(sex=1, age=11, name=張三)
    System.out.println(user2);
    //findAny:單線程是獲取第一個元素,多線程可能不一樣
    User user3 = userList.stream().findAny().get();
    //結果:User(sex=1, age=11, name=張三)
    System.out.println(user3);
    User user4 = userList.parallelStream().findAny().get();
    //結果:User(sex=1, age=33, name=王五)
    System.out.println(user4);
    //【IntStream+summaryStatistics】獲取int數組中的最大值
    //1.准備一個int數組作為數據源
    int[] array = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    //2.讀取數據到流中,獲取IntStream對象
    IntStream intStream = Arrays.stream(array);
    //兩種方法:(不能一起用,因為是中間操作)
    //1. 直接通過IntStream來獲取
    //System.out.println(intStream.max().getAsInt());
    //2. 通過IntSummaryStatistics,里面包括最大/最小/平均/數量等方法
    IntSummaryStatistics intSummaryStatistics = intStream.summaryStatistics();
    //結果:9
    System.out.println(intSummaryStatistics.getMax());

    //----------------------------------------------其它操作----------------------------------------------
    //【list轉數組1】
    Integer[] ints = userList.stream().map(User::getAge).toArray(Integer[]::new);
    //【list轉數組2】
    List<String> list = new ArrayList();
    list.add("1");
    list.add("2");
    list.add("3");
    String[] strings = list.toArray(new String[list.size()]);
    //【數組轉list】
    String[] arrays = {"1", "2", "3"};
    List<String> listStrings = Stream.of(arrays).collect(Collectors.toList());
    //結果:[1, 2, 3]
    System.out.println(listStrings);
    //【修改集合中的對象屬性的值】
    //原值:[User(sex=1, age=11, name=張三), User(sex=1, age=11, name=張三), User(sex=2, age=22, name=李四), 
    //      User(sex=1, age=33, name=王五), User(sex=2, age=44, name=趙六), User(sex=2, age=44, name=趙六)]
    System.out.println(userList);
    userList.forEach(s->{
        s.setAge(100);
        s.setSex(100);
    });
    //新值:[User(sex=100, age=100, name=張三), User(sex=100, age=100, name=張三),User(sex=100, age=100, name=李四), 
    // User(sex=100, age=100, name=王五), User(sex=100, age=100, name=趙六), User(sex=100, age=100, name=趙六)]
    System.out.println(userList);
View Code

、集合流的簡介

1. 集合的流式編程的簡介

Stream是JDK1.8之后出現的新特性,也是JDK1.8新特性中最值得學習的兩種新特性之一(另一個是lambda表達式)Stream是對集合操作的增強,流不是集合的元素,不是一種數據結構,不負責數據的存儲的。流更像是一個迭代器,可以單向的遍歷一個集合中的每一個元素,並且不可循環。

2. 為什么要使用集合的流式編程

有些時候,對集合中的元素進行操作的時候,需要使用到其他操作的結果。在這個過程中,集合的流式編程可以大幅度的簡化代碼的數量。將數據源中的數據,讀取到一個流中,可以對這個流中的數據進行操作(刪除、過濾、映射...)。每次的操作結果也是一個流對象,可以對這個流再進行其它的操作。

3. 使用流式編程的步驟

通常情況下,對集合中的數據使用流式編程,需要經過以下三步:

 (1)獲取數據源,將數據源中的數據讀取到流中
 (2)對流中的數據進行各種各樣的處理
 (3)對流中的數據進行整合處理

在上述三個過程:

 (1)過程2中,有若干方法,可以對流中的數據進行各種各樣的操作,並且返回流對象本身,這樣的操作,被稱為中間操作
 (2)過程3中,有若干方法,可以對流中的數據進行各種處理,並關閉流,這樣的操作,被稱為最終操作

在中間操作和最終操作中,基本上所有的方法參數都是函數式接口,可以使用lambda表達式來實現。使用集合的流式編程,來簡化代碼量。

二、數據源的獲取

1. 數據源的簡介

數據源,顧名思義,就是流中的數據的來源,是集合的流式編程的第一步,將數據源中的數據讀取到流中,進行處理。注意:將數據讀取到流中進行處理的時候,與數據源中的數據沒有關系。也就是說,中間操作對流中的數據進行處理、過濾、映射、排序...是不會影響到數據源中的數據的。

2. 數據源的獲取

這個過程,其實是將一個容器中的數據,讀取到一個流中,因此無論什么容器作為數據源,讀取到流中的方法返回值一定是一個Stream。

public static void main(String[] args) throws Exception{
    //將集合作為數據源,讀取集合中的數據到一個流中
    collectionDataSource();
    //將數組作為數據源,讀取數組中的數據到一個流中(使用引用數據類型)
    arrayDataSource();
    //將數組作為數據源,讀取數組中的數據到一個流中(使用基本數據類型)
}

//將集合作為數據源,讀取集合中的數據到一個流中
public static void collectionDataSource(){
    //1.實例化一個集合
    List<Integer> list = new ArrayList<>();
    //2.填充元素
    Collections.addAll(list,0,1,2,3,4,5,6,7,8,9);
    //3.讀取集合中的數據,將其讀取到流中
    //Stream<Integer> stream = list.stream();//同步流
    Stream<Integer> integerStream = list.parallelStream();//並發流
    //4.輸出stream
    System.out.println(integerStream);//java.util.stream.ReferencePipeline$Head@4554617c
}

//將數組作為數據源,讀取數組中的數據到一個流中
public static void arrayDataSource(){
    //1.實例化一個數組
    Integer[] array = new Integer[]{0,1,2,3,4,5,6,7,8,9};
    //2.讀取數組中的數據到流中,得到一個流對象
    Stream<Integer> stream = Arrays.stream(array);
    //3.輸出Stream
    System.out.println(stream);
}

//將數組作為數據源,讀取數組中的數據到一個流中
//集合中只能存引用數據類型,但是數組中不用
public static void arrayDataSource2(){
    //1.實例化一個數組
    int[] array = new int[]{0,1,2,3,4,5,6,7,8,9};
    //2.讀取數組中的數據到流中,得到一個流對象
    IntStream stream = Arrays.stream(array);
    //3.輸出Stream
    System.out.println(stream);
}

三、最終操作

將流中的數據整合到一起,可以存入一個集合,也可以直接對流中的數據進行遍歷,數據統計...通過最終操作,需要掌握如何從流中提取出來我們想要的信息。

注意事項:最終操作,在執行結束之后,會關閉這個流,流中的所有數據都會被銷毀,如果使用一個已經關閉了的流,會出現異常。

最終操作包括:collect、reduce、count、forEach、max&min、Matching、find、IntStream等。

1. collect

將流中的數據收集到一起,對這些數據進行一些處理。最常見的處理,就是將流中的數據存入一個集合。collect方法的參數,是一個collector接口,而且這個接口並不是一個函數式接口,實現這個接口,可以自定義收集的規則。但是,絕大部分情況下,不需要自定義。
直接使用Collectors工具類提供的方法即可。

public class FinalOperation {
    public static void main(String[] args) {
        collectUsage();
    }

    //最終操作:collect將流中的數據整合起來,最常見的處理是:讀取流中的數據,整合到一個容器中,得到一個集合。
    public static void collectUsage(){
        //1.讀取數據源
        Stream<Integer> dataSource = getDataSource();
        //2.流中的數據的聚合
        //List<Integer> list = dataSource.collect(Collectors.toList());
        //System.out.println(list);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        //Set<Integer> set = dataSource.collect(Collectors.toSet());
        //System.out.println(set);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        //Map<String, Integer> map = dataSource.collect(Collectors.toMap(i -> i.toString(), i -> i));//i.toString作為鍵 i作為值
        Map<String, Integer> map = dataSource.collect(Collectors.toMap(Object::toString, i -> i));//i.toString作為鍵 i作為值
        System.out.println(map);//{0=0, 1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9}
    }

    //數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象)
    public static Stream<Integer> getDataSource(){
        //1.准備一個容器
        List<Integer> dataSource = new ArrayList<>();
        //2.向數據源中添加數據
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //3.讀取數據源中的數據,得到Stream對象
        return dataSource.stream();
    }
}
View Code

2. reduce

將流中的數據按照一定的規則聚合起來。將流的元素,逐一帶入這個方法中,進行運算。最終的運算結果,得到的其實是一個Optional類型,需要使用get()獲取到里面的數據

public class FinalOperation {
    public static void main(String[] args) {
        reduceUsage();
    }

    public static void reduceUsage(){
        //1.讀取數據源,得到流對象
        Stream<Integer> dataSource = getDataSource();
        //2.最終操作 (這里有兩個參數,實現了從0到9的和的求值 即p1=0 p2=1 和的結果為1作為p1 再跟p2=2相加,以此類推)
        Integer num = dataSource.reduce((p1, p2) -> p1 + p2).get();
        //Integer num = dataSource.reduce(Integer::sum).get();
        //3.輸出
        System.out.println(num);//45
    }

    //數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象)
    public static Stream<Integer> getDataSource(){
        //1.准備一個容器
        List<Integer> dataSource = new ArrayList<>();
        //2.向數據源中添加數據
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //3.讀取數據源中的數據,得到Stream對象
        return dataSource.stream();
    }
}
View Code

3. count

統計流中的元素數量

public class FinalOperation {
    public static void main(String[] args) {
        countUsage();
    }

    public static void countUsage(){
        //1.讀取數據源,得到流對象
        Stream<Integer> dataSource = getDataSource();
        //2.最終操作 獲取元素數量
        Long num = dataSource.count();
        //3.輸出
        System.out.println(num);//10
    }

    //數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象)
    public static Stream<Integer> getDataSource(){
        //1.准備一個容器
        List<Integer> dataSource = new ArrayList<>();
        //2.向數據源中添加數據
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //3.讀取數據源中的數據,得到Stream對象
        return dataSource.stream();
    }
}
View Code

4. forEach

迭代、遍歷流中的數據

public class FinalOperation {
    public static void main(String[] args) {
        forEachUsage();
    }

    public static void forEachUsage(){
        //1.讀取數據源,得到流對象
        Stream<Integer> dataSource = getDataSource();
        //2.最終操作 遍歷流中的數據 輸出
        dataSource.forEach(System.out::print);//0123456789
    }

    //數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象)
    public static Stream<Integer> getDataSource(){
        //1.准備一個容器
        List<Integer> dataSource = new ArrayList<>();
        //2.向數據源中添加數據
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //3.讀取數據源中的數據,得到Stream對象
        return dataSource.stream();
    }
}
View Code

5. max&min

獲取流中的最大/最小元素

public class FinalOperation {
    public static void main(String[] args) {
        maxAndMinUsage();
    }

    //按照執行的對象比較的規則去進行大小的比較,然后得出流中最大、最小的數據
    public static void maxAndMinUsage(){
        //1.讀取數據源,得到流對象
        Stream<Integer> dataSource = getDataSource();
        //2.最終操作 獲取流中的最大、最小值
        //Integer max = dataSource.max(Integer::compareTo).get();
        //System.out.println(max);//9
        Integer min = dataSource.min(Integer::compareTo).get();
        System.out.println(min);//0
    }

    //數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象)
    public static Stream<Integer> getDataSource(){
        //1.准備一個容器
        List<Integer> dataSource = new ArrayList<>();
        //2.向數據源中添加數據
        Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //3.讀取數據源中的數據,得到Stream對象
        return dataSource.stream();
    }
}
View Code

6. Matching

allMatch:只有當流中所有的元素,都匹配指定的規則,才會返回true
anyMatch:只要流中有任意的數據,滿足指定的規則,都會返回true
noneMatch:只有當流中所有的元素,都不滿足指定的規則,才會返回true

public static void main(String[] args) {
    matchingUsage();
}

public static void matchingUsage(){
    //1.讀取數據源,獲取Stream對象
    Stream<Integer> dataSource = getDataSource();
    //2.匹配的操作
    //boolean b = dataSource.allMatch(e -> e>0);
    //System.out.println(b);//false 因為不是集合中所有的元素都大於0 還有一個等於0
    //boolean b = dataSource.anyMatch(e -> e >= 9);
    //System.out.println(b);//true
    boolean b = dataSource.noneMatch(e -> e > 9);
    System.out.println(b);//true
}

//數據源的獲取,從一個容器中獲取數據源中的數據(得到一個Stream對象)
public static Stream<Integer> getDataSource(){
    //1.准備一個容器
    List<Integer> dataSource = new ArrayList<>();
    //2.向數據源中添加數據
    Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    //3.讀取數據源中的數據,得到Stream對象
    return dataSource.stream();
}
View Code

7. find

findFirst:從流中獲取一個元素(是獲取的開頭元素)
findAny:從流中獲取一個元素(一般情況下,是獲取的開頭的元素)
這兩個方法,絕大部分情況下,是完全相同的,但是在多線程環境下,返回結果可能不一樣

public static void main(String[] args) {
    findUsage();
}

public static void findUsage(){
    //1.實例化一個集合
    ArrayList<Integer> dataSource = new ArrayList<>();
    Collections.addAll(dataSource, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    //2.findFirst演示
    //Integer integer = dataSource.stream().findFirst().get();//串行流
    //Integer integer = dataSource.parallelStream().findFirst().get();//並行流
    //System.out.println(integer);//串行流或者是並行流結果都是0
    //3.findAny演示
    //Integer integer = dataSource.stream().findAny().get();//串行流
    Integer integer = dataSource.parallelStream().findAny().get();//並行流
    System.out.println(integer);//串行流是0、並行流結果為6  即不一定是0
}
View Code

8. IntStream

主要可以實現獲取流中int類型數據的最大值、最小值、平均值、和、數量
還可以獲取到一個對流中數據的分析結果(即一次獲取所有類型的值)

public static void main(String[] args) {
    intStreamUsage();
}

public static void intStreamUsage(){
    //1.准備一個int數組作為數據源
    int[] array = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    //2.讀取數據到流中,獲取IntStream對象
    IntStream stream = Arrays.stream(array);
    //3.輸出
    //System.out.println(stream.max().getAsInt());//獲取最大值     9
    //System.out.println(stream.min().getAsInt());//獲取最小值     0
    //System.out.println(stream.sum());//獲取和      45
    //System.out.println(stream.count());//獲取流中數據個數   10
    //System.out.println(stream.average().getAsDouble());//獲取流中數據的平均值   4.5
    //4.獲取到一個對流中數據的分析結果(即一次獲取所有類型的值)
    IntSummaryStatistics intSummaryStatistics = stream.summaryStatistics();
    System.out.println("最大值:"+intSummaryStatistics.getMax()+" 最小值:"+intSummaryStatistics.getMin());//最大值:9 最小值:0
    System.out.println("平均值:"+intSummaryStatistics.getAverage()+" 和:"+intSummaryStatistics.getSum());//平均值:4.5 和:45
    System.out.println("數量:"+intSummaryStatistics.getCount());//數量:10
}
View Code

四、中間操作

將數據從數據源中讀取到流中,就是對流中的數據進行各種各樣的操作、處理。中間操作可以連續操作,每一個操作的返回值都是一個Stream對象,可以繼續進行其他的操作,直到最終操作。

中間操作主要分為:filter、distinct、sorted、limit&skip、map&flatMap、Collections工具類

1. filter

條件過濾,僅保留流中滿足指定條件的數據,其他不滿足的數據都會被刪除。

//學生類:存儲於集合中的數據類型
private static class Student{
    private String name;
    private int age;
    private int score;

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    //這里省略getter、setter、toString方法
}

public static void main(String[] args) {
    filterUsage();
}

public static void filterUsage(){
    //1. 獲取數據源
    Stream<Student> dataSource = getDataSource();
    //2. 過濾掉集合中成績不合格的學生信息
    dataSource.filter(s -> s.getScore()>=60).forEach(System.out::println);
    //Student{name='xiaoming', age=18, score=100}
    //Student{name='xiaoming', age=19, score=90}
    //Student{name='xiaoming', age=20, score=80}
    //Student{name='xiaoming', age=21, score=70}
    //Student{name='xiaoming', age=22, score=60}
}

//讀取數據源,將集合中存儲的數據,讀取到數據源中
public static Stream<Student> getDataSource(){
    //1.實例化一個集合,存Student對象
    ArrayList<Student> arrayList = new ArrayList<>();
    //2.添加若干數據
    Collections.addAll(arrayList,
                       new Student("xiaoming",18,100),
                       new Student("xiaoming",19,90),
                       new Student("xiaoming",20,80),
                       new Student("xiaoming",21,70),
                       new Student("xiaoming",22,60),
                       new Student("xiaoming",23,50),
                       new Student("xiaoming",24,40)
                      );
    //3.讀取數據源,得到Stream對象
    return arrayList.stream();
}
View Code

2. distinct

去除集合中重復的元素,這個方法沒有參數,去重的規則與HashSet相同。
 (1)比較兩個對象的hashcode
 (2)使用equals再來對比一下
這里要注意:實體類中需要重寫hashcode和equals方法,否則去重可能不會生效

//學生類:存儲於集合中的數據類型
private static class Student{
    private String name;
    private int age;
    private int score;

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    //這里省略getter、setter、toString、hashcode、equals方法
}

public static void main(String[] args) {
    distinctUsage();
}


public static void distinctUsage(){
    //1. 獲取數據源
    Stream<Student> dataSource = getDataSource();
    //2. 去重 要注意實體類Student中需要重寫equals和hashCode方法,否則去重不會生效
    dataSource.distinct().forEach(System.out::println);
    //Student{name='xiaoming1', age=18, score=100}
    //Student{name='xiaoming2', age=20, score=80}
    //Student{name='xiaoming3', age=21, score=70}
    //Student{name='xiaoming4', age=22, score=60}
    //Student{name='xiaoming5', age=23, score=50}
    //Student{name='xiaoming6', age=24, score=40}

}

//讀取數據源,將集合中存儲的數據,讀取到數據源中
public static Stream<Student> getDataSource(){
    //1.實例化一個集合,存Student對象
    ArrayList<Student> arrayList = new ArrayList<>();
    //2.添加若干數據
    Collections.addAll(arrayList,
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming2",20,80),
                       new Student("xiaoming3",21,70),
                       new Student("xiaoming4",22,60),
                       new Student("xiaoming5",23,50),
                       new Student("xiaoming6",24,40)
                      );
    //3.讀取數據源,得到Stream對象
    return arrayList.stream();
}
View Code

3. sorted

對流中的數據進行排序
 (1)無參:sorted():將流中的數據,按照其對應的類實現的Comparable接口提供的比較規則進行排序
 (2)有參:sorted(Comparator<T> comparator):將流中的數據,按照參數接口提供的比較規則進行排序

private static class Student implements Comparable<Student>{
    private String name;
    private int age;
    private int score;

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    @Override
    public int compareTo(Student o) {
        return score-o.score;
    }
    //這里省略getter、setter、toString、hashcode、equals方法
}

public static void main(String[] args) {
    sortedUsage();
}


public static void sortedUsage(){
    //1. 獲取數據源
    Stream<Student> dataSource = getDataSource();
    //2. 將流中的數據進行排序 (注意實體類要注意實現Comparable接口並重寫compareTo方法,否則會報錯)
    //dataSource.sorted().forEach(System.out::println);
    //Student{name='xiaoming6', age=24, score=40}
    //Student{name='xiaoming5', age=23, score=50}
    //Student{name='xiaoming4', age=22, score=60}
    //Student{name='xiaoming3', age=21, score=70}
    //Student{name='xiaoming2', age=20, score=80}
    //Student{name='xiaoming1', age=18, score=100}
    //Student{name='xiaoming1', age=18, score=100}
    //3. 對流中的數據按照自定義的規則進行排序 (按照年齡升序排列)
    dataSource.sorted((s1,s2)->s1.getAge()-s2.getAge()).forEach(System.out::println);
    //Student{name='xiaoming1', age=18, score=100}
    //Student{name='xiaoming1', age=18, score=100}
    //Student{name='xiaoming2', age=20, score=80}
    //Student{name='xiaoming3', age=21, score=70}
    //Student{name='xiaoming4', age=22, score=60}
    //Student{name='xiaoming5', age=23, score=50}
    //Student{name='xiaoming6', age=24, score=40}
}

//讀取數據源,將集合中存儲的數據,讀取到數據源中
public static Stream<Student> getDataSource(){
    //1.實例化一個集合,存Student對象
    ArrayList<Student> arrayList = new ArrayList<>();
    //2.添加若干數據
    Collections.addAll(arrayList,
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming2",20,80),
                       new Student("xiaoming3",21,70),
                       new Student("xiaoming4",22,60),
                       new Student("xiaoming5",23,50),
                       new Student("xiaoming6",24,40)
                      );
    //3.讀取數據源,得到Stream對象
    return arrayList.stream();
}
View Code

4. limit&skip

limit:限制,截取流中指定數量的元素   skip:跳過流中的指定數量的元素 經常放在一起用

//實體類省略,參考上面即可

public static void main(String[] args) {
     limitAndSkipUsage();
 }


public static void limitAndSkipUsage(){
    //1. 獲取數據源
    Stream<Student> dataSource = getDataSource();
    //2. 獲取成績的前5名
    //        dataSource.distinct()
    //                .sorted((s1,s2)->s2.getScore()-s1.getScore())
    //                .limit(5)
    //                .forEach(System.out::println);
    //3. 獲取成績為3-5名的
    dataSource.distinct()
        .sorted((s1,s2)->s2.getScore()-s1.getScore())
        .limit(5)
        .skip(2)
        .forEach(System.out::println);
}

//讀取數據源,將集合中存儲的數據,讀取到數據源中
public static Stream<Student> getDataSource(){
    //1.實例化一個集合,存Student對象
    ArrayList<Student> arrayList = new ArrayList<>();
    //2.添加若干數據
    Collections.addAll(arrayList,
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming2",20,80),
                       new Student("xiaoming3",21,70),
                       new Student("xiaoming4",22,60),
                       new Student("xiaoming5",23,50),
                       new Student("xiaoming6",24,40)
                      );
    //3.讀取數據源,得到Stream對象
    return arrayList.stream();
}
View Code

5. map&flatMap

對流中的數據進行映射,用新的數據替換舊的數據

map最主要,就是來做元素的替換,其實map是一個元素的映射(將流中每一個元素替換成指定的元素)

flatMap也是元素的映射,flatMap是扁平化映射

扁平化映射:一般用在map映射完成后,流中的數據是一個容器,而我們需要對容器中的數據進行處理 此時使用扁平化映射,可以將流中的容器中的數據,直接讀取到流中

案例1:

public static void main(String[] args) {
    mapUsage();
}


public static void mapUsage(){
    //1. 獲取數據源
    Stream<Student> dataSource = getDataSource();
    //2. 實際需求:獲取所有學生的名字
    //dataSource.map(Student::getName).forEach(System.out::println);
    //dataSource.map(s->s.getName()).forEach(System.out::println);
    //3. 實際需求:獲取所有學生的成績 注意:泛型中不能是基本數據類型,只能是包裝類 即下面的返回值應該為Stream<Integer>
    //dataSource.map(Student::getScore).forEach(System.out::println);
    //4. 實際需求:獲取所有學生的成績
    IntSummaryStatistics intSummaryStatistics = dataSource.mapToInt(Student::getScore).summaryStatistics();
    System.out.println(intSummaryStatistics.getMax());
}

//讀取數據源,將集合中存儲的數據,讀取到數據源中
public static Stream<Student> getDataSource(){
    //1.實例化一個集合,存Student對象
    ArrayList<Student> arrayList = new ArrayList<>();
    //2.添加若干數據
    Collections.addAll(arrayList,
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming1",18,100),
                       new Student("xiaoming2",20,80),
                       new Student("xiaoming3",21,70),
                       new Student("xiaoming4",22,60),
                       new Student("xiaoming5",23,50),
                       new Student("xiaoming6",24,40)
                      );
    //3.讀取數據源,得到Stream對象
    return arrayList.stream();
}
View Code

案例2:

public static void main(String[] args) {
    mapUsage();
}

public static void mapUsage(){
    //1.實例化一個字符串數組
    String[] array = {"hello","world"};
    //2.將字符串數組中的數據讀取到流中
    Stream<String> stream = Arrays.stream(array);
    //3.需求:統計字符串數組中所有出現的字符
    //stream.map(String::toCharArray).forEach(e->System.out.println(Arrays.toString(e)));
    //結果為 [h, e, l, l, o]  [w, o, r, l, d] 兩個數組 不符合我們的要求
    stream.map(s->s.split(""))
        .flatMap(Arrays::stream)
        .distinct()
        .forEach(System.out::println);
    //結果為h e l o w r d
}
View Code

6. Collections工具類

Collectors是一個工具類,里面封裝了很多方法,可以很方便的獲取到一個Collector接口的實現類對象,從而可以使用collect()方法,對流中的數據,進行各種各樣的處理、整合。
常用方法:
 Collectors.toList()  將流中的數據,聚合到一個List集合中
 Collectors.toSet()  將流中的數據,聚合到一個Set集合中
 Collectors.toMap()  將流中的數據,聚合到一個Map集合中
 maxBy()     按照指定的規則,找到流中最大的元素,等同於max
 minBy()     按照指定的規則,找到流中最小的元素,等同於min
 joining()     將流中的數據拼接成一個字符串,注意:只能操作流中是String的數據
 summingInt()    將流中的數據,映射成int類型的數據,並求和
 averagingInt()   將流中的數據,映射成int類型的數據,並求平均值
 summarizingInt()   將流中的數據,映射成int類型的數據,並獲取描述信息

public static void main(String[] args) {
    //1. 准備一個字符串數組,作為數據源
    String[] dataSource = {"nihao","wo","shi","xxx"};
    //2. 讀取數據源中的數據
    Stream<String> stream = Arrays.stream(dataSource);
    //3. joining方法,只適用於 Stream<String> 這種流
    //String collect = stream.collect(Collectors.joining());//拼接
    //System.out.println(collect);//nihaowoshixxx
    //String collect = stream.collect(Collectors.joining(","));//拼接 按照逗號分隔
    //System.out.println(collect);//nihao,wo,shi,xxx
    //tring collect = stream.collect(Collectors.joining(",","[","]"));//拼接 帶前綴、后綴
    //System.out.println(collect);//[nihao,wo,shi,xxx]

    //4. summingInt
    Integer collect = stream.collect(Collectors.summingInt(String::length));
    System.out.println(collect);//13
}
View Code

 

 

持續更新!!!

注意:本篇文章大多數內容來自bilibili網站千鋒教育,地址:https://www.bilibili.com/video/BV1fT4y177ui?p=6  本篇文章僅用於個人學習和總結,如有侵權,聯系刪除!


免責聲明!

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



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