java8新特性-Stream(流)

简介: java8新特性-Stream(流)

简介

流(Stream)是 Java 8 引入的一种处理集合数据的抽象概念,它提供了一种更简洁、更灵活的方式来操作和处理集合数据。流可以看作是一系列元素的管道,可以对这些元素进行筛选、转换、排序、归约等操作,实现各种数据处理需求。与传统的循环迭代方式相比,流的代码更易读、更易于并行化处理,并且能够充分发挥多核处理器的优势。通过使用流,可以提高代码的可读性和可维护性,同时也能够更高效地处理大规模数据集合。

Stream的常用案例

1.steam将list集合转set集合

public static void main(String [] args){
    List<Student> students=Arrays.asList(new Student("小明",18),new Student("小黑",16),new Student("小红",17));
    //转成流并进行set集合转换
    Set<Student> sets=students.stream().collect(Collectors.toSet());
    //集合遍历
    sets.forEach(stu->System.out.println(stu.toString()));
    
  }

在上面的示例中,我们首先创建了一个 List 集合 list,包含了三个对象。然后使用 stream 方法将其转换为流,接着使用 collect 方法将流中的元素收集到一个 Set 集合中,使用 Collectors.toSet() 指定要收集到的集合类型。最终得到了一个包含唯一元素的 Set 集合。

注意:转成set集合需要重写实体类Student的equals 方法和 hashCode 方法。

2.steam将list集合转map集合

public static void main(String [] args){
    List<Student> students=Arrays.asList(new Student("小明",18),new Student("小黑",16),new Student("小红",17));
    //转成Stream
    Stream<Student> stream=students.stream();
    //转Map
    Map<String,Student> map=stream.collect(Collectors.toMap(student->student.getName(), student->student));
    //遍历
    map.forEach((key,value)->System.out.println(key+"--"+value));
 
  }

在上面的示例中,我们首先创建了一个包含学生对象的 List<Student> 集合 students。然后使用 stream 方法将其转换为流,接着使用 collect 方法将流中的元素收集到一个 Map 集合中,使用 Collectors.toMap() 指定键和值的提取方式。在这里,我们使用学生对象的姓名作为键,学生对象本身作为值。

3.steam计算求和

public static void main(String[] args) {
 
        List<Student> students= Arrays.asList(new Student("小明",18),new Student("小黑",16),new Student("小红",17));
        //创建流并累加年龄
        int sum=students.stream().mapToInt(Student::getAge).sum();
        System.out.println(sum);
 
    }

4.steam查找最值

  public static void main(String[] args) {
        List<Student> students= Arrays.asList(new Student("小明",18),new Student("小黑",16),new Student("小红",17));
        //找出年龄最大的人
        Optional<Student> max=students.stream().max((o1, o2)->o1.getAge()-o2.getAge());
        System.out.println(max);
        //找出年龄最小的人
        Optional<Student> min=students.stream().min((o1, o2)->o1.getAge()-o2.getAge());
        System.out.println(min);
    }

5.stream的match

match 方法用于判断流中的元素是否符合指定的条件,并返回一个布尔值。

match 方法有三个变种:

  1. allMatch 方法:判断流中的所有元素是否都符合指定的条件,如果都符合,返回 true,否则返回 false
  2. anyMatch 方法:判断流中是否存在任意一个元素符合指定的条件,如果有,返回 true,否则返回 false
  3. noneMatch 方法:判断流中是否不存在任何一个元素符合指定的条件,如果没有,返回 true,否则返回 false
 public static void main(String[] args) {
        List<Student> students= Arrays.asList(new Student("小明",18),new Student("小黑",16),new Student("小红",17));
        // 判断所有学生年龄是否都大于17
        boolean match = students.stream().allMatch(s -> s.getAge() > 17);
        System.out.println(match);//false
        //判断只要有一个学生年龄小于17
        boolean match1 = students.stream().anyMatch(s -> s.getAge() < 17);
        System.out.println(match1);//true
        //判断没有一个学生年龄大于18
        boolean match2 = students.stream().noneMatch(s -> s.getAge() > 18);
        System.out.println(match2);//true
    }

6.stream过滤器

filter 方法接受一个 Predicate 参数,该参数是一个函数式接口,用于指定过滤条件。filter 方法会根据条件筛选出流中符合条件的元素,并返回一个新的流。

 public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // 过滤并打印出所有偶数
        Stream<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0);
        evenNumbers.forEach(System.out::println);
 
    }

7.stream Limit和skip

Stream 类提供了 limitskip 方法,用于限制流中元素的数量。

1.limit 方法:该方法用于截取流中的前 n 个元素,并返回一个新的流。如果流中的元素不足 n 个,则返回包含所有元素的流。

 public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        // 获取前3个元素
        Stream<Integer> limitedStream = numbers.stream().limit(3);
        limitedStream.forEach(System.out::println);
    }

2.skip 方法:该方法用于跳过流中的前 n 个元素,并返回一个新的流。如果流中的元素不足 n 个,则返回一个空的流。

 public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
 
        //跳过前两个元素
        Stream<Integer> skipStream = numbers.stream().skip(2);
        skipStream.forEach(System.out::println);
    }

一般我们会通过limit方法和skip搭配进行分页截取

public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5,6,7,8,9,10);
       
        //一页五个截取第二页
        Stream<Integer> skipLimitStream = numbers.stream().skip(5).limit(5);
        skipLimitStream.forEach(System.out::println);
    }

8.stream实现排序

 public static void main(String[] args) {
        // 创建一个包含整数的Stream
        Stream<Integer> stream1 = Stream.of(3, 1, 4, 1, 5, 9);
        Stream<Integer> stream2 = Stream.of(3, 1, 4, 1, 5, 9);
 
        // 使用sorted()方法对Stream1进行升序排序(默认)
        Stream<Integer> sortedStream = stream1.sorted();
        sortedStream.forEach(System.out::println);
        System.out.println("-----------------------------------------------");
        // 使用sorted()方法对Stream2进行降序排序
        Stream<Integer> sortedDescStream = stream2.sorted((a, b) -> b.compareTo(a));
        sortedDescStream.forEach(System.out::println);
 
    }

9.组合案例

我们来看一个需求

对给定的学生列表按照年龄降序排列并查找姓张的,获取前3位

public static void main(String[] args) {
        
        List<Student> students= Arrays.asList(new Student("张明",18),
                new Student("李黑",16),
                new Student("王红",17),
                new Student("张三",36),
                new Student("李四",27),
                new Student("刘备",56),
                new Student("关羽",47),
                new Student("张飞",49),
                new Student("张同",17),
                new Student("张良",41));
        //降序排序--查找姓张的--截取前三位
        students.stream().sorted((s1,s2)->s2.getAge()-s1.getAge())
                .filter(s->s.getName().startsWith("张"))
                .limit(3).forEach(System.out::println);
        System.out.println("-----------------------------------------------");
 
    }

通过对流进行一系列的中间操作就可以完成这个需求,这种链式调用可以使代码非常简洁。

10.并行流

Stream 类提供了并行流的支持,可以通过 parallel 方法将一个顺序流转换为并行流。并行流可以充分利用多核处理器的优势,将流中的元素进行并发处理,从而提高处理效率。

前面所有流的示例都是顺序流(单线程),有时在面对较大的数据处理单线程效率太慢,我们就可以使用并行流(多线程)进行优化。

来看一个需求,求1-1亿的累加和,分别用单线程的顺序流跟多线程的并行流来看执行效率。

 public static void main(String[] args) {
        // 顺序流计算
        long start = System.currentTimeMillis();
        int sum = IntStream.rangeClosed(1, 1000000000).sum();
        long end = System.currentTimeMillis();
        System.out.println("顺序流计算结果:" + sum + ",耗时:" + (end - start) + " 毫秒");
 
        // 并行流计算
        start = System.currentTimeMillis();
        sum = IntStream.rangeClosed(1, 1000000000).parallel().sum();
        end = System.currentTimeMillis();
        System.out.println("并行流计算结果:" + sum + ",耗时:" + (end - start) + " 毫秒");
    }

可以看到执行效率还是有明显提升的。

目录
相关文章
|
4月前
|
存储 安全 Java
Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
【10月更文挑战第17天】Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
99 2
|
4月前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
58 3
|
4月前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
50 2
|
2月前
|
存储 Java 开发者
什么是java的Compact Strings特性,什么情况下使用
Java 9引入了紧凑字符串特性,优化了字符串的内存使用。它通过将字符串从UTF-16字符数组改为字节数组存储,根据内容选择更节省内存的编码方式,通常能节省10%至15%的内存。
|
2月前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
89 6
|
2月前
|
Java API 开发者
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。
|
2月前
|
Rust 安全 Java
Java Stream 使用指南
本文介绍了Java中Stream流的使用方法,包括如何创建Stream流、中间操作(如map、filter、sorted等)和终结操作(如collect、forEach等)。此外,还讲解了并行流的概念及其可能带来的线程安全问题,并给出了示例代码。
|
3月前
|
分布式计算 Java API
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
47 4
|
3月前
|
安全 Java API
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
39 0
|
3月前
|
Java API 数据处理
探索Java中的Lambda表达式与Stream API
【10月更文挑战第22天】 在Java编程中,Lambda表达式和Stream API是两个强大的功能,它们极大地简化了代码的编写和提高了开发效率。本文将深入探讨这两个概念的基本用法、优势以及在实际项目中的应用案例,帮助读者更好地理解和运用这些现代Java特性。