Java8新特性之Stream流(二)

简介

  • Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

  • Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

  • Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

  • 这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

  • 元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

语法

Stream流的三个操作步骤

  1. 创建Stream
    一个数据源(如:集合,数组),获取一个流
  2. 中间操作
    一个中间链,对数据源数据进行处理
  3. 终止操作
    一个终止操作,执行中间链,并产生结果

创建stream

	@Test
    public void test(){
        // 1. 通过collection的stream()
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();

        // 2. 通过Arrays的stream()
        User[] users = new User[10];
        Stream<User> stream2 = Arrays.stream(users);

        // 3. 通过Stream的静态方法of()
        Stream<String> stream3 = Stream.of("aa", "bb", "cc");

        // 4. 创建无限流
        // 迭代
        Stream<Integer> stream4 = Stream.iterate(0, x -> x + 2);
        stream4.limit(10).forEach(System.out::println);

        // 生成
        Stream.generate(() -> Math.random())
                .limit(10).forEach(System.out::println);
    }

中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何处理!而在终止操作时一次性全部处理,称为:“惰性求值”

  • 筛选与切片
    • filter—接收Lambda,从流中排除某些元素
    	@Test
        public void test(){
            List<User> users = Arrays.asList(new User("xyn",20),
                    new User("zyn",20));
            // 中间操作,不会执行任何操作
            Stream<User> userStream = users.stream()
                    .filter(user -> {
                        System.out.println("Stream 操作");
                        return user.getAge() > 19;
                    });
            // 终止操作:一次性执行全部内容,即惰性求值
            userStream.forEach(System.out::println);
        }
    
    • limit—截断流,使其元素不超过给定数量
    	@Test
        public void test(){
    	    List<User> users = Arrays.asList(new User("xyn",20),
    	                new User("zyn",20));
            // 中间操作,不会执行任何操作
            users.stream()
                .filter(user -> {
                    System.out.println("短路");
                    return user.getAge() > 19;
                })
                .limit(2)
                .forEach(System.out::println);
        }
    
    • skip(n)—跳过元素,返回一个扔掉了n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
    	@Test
        public void test(){
    	    List<User> users = Arrays.asList(new User("xyn",20),
    	                new User("zyn",20));
            // 中间操作,不会执行任何操作
            users.stream()
                    .filter(user -> user.getAge() > 18)
                    .skip(1)
                    .forEach(System.out::println);
        }
    
    • distinct—筛选,通过流所生成元素的hashcode()和equals()去除重复元素
    @Test
        public void test(){
    	    List<User> users = Arrays.asList(new User("xyn",20),
    	                new User("zyn",20));
            // 中间操作,不会执行任何操作
            users.stream()
                    .filter(user -> user.getAge() > 18)
                    .skip(1)
                    .distinct()
                    .forEach(System.out::println);
        }
    
  • 映射
    • map—接收Lambda,将元素转换为其他形式或提取信息,接收一个函数做参数该函数会被应用到每个参数上,并将其映射成一个新的元素
    	@Test
        public void test1(){
            List<User> users = Arrays.asList(new User("xyn",20),
                                             new User("zyn",20));
            users.stream()
                    .map(User::getName)
                    .forEach(System.out::println);
        }
    
    	@Test
        public void test2(){
            List<String> list = Arrays.asList("aaa", "bbb", "ccc");
            Stream<Stream<Character>> streamStream = list.stream()
                    .map(TestStreamAPI3::filterCharacter);
    
            streamStream.forEach(action -> {
                action.forEach(System.out::println);
            });
        }
    	
    	// 将字符串转化为字符流
        private static Stream<Character> filterCharacter(String str){
            List<Character> list = new ArrayList<>(10);
    
            for (char c : str.toCharArray()) {
                list.add(c);
            }
    
            return list.stream();
         }
    
    • flatMap—接收一个函数作为参数,将流中的每个值都换成另一个流,然后把这些流连接成一个流
    	// 与上方map形成对比
    	@Test
        public void test3(){
            List<String> list = Arrays.asList("aaa", "bbb", "ccc");
            Stream<Character> stream = list.stream()
                    .flatMap(TestStreamAPI3::filterCharacter);
    
            stream.forEach(System.out::println);
    
        }
        // 将字符串转化为字符流
        private static Stream<Character> filterCharacter(String str){
            List<Character> list = new ArrayList<>(10);
    
            for (char c : str.toCharArray()) {
                list.add(c);
            }
    
            return list.stream();
        }
    
  • 排序
    • sorted—自然排序
    	@Test
        public void test(){
    	    // 自然排序
            List<String> list = Arrays.asList("bbb", "aaa", "ccc");
            list.stream().sorted().forEach(System.out::println);
        }
    
    • sorted(Comparator com)—定制排序
    	@Test
        public void test(){
    	    // 定制排序
            List<User> users = Arrays.asList(new User("xyn",20),
                    new User("zyn",20));
    
            // 进行排序的对象必须实现Comparable接口(否则会报错)
            // users.stream().sorted().forEach(System.out::println);
    
            users.stream().sorted((u1,u2) -> {
                    if(u1.getAge() == u2.getAge()){
                        return u1.getName().compareTo(u2.getName());
                    }else{
                        return u1.getAge().compareTo(u2.getAge());
                    }
                }).forEach(System.out::println);
        }
    

终止操作

  • 查找与匹配
    • allMatch—检查是否匹配所有元素
    	public class User {
    	    private String name;
    	    private Integer age;
    	    private Status status;
    	
    	    public User(String name, Integer age) {
    	        this.name = name;
    	        this.age = age;
    	    }
    	
    	    public User(String name, Integer age, Status status) {
    	        this.name = name;
    	        this.age = age;
    	        this.status = status;
    	    }
    	
    	    public User() {
    	    }
    	
    	    public Status getStatus() {
    	        return status;
    	    }
    	
    	    public void setStatus(Status status) {
    	        this.status = status;
    	    }
    	
    	    public String getName() {
    	        return name;
    	    }
    	
    	    public void setName(String name) {
    	        this.name = name;
    	    }
    	
    	    public Integer getAge() {
    	        return age;
    	    }
    	
    	    public void setAge(Integer age) {
    	        this.age = age;
    	    }
    	
    	    @Override
    	    public String toString() {
    	        return "User{" +
    	                "name='" + name + '\'' +
    	                ", age=" + age +
    	                ", status=" + status +
    	                '}';
    	    }
    	
    	    public enum Status{
    	        FREE,
    	        BUSY,
    	        VOCATION;
    	    }
    	}
    
    	@Test
        public void test(){
        	List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY),
    		        new User("zyn",20, User.Status.FREE));
            boolean b = users.stream()
                    .allMatch(e -> e.getStatus().equals(User.Status.BUSY));
            System.out.println(b);
        }
    
    • anyMatch—检查是否至少匹配一个元素
    	@Test
        public void test(){
        	List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY),
    		        new User("zyn",20, User.Status.FREE));
            boolean b = users.stream()
                    .anyMatch(e -> e.getStatus().equals(User.Status.BUSY));
            System.out.println(b);
        }
    
    • noneMatch—检查是否没有匹配所有元素
    	@Test
        public void test(){
        	List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY),
    		        new User("zyn",20, User.Status.FREE));
            boolean b = users.stream()
                    .noneMatch(e -> e.getStatus().equals(User.Status.BUSY));
            System.out.println(b);
        }
    
    • findFirst—返回第一个元素
    	@Test
        public void test(){
        	List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY),
    		        new User("zyn",20, User.Status.FREE));
            Optional<User> optionalUser = users.stream()
                    .findFirst();
            System.out.println(optionalUser.get());
        }
    
    • findAny—返回当前流中的任意元素
    	@Test
        public void test(){
        	List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY),
    		        new User("zyn",20, User.Status.FREE));
            Optional<User> optionalUser = users.stream()
                    .filter(e -> e.getStatus().equals(User.Status.FREE))
                    .findAny();
            System.out.println(optionalUser.get());
        }
    
    • count—返回流中元素的总个数
    	@Test
        public void test(){
        	List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY),
    		        new User("zyn",20, User.Status.FREE));
            long count = users.stream()
                    .count();
            System.out.println(count);
        }
    
    • max—返回流中的最大值
    	@Test
        public void test(){
        	List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY),
    		        new User("zyn",20, User.Status.FREE));
            Optional<User> max = users.stream()
                    .max((u1, u2) -> Integer.compare(u1.getAge(), u2.getAge()));
            System.out.println(max.get());
        }
    
    • min—返回流中的最小值
    	@Test
        public void test(){
        	List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY),
    		        new User("zyn",20, User.Status.FREE));
            Optional<Integer> min = users.stream()
                .map(User::getAge)
                .min(Integer::compareTo);
            System.out.println(min.get());
        }
    
  • 归约与收集(重要)
    • reduce(T identity, BinaryOperator) / reduce(BinaryOperator)—可以将六中的元素反复结合起来,得到一个值
    	@Test
        public void test(){
            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
            List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY),
                    new User("zyn",20, User.Status.FREE));
    
            Integer sum = list.stream()
                    .reduce(0, (x, y) -> x + y);
            System.out.println(sum);
    		// 求年龄的和
            Optional<Integer> optional = users.stream()
                    .map(User::getAge)
                    .reduce(Integer::sum);
            System.out.println(optional.get());
        }
    
    • collect—将流转化为其他形式。接收一个Collector接口的实现,用于给Stream中的元素做汇总的方法
    	@Test
        public void test(){
            List<User> users = Arrays.asList(new User("xyn",20, User.Status.BUSY),
                    new User("zyn",20, User.Status.FREE),
                    new User("ayn",40, User.Status.FREE));
            // 放入集合
            List<String> list = users.stream()
                    .map(User::getName)
                    .collect(Collectors.toList());
    
            list.forEach(System.out::println);
    
            // 总和(年龄)
            Integer count = users.stream()
                    .collect(Collectors.summingInt(User::getAge));
            System.out.println(count);
    
            // 平均值(年龄)
            Double avg = users.stream()
                    .collect(Collectors.averagingInt(User::getAge));
            System.out.println(avg);
    
            // 最大值(年龄)
            Optional<Integer> max = users.stream()
                    .map(User::getAge)
                    .collect(Collectors.maxBy((u1, u2) -> Integer.compare(u1, u2)));
            System.out.println(max.get());
    
            // 最小值(年龄)
            Optional<Integer> min = users.stream()
                    .map(User::getAge)
                    .collect(Collectors.minBy((u1, u2) -> Integer.compare(u1, u2)));
            System.out.println(min.get());
    
            // 分组(按状态)
            Map<User.Status, List<User>> collect = users.stream()
                    .collect(Collectors.groupingBy(User::getStatus));
    
            System.out.println(collect);
    
            // 多级分组(先状态,后年龄)
            Map<User.Status, Map<String, List<User>>> collect1 = users.stream()
                    .collect(Collectors.groupingBy(User::getStatus, Collectors.groupingBy(e -> {
                        if (((User) e).getAge() <= 35) {
                            return "青年";
                        } else {
                            return "中年";
                        }
                    })));
            System.out.println(collect1);
    
            // 分区(按年龄分,大于20在一个区,其余在一个区)
            Map<Boolean, List<User>> collect2 = users.stream()
                    .collect(Collectors.partitioningBy(e -> e.getAge() > 20));
            System.out.println(collect2);
    
            // 功能统计
            DoubleSummaryStatistics collect3 = users.stream()
                    .collect(Collectors.summarizingDouble(User::getAge));
    
            System.out.println(collect3.getMax());
            System.out.println(collect3.getAverage());
            System.out.println(collect3.getCount());
            System.out.println(collect3.getSum());
    
            // 连接(姓名)
            String collect4 = users.stream()
                    .map(User::getName)
                    .collect(Collectors.joining(","));
            System.out.println(collect4);
        }
    

上一篇:Java8新特性之Lambda表达式(一)
下一篇:Java8新特性之Optional类(三)

视频:https://www.bilibili.com/video/av35195879

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值