Stream流

概述

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Book {
    //id
    private Long id;
    //书名
    private String name ;
    //分类
    private String category;
    //评分
    private Integer score;
    //简介
    private String intro;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode //用于后期的去重使用
public class Author {
    private Long id;//id
    private String name;//姓名
    private Integer age;//年龄
    private String intro;//简介
    private List<Book> books;//作品
}

测试类

private static List<Author> getAuthors() {
    //数据初始化
    Author author = new Author(1L, "蒙多", 33, "一个从菜刀中明悟哲理的祖安人", null);
    Author author2 = new Author(2L, "亚拉索", 15, "狂风也追逐不上他的思考速度", null);
    Author author3 = new Author(3L, "易", 14, "是这个世界在限制他的思维", null);
    Author author4 = new Author(3L, "易", 14, "是这个世界在限制他的思维", null);
    //书籍列表
    List<Book> books1 = new ArrayList<>();
    List<Book> books2 = new ArrayList<>();
    List<Book> books3 = new ArrayList<>();


    books1.add(new Book(1L, "刀的两侧是光明与黑暗", "哲学,爱情",88,"用一把刀划分了爱恨"));
    books1.add(new Book(2L,"一个人不能死在同一把刀下" , "个人成长,爱情" ,99, "讲述如何从失败中明悟真理"));

    books2.add(new Book(3L, "那风吹不到的地方", "哲学" ,85, "带你用思维去领略世界的尽头"));
    books2.add(new Book(3L, "那风吹不到的地方", "哲学" ,85, "带你用思维去领略世界的尽头"));
    books2.add(new Book(4L,"吹或不吹","爱情,个人传记",56,"一个哲学家的恋爱观注定很难把他所在的时代理解"));

    books3.add(new Book(5L, "你的剑就是我的剑","爱情",56,"无法想象一个武者能对他的伴侣这么的宽容"));
    books3.add(new Book(6L, "风与剑","个人传记",100, "两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
    books3.add(new Book(6L, "风与剑","个人传记",100, "两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
    author.setBooks(books1);
    author2.setBooks(books2);
    author3.setBooks(books3);
    author4.setBooks(books3);

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

问题:去重并打印18岁以下的名字

public static void main(String[] args) {
    List<Author> authors = getAuthors();
    authors.stream()
            .distinct()
            .filter((author -> author.getAge()<18))
            .forEach(author -> System.out.println(author.getName()));
}

创建流

单列集合集合对象.stream()

Stream<Author> stream = list.stream();

数组Arrays.stream(数组) 或者使用Stream.of来创建

Integer[] arr = {1,2,3,4,5};
//方法一
Stream<Integer> stream1 = Arrays.stream(arr);
//方法二
Stream<Integer> stream2 = Stream.of(arr);

双列集合:转换成单列集合在创建

public static void main(String[] args) {
    HashMap<String, Integer> hashMap = new HashMap<>();
    hashMap.put("小明",11);
    hashMap.put("小红",11);
    hashMap.put("小张",12);

    Set<Map.Entry<String, Integer>> entries = hashMap.entrySet();
    Stream<Map.Entry<String, Integer>> stream = entries.stream();
    stream.distinct()
            .filter(entry -> entry.getValue() >11)
            .forEach(System.out::println);
}

在这里插入图片描述

中间操作

filter

可以对流中的元素进行条件过滤,符合过滤条件的才能继续留在流中。

例如:
打印所有姓名长度大于1的作家的姓名

List<Author> authors = getAuthors();

authors.stream()
        .distinct()
        .filter((author -> author.getName().length() > 1))
        .forEach(author -> System.out.println(author.getName()));

map

可以把流中的元素进行计算或转换

例如:

//打印所有作家的姓名
List<Author> authors = getAuthors();

authors.stream()
        .map(author -> {
            author.setName("张三");
            return author;//是将对象的name都改成 张三 但是还是返回的List对象
        })
        .map(author -> author.getName())//但是这里就相当于 将原来传入的List<Author> 变为List<String>
        .forEach(name -> System.out.println(name instanceof String));//将括号中的换成name会全部打印张三

在这里插入图片描述

distinct

可以取出流中的重复元素

List<Author> authors = getAuthors();

authors.stream()
        .distinct()
        .forEach(author -> System.out.println(author.getName()));

结果:
在这里插入图片描述

注意: distinct方法是依赖Object的equals方法来判断是否是相同对象的。所以需要注意重写equals方法。如果不重写就相当于== ,对象就是比较的地址值。

sorted

这个方法有两种形式:
在这里插入图片描述
① 如果调用空参的sorted()方法,需要流中的元素实现Comparable,并且重写compareTo方法

@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode //用于后期的去重使用
public class Author implements Comparable<Author>{
    private Long id;//id
    private String name;//姓名
    private Integer age;//年龄
    private String intro;//简介
    private List<Book> books;//作品


    @Override
    public int compareTo(Author o) {
        return this.getAge() - o.getAge();
    }
}
private static void test03() {
    List<Author> authors = getAuthors();

    authors.stream()
            .distinct()
            .sorted()
            .forEach(author -> System.out.println(author.getAge()));
}

② 带参数的sorted我们用的比较多

private static void test03() {
    List<Author> authors = getAuthors();

    authors.stream()
            .distinct()
            .sorted((o1,o2)->o1.getAge()-o2.getAge())
            .forEach(author -> System.out.println(author.getAge()));
}

结果:
在这里插入图片描述

limit

跟mysql中limit一个意思,一般配合sorted使用

例如:
打印年龄最大的两个作家并且去重

List<Author> authors = getAuthors();

authors.stream()
        .distinct()
        .sorted((o1,o2)->o2.getAge()-o1.getAge())
        .limit(2)
        .forEach(author -> System.out.println(author.getName()));

结果:
在这里插入图片描述

skip

跳过前n个元素

例如:
打印除了年龄最大的作家外的其他作家,要求不能有重复元素,并且按照年龄降序排序。

private static void test04() {
    List<Author> authors = getAuthors();

    authors.stream()
            .distinct()
            .sorted((o1,o2)->o2.getAge()-o1.getAge())
            .skip(1)
            .forEach(author -> System.out.println(author.getName()));
}

结果:
在这里插入图片描述

flatMap

map只能把一个对象转换成另一个对象来作为流中的元素。而flatMap可以把一个对象转换成多个对象作为流中的元素。

例如:
打印所有书籍的名字。要求对重复的元素进行去重

List<Author> authors = getAuthors();

authors.stream()
        .flatMap(author -> author.getBooks().stream())
        .distinct()
        .forEach(book -> System.out.println(book.getName()));

结果:
在这里插入图片描述

//打印现有数据的所有分类。要求对分类进行去重。不能出现这种格式:哲学,爱情
List<Author> authors = getAuthors();

authors.stream()
        .flatMap(author -> author.getBooks().stream())
        .distinct()
        .flatMap(book -> Arrays.stream(book.getCategory().split(",")))
        .distinct()
        .forEach(category -> System.out.println(category));

结果:
在这里插入图片描述
map和flatmap 的区别

map:map方法返回的是一个object,map将流中的当前元素替换为此返回值;
flatMap:flatMap方法返回的是一个stream,flatMap将流中的当前元素替换为此返回流拆解的流元素;

网上有一个比较经典的例子
有二箱鸡蛋,每箱5个,现在要把鸡蛋加工成煎蛋,然后分给学生。
map做的事情:把二箱鸡蛋分别加工成煎蛋,还是放成原来的两箱,分给2组学生;
flatMap做的事情:把二箱鸡蛋分别加工成煎蛋,然后放到一起【10个煎蛋】,分给10个学生;

说白了map 只是改变了原来流中元素的类型(即我们的返回值),而flatmap 是将原来流中的每个值都换成另一个流,然后把所有流连接成一个新的流,这是我的理解

终结操作

forEach

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

例如:
输出所有的作家的名字

List<Author> authors = getAuthors();

authors.stream()
        .map(author -> author.getName())
        .distinct()
        .forEach(name -> System.out.println(name));

count

获取流中元素的个数

例如:
打印这些作家的所出书籍的数目,注意删除重复元素。

List<Author> authors = getAuthors();

long count = authors.stream()
        .flatMap(author -> author.getBooks().stream())
        .distinct()
        .count();
System.out.println(count);

max&min

求流中的最大最小值

例如:
分别获取这些作家的所出书籍的最高分和最低分并打印。

List<Author> authors = getAuthors();

Optional<Integer> maxScore = authors.stream()
        .flatMap(author -> author.getBooks().stream())
        .map(score -> score.getScore())
        .max((o1, o2) -> o1 - o2);//这里要实现Comparator的因为他不知道我们最大最小的规则是什么

System.out.println(maxScore.get());

collect

把当前流转换成一个集合

获取一个存放所有作者名字的List集合。
获取一个所有书名的set集合。
获取一个Map集合,map的key为作者名,value为List

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值