Java8新特性——Stream流式计算

一、Java 8 Stream

Stream流,可以让你以一种声明的方式处理数据。大致运用于集合类的操作,极大的提高了编程效率和程序可读性。

Stream流是一个来自数据源的元素队列并支持聚合操作,元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。

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

二、如何生成流?

如果是数组的话,可以使用 Arrays.stream() 或者 Stream.of() 创建流;如果是集合的话,可以直接使用 stream() 方法创建流,因为该方法已经添加到 Collection 接口中

  • stream() − 为集合创建串行流

public static void main(String[] args) {
        // 1.数组生成流    Arrays.stream()/Stream.of()
        Integer[] arr = new Integer[]{1,2,3,4,5,6,7};

        /* 方式一:Arrays.stream(数组) 
        Stream<String> stream = Arrays.stream(arr);  */

        // 方式二:Stream.of(数组)
        Stream<Integer> stream = Stream.of(arr);
        stream.forEach(System.out::println); // 打印数组中所有元素


        // 2.集合生成流. stream()
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
        list.stream().forEach(System.out::println); // 打印 list中所有元素
}

 执行结果:

forEach() 方法接收的是一个 Consumer(Java 8 新增的一个函数式接口,接受一个输入参数并且无返回的操作)类型的参数,类名 :: 方法名是 Java 8 引入的新语法。System.out::println 可以看作 lambda表达式 e -> System.out.println(e) 

  • parallelStream() − 为集合创建并行流

public static void main(String[] args) {
       
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
        
        // parallelStream() 生成一个并行流
        list.parallelStream().forEach(System.out::println);
}

执行结果:

 通过打印结果发现parallelStream并行流每次执行的结果都不相同,并行流,顾名思义,可以理解为多线程同时执行。

三、如何操作流?

1. limit 返回条数

limit 方法用于获取指定数量的流。

public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
        list.stream()
                .limit(2) // 获取2条
                .forEach(System.out::println);
}

执行结果:以上代码使用 limit 方法打印出 2 条数据

▶ 2. filter 过滤

通过 filter() 方法可以从流中过滤元素

public static void main(String[] args) {

       List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
       list.stream()
                .filter(n->n>2)    // 筛选出集合中大于2的元素
                .filter(n->n%2==0) // 筛选出集合中的偶数
                .forEach(System.out::println);
}

 执行结果:可以多个filter叠加

filter方法传入的是一个 Predicate断定型函数接口:接受一个输入参数返回一个布尔值结果,上篇文章已对函数型接口进行了介绍和使用,看不懂此语法的伙伴可以参考:

 ▶ 3. map转换

用于映射每个元素到对应的结果。可理解为将集合中的元素类型,转换为另一种数据类型,或者是替换集合内部元素打印结果

 public static void main(String[] args) {

        List<String> list = Arrays.asList("Java","C++","中国");
        list.stream()
                .map(String::length) //等同map(str->str.length());获取该元素长度
                .forEach(System.out::println);
}

执行结果:

示例2:将小写字母转换为大写字母

public static void main(String[] args) {

        List<String> list = Arrays.asList("Java","C++","中国");
        list.stream()
                .map(String::toUpperCase)
                .forEach(System.out::println);
}

执行结果:

示例3:提取用户年龄

public static void main(String[] args) {

        User u1 = new User(1,"张三",21); 
        User u2 = new User(2,"李四",22);
        List<User> list = Arrays.asList(u1, u2);
        list.stream()
                .map(u->u.getAge())
                .forEach(System.out::println);
}

执行结果:

 4. sorted排序

用于对流进行排序

public static void main(String[] args) {

        User u1 = new User(1,"张三",21);
        User u2 = new User(2,"李四",22);
        List<User> list = Arrays.asList(u1, u2);
        list.stream()
                .sorted((uu1,uu2)->{return uu2.getAge().compareTo(uu1.getAge());})
                .map(u->u.getAge())
                .forEach(System.out::println);
}

执行结果:对用户年龄降序输出

 ▶ 5. distinct 去重

对流中的元素进行去重

public static void main(String[] args) {

       List<Integer> list = Arrays.asList(1,2,2,3,5);
        list.stream()
                .distinct()
                .forEach(System.out::println);

}

执行结果:

 ▶ 6. reduce 组合

主要作用是把流中的元素组合起来

 提供2种用法:

  • Optional<T> reduce(BinaryOperator<T> accumulator)

       没有起始值,只有一个参数,就是运算规则,此时返回Optional

  • T reduce(T identity, BinaryOperator<T> accumulator)

      有起始值,有运算规则,两个参数,此时返回的类型和起始值类型一致。

public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1,1,1);

        // 1.没有起始值
        Optional<Integer> optional = list.stream().reduce((a, b) -> a + b);
        System.out.println(optional.orElse(0)); // 如果结果为null,则=0

        // 2.有起始值,赋初始值为2,并依次累加元素中的值
        int sum =list.stream().reduce(2,(a, b) -> a + b);
        System.out.println(sum);
}

执行结果:

  ▶ 7. Collectors 转换流

Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:

public static void main(String[] args) {

        // 转换成新流

        List<String> list = Arrays.asList("j", "", "a", "v", "","a");
        System.out.println("旧集合:"+list);

        // 1.转换成新集合
        List<String> newList = list.stream()
                .filter(string -> !string.isEmpty()) // 过滤为空的元素
                .collect(Collectors.toList());

        System.out.println("新集合: " + newList);


        // 2.转换成TreeSet
        TreeSet<String> treeSet = list.stream()
                 // 等同于Collectors.toList()
                .collect(Collectors.toCollection(TreeSet::new)); 
        System.out.println("treeSet:"+treeSet);


        // 3.转换成set集合
        Set<String> set = list.stream().collect(Collectors.toSet());
        System.out.println("set:"+set);


        // 4.转换成字符串
        String str = list.stream()
                .filter(string -> !string.isEmpty()) // 过滤为空的元素
                .collect(Collectors.joining("-")); // 分割符
        System.out.println("合并字符串: " + str);
}

执行结果:

示例2:分组

  • partitioningBy :分为ture和false两组
  • groupingBy:将数据分组成多个key的形式(即我们理解的groupby分组)
public static void main(String[] args) {

        // partitioningBy:根据判断的值为true还是false分成2组
        List<Integer> list = Arrays.asList(5, 4, 2, 3, 2,6);
        Map<Boolean, List<Integer>> result = list.stream()
                .collect(partitioningBy(n -> n>3));
        System.out.println(result);


        // groupingBy:根据user的年龄分组
        User u1 = new User(1,"张三",22);
        User u2 = new User(2,"李四",22);
        User u3 = new User(3,"王五",23);
        List<User> ulist = Arrays.asList(u1, u2, u3, u4);
        Map<Integer, List<User>>  userResult = ulist.stream()
                .collect(Collectors.groupingBy(User::getAge));
        System.out.println(userResult);

        
        // groupingBy:根据元素值分组
        List<Integer> numList = Arrays.asList(4, 4, 1, 2);
        Map<String, List<Integer>> collect = numList.stream()
                .collect(Collectors.groupingBy(n -> n.toString()));
        System.out.println(collect);
}

执行结果:同为22岁的有张三和李四,被分为了一组

  ▶ 8. math匹配

对流中的元素进行匹配,匹配成功返回true,否则false

  • anyMatch():只要有一个元素匹配传入的条件,就返回 true。

  • allMatch():如果全部元素都匹配传入的条件,则返回 true。有一个不匹配则返回 false

  • noneMatch():只要有一个元素匹配传入的条件,则返回 false;全不匹配则返回true

public static void main(String[] args) {

        // anyMatch
        List<String> list = Arrays.asList("张三", "张婷婷", "王武", "李四");
        boolean result = list.stream().anyMatch(n -> n.contains("四"));
        System.out.println("任意一个元素包含字符'四':"+result);

        // allMatch
        boolean result2 = list.stream().allMatch(n -> n.length()>2);
        System.out.println("集合元素全部长度>2:"+result2);

        // noneMatch
        boolean result3 = list.stream().noneMatch(n -> n.startsWith("刘"));
        System.out.println("不存在第一个字符为'刘'的元素:"+result3);
}

执行结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值