| 
 ?查看之前的博客可以点击顶部的【分类专栏】 什么是 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 集合转换成 Mappublic 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 过滤器 Filterpublic 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 流分页 limitpublic 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}
 |