IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 系列学习 Lambda 表达式之第 2 篇 —— JDK1.8 的 Stream 流基本使用 -> 正文阅读

[Java知识库]系列学习 Lambda 表达式之第 2 篇 —— JDK1.8 的 Stream 流基本使用

?查看之前的博客可以点击顶部的【分类专栏】

什么是 Stream?

Stream 是 JDK1.8 中处理集合的关键抽象概念。Lambda 和 Stream 是 JDK1.8 新增的函数式编程最优亮点的特性。它可以对集合进行查找、过滤、排序和映射数据等操作。类似于使用 SQL 执行数据库查询语句一样。Stream API 可以让程序员写出高效率、干净、简洁的代码。

说明:使用终止操作的关键字,是不允许再使用中间操作的关键字了。也就是说,如果使用了 forEach、collect、min、max等终止操作,则不能在后面使用 filter 等中间操作了。

?Stream 流有串行流 stream() 和并行流 parallelStream() 之分。并行流表示多线程的,效率高一点。

使用 Stream 流将List 转成 Set 集合

public class Test2 {

    public static void main(String[] args) {
        List<UserInfo> list = new ArrayList<>();
        list.add(new UserInfo("张三",13));
        list.add(new UserInfo("李四",14));
        list.add(new UserInfo("王五",15));
        list.add(new UserInfo("朱六",16));
        list.add(new UserInfo("朱六",16));

        //并行流,效率高一点
        //list.parallelStream();

        //创建一个串行流
        Stream<UserInfo> stream = list.stream();
        //转换成 Set 集合
        Set<UserInfo> set = stream.collect(Collectors.toSet());
        set.forEach(p ->{
            System.out.println(p.toString());
        });

    }

    static class UserInfo {
        private String userName;
        private Integer age;

        public UserInfo(String userName, Integer age) {
            this.userName = userName;
            this.age = age;
        }

        @Override
        public String toString() {
            return "UserInfo{" +
                    "userName='" + userName + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

}

我们现在把 List 转成 Set 集合,在JDK1.8 之前,我们需要 for 循环,然后一个个的放入 Set 集合里。现在不需要了。直接以下使用方法即可:

        Stream<UserInfo> stream = list.stream();
        Set<UserInfo> set = stream.collect(Collectors.toSet());
        set.forEach(p ->{
            System.out.println(p.toString());
        });

输出(注意两个朱六,因为是使用 new 的方式创建,它们的地址引用是不同的,因此是2个对象,hashCode 不一样):

UserInfo{userName='李四', age=14}
UserInfo{userName='王五', age=15}
UserInfo{userName='朱六', age=16}
UserInfo{userName='张三', age=13}
UserInfo{userName='朱六', age=16}

我们重写? UserInfo 实体的 equals 和 hashCode 方法:(IDEA 下按 Alt+INSERT,调出快捷键)

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            UserInfo userInfo = (UserInfo) o;
            return Objects.equals(userName, userInfo.userName) &&
                    Objects.equals(age, userInfo.age);
        }

        @Override
        public int hashCode() {
            return Objects.hash(userName, age);
        }

然后重新运行,输出:

UserInfo{userName='朱六', age=16}
UserInfo{userName='张三', age=13}
UserInfo{userName='李四', age=14}
UserInfo{userName='王五', age=15}

使用 Stream 流将 List 集合转换成 Map

public class Test3 {

    public static void main(String[] args) {
        List<UserInfo> list = new ArrayList<>();
        list.add(new UserInfo("张三", 13));
        list.add(new UserInfo("李四", 14));
        list.add(new UserInfo("王五", 15));
        list.add(new UserInfo("朱六", 16));

        //创建 Stream 流
        Stream<UserInfo> stream = list.stream();
        //转成 Map 集合,其中 key 为用户名,value 为实体
        Map<String, UserInfo> map = stream.collect(Collectors.toMap(info -> info.getUserName(), info -> info));
        map.forEach((BiConsumer) (p1, p2) -> {
            System.out.println("key=" + p1 + ",value=" + p2);
        });

    }

    static class UserInfo {
        private String userName;
        private Integer age;

        public UserInfo(String userName, Integer age) {
            this.userName = userName;
            this.age = age;
        }

        @Override
        public String toString() {
            return "UserInfo{" +
                    "userName='" + userName + '\'' +
                    ", age=" + age +
                    '}';
        }

        public String getUserName() {
            return userName;
        }
    }
}

输出:

key=朱六,value=UserInfo{userName='朱六', age=16}
key=李四,value=UserInfo{userName='李四', age=14}
key=张三,value=UserInfo{userName='张三', age=13}
key=王五,value=UserInfo{userName='王五', age=15}

使用 Stream 流查询最大、最小的元素

public class Test4 {
    public static void main(String[] args) {
        List<UserInfo> list = new ArrayList<>();
        list.add(new UserInfo("张三", 13));
        list.add(new UserInfo("李四", 14));
        list.add(new UserInfo("王五", 15));
        list.add(new UserInfo("朱六", 16));

        //创建 Stream 流
        Stream<UserInfo> stream = list.stream();
        //最大的年龄
        Optional<UserInfo> max = stream.max((m1,m2) -> m1.getAge() - m2.getAge());
        System.out.println(max.get());

        //最小的年龄
        //创建 Stream 流
        Stream<UserInfo> stream2 = list.stream();
        Optional<UserInfo> min = stream2.min((m1,m2) -> m1.getAge() - m2.getAge());
        System.out.println(min.get());

    }

    static class UserInfo {
        private String userName;
        private Integer age;

        public UserInfo(String userName, Integer age) {
            this.userName = userName;
            this.age = age;
        }

        @Override
        public String toString() {
            return "UserInfo{" +
                    "userName='" + userName + '\'' +
                    ", age=" + age +
                    '}';
        }

        public Integer getAge() {
            return age;
        }
    }
}

注意:Stream 流使用一次后,就会释放资源,如果想要二次使用,需要重新创建。否则报错:

Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed

输出:

UserInfo{userName='朱六', age=16}
UserInfo{userName='张三', age=13}

使用 Stream 的 Match 匹配

public class Test5 {
    public static void main(String[] args) {
        List<UserInfo> list = new ArrayList<>();
        list.add(new UserInfo("张三", 13));
        list.add(new UserInfo("李四", 14));
        list.add(new UserInfo("王五", 15));
        list.add(new UserInfo("朱六", 16));

        //创建 Stream 流
        Stream<UserInfo> stream = list.stream();
        boolean flag = stream.anyMatch(m -> "张三".equals(m.getUserName()));
        System.out.println(flag);
    }

    static class UserInfo {
        private String userName;
        private Integer age;

        public UserInfo(String userName, Integer age) {
            this.userName = userName;
            this.age = age;
        }

        @Override
        public String toString() {
            return "UserInfo{" +
                    "userName='" + userName + '\'' +
                    ", age=" + age +
                    '}';
        }

        public String getUserName() {
            return userName;
        }
    }
}

anyMatch 是返回任何一条匹配的即可。

输出:

true

使用 Stream 过滤器 Filter

public class Test6 {
    public static void main(String[] args) {
        List<UserInfo> list = new ArrayList<>();
        list.add(new UserInfo("张三", 13));
        list.add(new UserInfo("李四", 14));
        list.add(new UserInfo("王五", 15));
        list.add(new UserInfo("朱六", 16));
        list.add(new UserInfo("朱六", 20));

        //创建 Stream 流
        Stream<UserInfo> stream = list.stream();
        //过滤名字是【朱六】,且年龄大于18岁的
        stream.filter(m -> "朱六".equals(m.getUserName()) && m.getAge() > 18)
                .forEach(m -> System.out.println(m));
    }

    static class UserInfo {
        private String userName;
        private Integer age;

        public UserInfo(String userName, Integer age) {
            this.userName = userName;
            this.age = age;
        }

        @Override
        public String toString() {
            return "UserInfo{" +
                    "userName='" + userName + '\'' +
                    ", age=" + age +
                    '}';
        }

        public String getUserName() {
            return userName;
        }

        public Integer getAge() {
            return age;
        }
    }
}

输出:

UserInfo{userName='朱六', age=20}

使用 Stream 流分页 limit

public class Test7 {
    public static void main(String[] args) {
        List<UserInfo> list = new ArrayList<>();
        list.add(new UserInfo("张三", 13));
        list.add(new UserInfo("李四", 14));
        list.add(new UserInfo("王五", 15));
        list.add(new UserInfo("朱六", 16));
        list.add(new UserInfo("朱六", 20));

        //创建 Stream 流
        Stream<UserInfo> stream = list.stream();
        //取出前2条
        stream.limit(2).forEach(m -> System.out.println(m));
    }

    static class UserInfo {
        private String userName;
        private Integer age;

        public UserInfo(String userName, Integer age) {
            this.userName = userName;
            this.age = age;
        }

        @Override
        public String toString() {
            return "UserInfo{" +
                    "userName='" + userName + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
}

输出:

UserInfo{userName='张三', age=13}
UserInfo{userName='李四', age=14}

如果想从第3条开始获取呢?使用 skip 跳过,如下:

stream.skip(2).limit(3).forEach(m -> System.out.println(m));

输出:(如果 limit 的数字超过了 list 集合的长度,不会抛异常。)

UserInfo{userName='王五', age=15}
UserInfo{userName='朱六', age=16}
UserInfo{userName='朱六', age=20}

使用 Stream 排序 sort

按照年龄升序:

public class Test8 {
    public static void main(String[] args) {
        List<UserInfo> list = new ArrayList<>();
        list.add(new UserInfo("张三", 13));
        list.add(new UserInfo("李四", 14));
        list.add(new UserInfo("王五", 15));
        list.add(new UserInfo("朱六", 16));
        list.add(new UserInfo("朱六", 20));

        //创建 Stream 流
        Stream<UserInfo> stream = list.stream();
        stream.sorted((m1, m2) -> m1.getAge() - m2.getAge())
                .forEach(k -> System.out.println(k));
    }

    static class UserInfo {
        private String userName;
        private Integer age;

        public UserInfo(String userName, Integer age) {
            this.userName = userName;
            this.age = age;
        }

        @Override
        public String toString() {
            return "UserInfo{" +
                    "userName='" + userName + '\'' +
                    ", age=" + age +
                    '}';
        }

        public Integer getAge() {
            return age;
        }
    }
}

输出:

UserInfo{userName='张三', age=13}
UserInfo{userName='李四', age=14}
UserInfo{userName='王五', age=15}
UserInfo{userName='朱六', age=16}
UserInfo{userName='朱六', age=20}

如果需要降序排,则使用 m2 - m1 即可,如:

        //创建 Stream 流
        Stream<UserInfo> stream = list.stream();
        stream.sorted((m1, m2) -> m2.getAge() - m1.getAge())
                .forEach(k -> System.out.println(k));

输出:

UserInfo{userName='朱六', age=20}
UserInfo{userName='朱六', age=16}
UserInfo{userName='王五', age=15}
UserInfo{userName='李四', age=14}
UserInfo{userName='张三', age=13}

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-14 22:59:17  更:2021-07-14 22:59:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/17 20:51:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码