Stream流

 数据准备

创建实体类Author

package com.zsh.stream.domain.po;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode// 用于后期的去重使用
public class Author {

    // id
    private Long id;

    // 姓名
    private String name;

    // 年龄
    private Integer age;

    // 简介
    private String intro;

    // 作品
    private List books;
}

创建实体类Book

package com.zsh.stream.domain.po;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode// 用于后期的去重使用
public class Book {

    // id
    private Long id;

    // 书名
    private String name;

    // 分类
    private String category;

    // 评分
    private Integer score;

    // 简介
    private String Intro;

}

创建测试类

package com.zsh.stream.demo;

import com.zsh.stream.domain.po.Author;
import com.zsh.stream.domain.po.Book;

import java.util.*;
import java.util.stream.Stream;

public class StreamDemo {

    /**
     * 数据准备
     * @return
     */
    private static List getAuthors() {
        // 数据初始化
        Author author1 = new Author(1L, "开朗觉觉", 16, "30年超级Java开发工程师", null);
        Author author2 = new Author(1L, "开朗觉觉", 16, "30年超级Java开发工程师", null);
        Author author3 = new Author(3L, "小美", 17, "10年超级Java开发工程师", null);
        Author author4 = new Author(4L, "觉觉", 19, "5年超级Java开发工程师", null);

        // 书籍列表
        ArrayList books1 = new ArrayList<>();
        ArrayList books2 = new ArrayList<>();
        ArrayList books3 = new ArrayList<>();

        books1.add(new Book(1L,"晨岛快速跑图攻略1","哲学",88,"123123"));
        books1.add(new Book(2L,"晨岛快速跑图攻略2","哲学",88,"123123"));
        books1.add(new Book(3L,"晨岛快速跑图攻略2","哲学",88,"123123"));

        books2.add(new Book(1L,"晨岛快速跑图攻略1","哲学",88,"123123"));
        books2.add(new Book(2L,"晨岛快速跑图攻略2","哲学",88,"123123"));
        books2.add(new Book(3L,"晨岛快速跑图攻略2","哲学",88,"123123"));

        books3.add(new Book(7L,"晨岛快速跑图攻略3","哲学",88,"123123"));
        books3.add(new Book(8L,"晨岛快速跑图攻略3","哲学",88,"123123"));
        books3.add(new Book(9L,"晨岛快速跑图攻略3","哲学",88,"123123"));

        author1.setBooks(books1);
        author2.setBooks(books2);
        author3.setBooks(books3);
        author4.setBooks(books3);


        ArrayList authorList = new ArrayList<>(Arrays.asList(author1,author2,author3,author4));
        return authorList;
    }

}

入门测试

打印年龄小于18的作家名字,并且去重

public class StreamDemo {
    public static void main(String[] args) {
        // 打印年龄小于18的作家名字,并且去重
        test1();

    }

    /**
     * 打印年龄小于18的作家名字,并且去重
     */
    private static void test1() {
        // 数据准备
        List authors = getAuthors();

        // 打印年龄小于18的作家名字,并且去重
        authors.stream()    // 把集合转换成流
                // 去重
                .distinct()
                // 筛选
                .filter(author -> author.getAge() < 18)
                // 打印
                .forEach(author -> System.out.println(author.getName()));
    }


}

单列集合创建流(重要)

public class StreamDemo {
    public static void main(String[] args) {
        // 单列集合创建流(重要)
        test2();
    }

    /**
     * 单列集合创建流
     */
    private static void test2() {
        // 数据准备
        List authors = getAuthors();

        // 单列集合创建流
        Stream stream = authors.stream();
    }


}

数组创建流

public class StreamDemo {
    public static void main(String[] args) {
        // 数组创建流(方式1)
        test3();

        // 数组创建流(方式2)
        test4();
    }

    /**
     * 数组创建流(方式2)
     */
    private static void test4() {
        // 创建数组
        Integer[] numArr = {1,2,3,4,5};

        // 数组创建流
        Stream stream = Stream.of(numArr);

        // 输出
        stream.filter(integer -> integer > 2)
                .forEach(integer -> System.out.println(integer));
    }

    /**
     * 数组创建流(方式1)
     */
    private static void test3() {
        // 创建数组
        Integer[] numArr = {1,2,3,4,5};

        // 数组创建流
        Stream stream = Arrays.stream(numArr);

        // 输出
        stream.filter(integer -> integer % 2 == 0)
                .forEach(integer -> System.out.println(integer));
    }


}

Map创建流

public class StreamDemo {
    public static void main(String[] args) {
        // Map创建流
        test5();
    }

    /**
     * Map创建流
     */
    private static void test5() {
        HashMap map = new HashMap<>();
        map.put("开朗觉觉",16);
        map.put("开朗莽莽",17);
        map.put("酪小美",18);

        // 将Map集合转换为Set集合 (Map集合是不能直接转换为Stream流的,所以要先转成Set集合)
        Set> entrySet = map.entrySet();

        // 创建Stream流
        Stream> stream = entrySet.stream();

        // 输出
        stream.filter(item -> item.getValue() == 18)
                .forEach(item -> System.out.println(item.getKey() + "," + item.getValue() + "岁"));
    }


}

中间操作常用方法

filter() 根据条件进行过滤

public class StreamCenter {
    public static void main(String[] args) {
        // filter() 打印所有名字长度大于2的作家姓名
        test1();
    }

    /**
     * filter() 打印所有名字长度大于2的作家姓名
     */
    private static void test1() {
        // 数据准备
        List authors = getAuthors();

        // 获取流并打印
        authors.stream()
                .distinct()
                .filter(author -> author.getName().length() > 2)
                .forEach(author -> System.out.println(author.getName()));
    }


}

map() 将流中的元素进行转换

public class StreamCenter {
    public static void main(String[] args) {
        // map() 将流中的元素进行转换
        test2();
    }

    /**
     * map() 将流中的元素进行转换
     */
    private static void test2() {
        // 数据准备
        List authors = getAuthors();

        // 创建流并输出
        authors.stream()
                .map(author -> author.getName())
                .forEach(name -> System.out.println(name));
    }


}

map() 将流中元素进行计算

public class StreamCenter {
    public static void main(String[] args) {
        // map() 将流中元素进行计算
        test3();

    }

    /**
     * map() 将流中元素进行计算
     */
    private static void test3() {
        // 数据准备
        List authors = getAuthors();
        // 创建流并输出
        authors.stream()
                .map(author -> author.getAge())
                .map(age -> age + 10)
                .forEach(System.out::println);
    }


}

mapToInt() 获取到的值为Int

将返回类型改为Int,后续进行数据操作可以避免拆箱装箱,增加效率

private static void test10() {
    List authors = getAuthors();
    authors.stream()
        // 将值的返回类型改为Int,后续进行数据操作可以避免拆箱装箱,增加效率
        .mapToInt(author -> author.getAge())
        .map(age -> age + 10)
        .filter(age -> age > 18)
        .map(age -> age + 2)
        .forEach(System.out::println);
}

flatMapToInt() 类型转换

与mapToInt()类似,参照mapToInt();

flatMapToDouble类型转换

与mapToInt()类似,参照mapToInt();

distinct() 去除重复元素

注意:distinct方法是依赖Object的equals方法来判断是否是相同对象的。所以注意重写equals方法;

public class StreamCenter {
    public static void main(String[] args) {
        // distinct() 去除重复元素 (distinct方法是依赖Object的equals方法来判断是否是相同对象的。所以注意重写equals方法)
        test4();
    }

    /**
     * distinct() 去除重复元素 (distinct方法是依赖Object的equals方法来判断是否是相同对象的。所以注意重写equals方法)
     */
    private static void test4() {
        // 数据准备
        List authors = getAuthors();

        // 创建流并输出
        authors.stream()
                .distinct()
                .forEach(author -> System.out.println(author.getName()));
    }


}

sorted() 对流中的元素进行排序

注意:如果调用空参的sorted方法,需要流中的元素是实现了Comparable;

public class StreamCenter {
    public static void main(String[] args) {
        // sorted() 对流中的元素按年龄进行排序 (注意如果调用空参的sorted方法,需要流中的元素是实现了Comparable)
        test5();
    }

    /**
     * sorted() 对流中的元素按年龄进行排序
     */
    private static void test5() {
        // 数据准备
        List authors = getAuthors();

        // 创建流并输出
        authors.stream()
                .sorted((o1, o2) -> o1.getAge() - o2.getAge())
                .forEach(author -> System.out.println(author.getName() + "," + author.getAge()));
    }


}

limit() 设置流的最大长度

注意:超出的部将被抛弃;

public class StreamCenter {
    public static void main(String[] args) {
        // limit() 对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素,然后打印其中两个年龄最大的作家
        test6();
    }

    /**
     * limit() 对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素,然后打印其中两个年龄最大的作家
     */
    private static void test6() {
        // 数据准备
        List authors = getAuthors();

        // 创建流并输出
        authors.stream()
                .distinct()
                .sorted((o1, o2) -> o2.getAge() - o1.getAge())
                .limit(2)
                .forEach(author -> System.out.println(author.getName() + "," + author.getAge()));
    }


}

skip() 跳过流中的几个元素

public class StreamCenter {
    public static void main(String[] args) {
        // skip() 跳过流中的几个元素
        test7();
    }

    // skip() 跳过流中的几个元素
    private static void test7() {
        // 数据准备
        List authors = getAuthors();

        // 创建流并输出
        authors.stream()
                .skip(1)
                .forEach(author -> System.out.println(author.getName()));
    }


}

flatMap() 将流中元素的多个对象作为流中的元素

public class StreamCenter {
    public static void main(String[] args) {
        // flatMap() 将流中元素的多个对象作为流中的元素
        test8();

    }

    /**
     * flatMap() 将流中元素的多个对象作为流中的元素
     */
    private static void test8() {
        // 数据准备
        List authors = getAuthors();

        // 创建流并输出
        authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .forEach(book -> System.out.println(book.getName()));
    }


}

打印现有数据的所有分类,要求去重,不能出现连着的分类:哲学,爱情

public class StreamCenter {
    public static void main(String[] args) {
        // 打印现有数据的所有分类,要求去重,不能出现连着的分类:哲学,爱情
        test9();
    }

    /**
     * 打印现有数据的所有分类,要求去重,不能出现连着的分类:哲学,爱情
     */
    private static void test9() {
        // 数据准备
        List authors = getAuthors();

        // 创建流并输出
        authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .flatMap(book -> Arrays.stream(book.getCategory().split(",")))
                .distinct()
                .forEach(category -> System.out.println(category));
    }


}

parallel() 并行流

parallel() 将串行的流改为并行的流,多线程操作

private static void test11() {
    // parallel() 将串行的流改为并行的流,多线程操作
    List authors = getAuthors();
    authors.stream()
            .parallel()
            .map(author -> author.getName())
            .forEach(name -> System.out.println(name + "  " + Thread.currentThread().getName()));
}

parallelStream() 直接的并行流对象

parallelStream() 直接的并行流对象,将串行的流改为并行的流,多线程操作

private static void test12() {
    // parallelStream() 直接的并行流对象,将串行的流改为并行的流,多线程操作
    List authors = getAuthors();
    authors.parallelStream()
            .map(author -> author.getName())
            .forEach(name -> System.out.println(name + "  " + Thread.currentThread().getName()));
}

终结操作

forEach() 对流中的元素进行遍历操作

对流中的元素进行遍历操作,通过传入传入的参数去指定对遍历的元素进行什么具体操作;

private static void test01(List authors) {
    // 打印所有作家的名字,注意删除重复元素
    authors.stream()
            // 将流中的元素进行转换,并返回
            .map(author -> author.getName())
            // 去重
            .distinct()
            // 遍历流中的元素
            .forEach(System.out::println);
}

count() 获取当前流中元素的个数

private static void test02(List authors) {
    // 打印作家所出的书籍的数目,注意删除重复元素
    long count = authors.stream()
            .flatMap(author -> author.getBooks().stream())
            .distinct()
            .count();
    // 输出
    System.out.println(count);
}

max()&min() 获取流中最大值-最小值

private static void test03(List authors) {
    // 获取这些作家分数最高和最低的书籍
    Optional max = authors.stream()
            .flatMap(author -> author.getBooks().stream())
            .map(book -> book.getScore())
            .max((score1, score2) -> score1 - score2);
    System.out.println("最大值:" + max.get());

    Optional min = authors.stream()
            .flatMap(author -> author.getBooks().stream())
            .map(book -> book.getScore())
            .min((score1, score2) -> score1 - score2);
    System.out.println("最小值:" + min.get());
}

collect() 把当前流转换成一个集合(重点)

List集合

private static void test04(List authors) {
    // 获取一个存放所有作者名字的List集合
    List nameList = authors.stream()
            .map(author -> author.getName())
            .collect(Collectors.toList());
    System.out.println(nameList);
}

set集合

private static void test05(List authors) {
    // 获取一个所有书名的Set集合
    Set bookNameSet = authors.stream()
            .flatMap(author -> author.getBooks().stream())
            .map(book -> book.getName())
            .collect(Collectors.toSet());
    System.out.println(bookNameSet);
}

map集合

注意map集合的key值不能重复

private static void test06(List authors) {
    // 获取一个map集合,key是作者名,value是书名的list集合
    Map> nameAndBookNameMap = authors.stream()
            .distinct()
            .collect(Collectors.toMap(author -> author.getName(), author -> author.getBooks()));
}

anyMatch() 判断是否有任意符合匹配条件的元素,结果为boolean类型

anyMatch() 和filter()的区别:

filter():根据条件过滤流中的元素,符合条件的继续往下走

anyMatch():根据条件判断,是否有符合条件的元素,有则返回true,没有返回false

private static void test07(List authors) {
    // 判断是否有年龄在29以上的作家
    boolean okAndNo = authors.stream()
            .anyMatch(author -> author.getAge() > 29);
    System.out.println(okAndNo);
}

allMatch() 判断是否全部都符合条件,结果为boolean类型

private static void test08(List authors) {
    // 判断作家是否都是成年人
    boolean okAndNo = authors.stream()
            .allMatch(author -> author.getAge() >= 18);
    System.out.println(okAndNo);
}

noneMatch() 判断流中的元素是否都不符合匹配条件,如果都不符合结果为true,否则为false

private static void test09(List authors) {
    // 判断作家是否都没超过100岁
    boolean okAndNo = authors.stream()
            .noneMatch(author -> author.getAge() > 100);
    System.out.println(okAndNo);
}

findAny() 取出流中的任意一个元素

private static void test10(List authors) {
    // 获取任意一个年龄大于18的作家,如果存在就输出名字
    Optional authorOptional = authors.stream()
            .filter(author -> author.getAge() > 18)
            .findAny();
    authorOptional.ifPresent(author -> System.out.println(author.getName()));
}

findFirst() 获取流中第一个元素

private static void test11(List authors) {
    // 获取一个年龄最小的作家,并输出他的名字
    Optional minAge = authors.stream()
            .sorted((o1, o2) -> o1.getAge() - o2.getAge())
            .findFirst();
    minAge.ifPresent(author -> System.out.println(author.getName()));
}

reduce() 对流中的数据按照你指定的计算方式计算出一个结果

reduce两个参数的重载形式内部的计算方式如下:

T result = identity;
for (T element : this stream) {
    result = accumulator.apply(result,element)
}
return result;

求所有作家的年龄和

public class StreamEnd {
    public static void main(String[] args) {
        // reduce() 对流中的数据按照你指定的计算方式计算出一个结果
        // 求所有作家的年龄和
//        test12(authors);
    }

    /**
     * reduce() 对流中的数据按照你指定的计算方式计算出一个结果
     * @param authors
     */
    private static void test12(List authors) {
        // 求所有作家的年龄和
        Integer avgSum = authors.stream()
                .map(author -> author.getAge())
                .reduce(0, (result, element) -> result + element);
        System.out.println(avgSum);
    }


}

求所有作家中年龄最大的值

public class StreamEnd {
    public static void main(String[] args) {
        // 求所有作家中年龄最大的值
        test13(authors);
    }

    /**
     * reduce() 对流中的数据按照你指定的计算方式计算出一个结果
     * @param authors
     */
    private static void test13(List authors) {
        // 求所有作家中年龄最大的值
        Integer ageMax = authors.stream()
                .map(author -> author.getAge())
                .reduce(Integer.MIN_VALUE, (result, element) -> result < element ? element : result);
        System.out.println(ageMax);
    }


}

求作家中年龄的最小值

public class StreamEnd {
    public static void main(String[] args) {
        // 求所有作家中年龄最大的值
		test14(authors);
    }

    /**
     * reduce() 对流中的数据按照你指定的计算方式计算出一个结果
     * @param authors
     */
    private static void test14(List authors) {
        // 求作家中年龄的最小值
        Integer ageMin = authors.stream()
                .map(author -> author.getAge())
                .reduce(Integer.MAX_VALUE, (result, element) -> result < element ? result : element);
        System.out.println(ageMin);
    }


}

reduce一个参数的重载形式内部的计算

这个就相当于是把第一个元素值当成默认值来用(要注意,不要为为出现空值)

boolean foundAny = false;
T result = null;
for (T element : this stream) {
    if (!foundAny) {
        foundAny = true;
        result = element;
    } else {
        result = accumulator.apply(result,element);
    }
}
return foundAny ? Optional.of(result) : Optional.empty();

用一个参数的reduce求作家中年龄的最小值

public class StreamEnd {
    public static void main(String[] args) {
        // 用一个参数的reduce求作家中年龄的最小值
        test15(authors);
    }

    /**
     * reduce() 对流中的数据按照你指定的计算方式计算出一个结果
     * @param authors
     */
    private static void test15(List authors) {
        // 用一个参数的reduce求作家中年龄的最小值
        Optional authorsOptional = authors.stream()
                .map(author -> author.getAge())
                .reduce((result, element) -> result > element ? element : result);
        authorsOptional.ifPresent(age -> System.out.println(age));
    }


}

注意事项

1、惰性求值(如果没有终结操作,没有中间操作时不会得到执行的)

2、流是一次性的(一旦一个流对象经过一个终结操作后。这个流就不能再被使用)

3、不会影响原数据(我们在流中可以多数据做很多处理。但是正常情况下,不会影响原来集合中的元素的。这往往也是我们期待的)

以下是非正常操作(会影响原数据)

authors.stream()
		.map(author -> {
		    author.setAge(author.getAge() + 10);
		    return author;
		})
		.forEach(list -> System.out.println(list));
System.out.println(authors);

你可能感兴趣的:(java,spring,boot,spring,cloud)