java8中一个极其强悍的新特性Stream(非常实用)

简介: java8中有两个非常有名的改进,一个是Lambda表达式,一个是Stream。如果我们了解过函数式编程的话,都知道Stream真正把函数式编程的风格引入到了java中。这篇文章由简入繁逐步介绍Stream。

一、Stream是什么


从名字来看,Stream就是一个流,他的主要作用就是对集合数据进行查找过滤等操作。有点类似于SQL的数据库操作。一句话来解释就是一种高效且易用的数据处理方式。大数据领域也有一个Steam实时流计算框架,不过和这个可不一样。别搞混了。


举个例子吧,比如说有一个集合Student数据,我们要删选出学生名字为“张三”的学生,或者是找出所有年龄大于18岁的所有学生。此时我们就可以直接使用Stream来筛选。当然了这只是给出了其中一个例子。Stream还有很多其他的功能。


Stream和Collection的区别就是:Collection只是负责存储数据,不对数据做其他处理,主要是和内存打交道。但是Stream主要是负责计算数据的,主要是和CPU打交道。现在明白了吧。


二、Stream语法讲解


Stream执行流程很简单,主要有三个,首先创建一个Stream,然后使用Stream操作数据,最后终止Stream。有点类似于Stream的生命周期。下面我们根据其流程来一个一个讲解。


1、前提准备


首先我们创建一个Student类,以后我们每次都是操作这个类

public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private Double score;
    public Student() {
    }
    public Student(Integer id, String name, Integer age, Double score) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.score = score;
    }
    //getter和setter方法
    //toString方法
}

然后下面我们再创建一个StudentData类,用于获取其数据

public class StudentData {
    public  static List<Student> getStudents(){
        List<Student> list = new ArrayList<>();
        list.add(new Student(1,"刘备",18,90.4));
        list.add(new Student(2,"张飞",19,87.4));
        list.add(new Student(3,"关羽",21,67.4));
        list.add(new Student(4,"赵云",15,89.4));
        list.add(new Student(5,"马超",16,91.4));
        list.add(new Student(6,"曹操",19,83.4));
        list.add(new Student(7,"荀彧",24,78.4));
        list.add(new Student(8,"孙权",26,79.4));
        list.add(new Student(9,"鲁肃",21,93.4));
        return list;
    }
}

我们只需要把方法变成static类型的就可以了。


2、创建一个Stream


方式一:通过一个集合创建Stream

@Test
public void test1(){
    List<Student> studentList = StudentData.getStudents();
    //第一种:返回一个顺序流
    Stream<Student> stream = studentList.stream();
    //第二种:返回一个并行流
    Stream<Student> stream2 = studentList.parallelStream();
}

方式二:通过一个数组创建Stream

@Test
    public void test2(){
        //获取一个整形Stream
        int[] arr = new int[]{1,2,34,4,65,7,87,};
        IntStream intStream = Arrays.stream(arr);
        //获取一个Student对象Stream
        Student[] students = StudentData.getArrStudents();
        Stream<Student> stream = Arrays.stream(students);
    }

方式三:通过Stream.of

@Test
    public void test3(){
        Stream<Integer> integerStream = Stream.of(1, 2, 3, 5, 6, 7, 8);
        Stream<String> stringStream = Stream.of("1", "2", "3", "4", "5");
        Stream<Student> studentStream = Stream.of(
                new Student(1, "刘备", 18, 90.4),
                new Student(2, "张飞", 19, 87.4),
                new Student(3, "关羽", 21, 67.4));
    }

方式四:创建一个无限流

@Test
    public void test4(){
        //每隔5个数取一个,从0开始,此时就会无限循环
        Stream.iterate(0,t->t+5).forEach(System.out::println);
        //每隔5个数取一个,从0开始,只取前5个数
        Stream.iterate(0,t->t+5).limit(5).forEach(System.out::println);
        //取出一个随机数
        Stream.generate(Math::random).limit(5).forEach(System.out::println);
    }


3、使用Stream操作数据


操作1:筛选和切片

@Test
    public void test1(){
        List<Student> list  = StudentData.getStudents();
        //(1)过滤:过滤出所有年龄大于20岁的同学
        list.stream().filter(item->item.getAge()>20).forEach(System.out::println);
        //(2)截断流:筛选出前3条数据
        list.stream().limit(3).forEach(System.out::println);
        //(3)跳过元素:跳过前5个元素
        list.stream().skip(5).forEach(System.out::println);
        //(4)过滤重复数据:
        list.stream().distinct().forEach(System.out::println);
    }

操作2:映射

@Test
    public  void test2(){
        //(1)map操作
        List<String> list  = Arrays.asList("java","python","go");
        Stream<String> stream = list.stream();
        //此时每一个小写字母都有一个大写的映射
        stream.map(str -> str.toUpperCase()).forEach(System.out::println);
        //筛选出所有的年龄,再过滤出所有大于20的年龄有哪些
        List<Student> studentList  = StudentData.getStudents();
        Stream<Student> stream1 = studentList.stream();
        Stream<Integer> ageStream = stream1.map(Student::getAge);
        ageStream.filter(age->age>20).forEach(System.out::println);
        //(2)floatMap:将流中的每一个值换成另外一个流
    }

操作3:排序

public  void test3(){
        //(1)自然排序
        List<Integer> list  = Arrays.asList(4,3,7,9,12,8,10,23,2);
        Stream<Integer> stream = list.stream();
        stream.sorted().forEach(System.out::println);
        //(2)对象排序:对象类可以先实现comparable接口,或者是直接指定
        //第一种:先实现compable接口
        List<Student> studentList  = StudentData.getStudents();
        studentList.stream().sorted().forEach(System.out::println);
        //第二种:直接指定comparable
        List<Student> studentList1  = StudentData.getStudents();
        studentList1.stream()
                .sorted((e1,e2)-> Integer.compare(e1.getAge(),e2.getAge()))
                .forEach(System.out::println);
    }


4、终止Stream


操作1:匹配和查找

public void test1(){
        List<Student> list  = StudentData.getStudents();
        //(1)判断所有的学生年龄是否都大于20岁
        boolean allMatch = list.stream().allMatch(item -> item.getAge() > 20);
        //(2)判断是否存在学生的年龄大于20岁
        boolean anyMatch = list.stream().anyMatch(item -> item.getAge() > 20);
        //(3)判断是否存在学生叫曹操
        boolean noneMatch = list.stream().noneMatch(item -> item.getName().equals("曹操"));
        //(4)查找第一个学生
        Optional<Student> first = list.stream().findFirst();
        //(5)查找所有的学生数量
        long count = list.stream().count();
        long count1 = list.stream().filter(item -> item.getScore() > 90.0).count();
        //(6)查找当前流中的元素
        Optional<Student> any = list.stream().findAny();
        //(7)查找学生最高的分数:Student实现了comparable接口的话,可直接比较
        Stream<Double> doubleStream = list.stream().map(item -> item.getScore());
        doubleStream.max(Double::compare);
        //(8)查找学生最低的分数
    }

操作2:归约

public void test2(){
        //(1)计算数的总和
        List<Integer> list = Arrays.asList(1,2,3,4,5);
        list.stream().reduce(0,Integer::sum);
        //(3)计算学生总分
        List<Student> studentList = StudentData.getStudents();
        Stream<Double> doubleStream = studentList.stream().map(Student::getScore);
        doubleStream.reduce(Double::sum);
    }

操作3:收集

public void test3(){
        List<Student> studentList = StudentData.getStudents();
        //返回一个list
        List<Student> listStream = studentList.stream()
                .filter(e -> e.getAge() > 18)
                .collect(Collectors.toList());
        //返回一个Set
        Set<Student> setStream = studentList.stream()
                .filter(e -> e.getAge() > 18)
                .collect(Collectors.toSet());
        //返回其他的类型
    }

stream基本的语法就是这样,你会发现Stream就像是一个工具一样,可以帮我们分析处理数据,极其的好用,但是目前还不知道其效率如何。根据网上一位大佬的内存时间分析,其实在数据量比较庞大的时候,Stream可以为我们节省大量的时间,数据量小的时候并不明显。

相关文章
|
5天前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
20 3
|
5天前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
15 2
|
7天前
|
存储 算法 Java
Java Set因其“无重复”特性在集合框架中独树一帜
【10月更文挑战第14天】Java Set因其“无重复”特性在集合框架中独树一帜。本文深入解析Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定的数据结构(哈希表、红黑树)确保元素唯一性,并提供最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的`hashCode()`与`equals()`方法。
19 3
|
11天前
|
安全 Java API
Java 17新特性让你的代码起飞!
【10月更文挑战第4天】自Java 8发布以来,Java语言经历了多次重大更新,每一次都引入了令人兴奋的新特性,极大地提升了开发效率和代码质量。本文将带你从Java 8一路走到Java 17,探索那些能让你的代码起飞的关键特性。
46 1
|
19天前
|
编解码 Oracle Java
java9到java17的新特性学习--github新项目
本文宣布了一个名为"JavaLearnNote"的新GitHub项目,该项目旨在帮助Java开发者深入理解和掌握从Java 9到Java 17的每个版本的关键新特性,并通过实战演示、社区支持和持续更新来促进学习。
57 3
|
19天前
|
Java 流计算
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
32 1
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
|
19天前
|
Java Shell 流计算
Flink-02 Flink Java 3分钟上手 Stream SingleOutputStreamOpe ExecutionEnvironment DataSet FlatMapFunction
Flink-02 Flink Java 3分钟上手 Stream SingleOutputStreamOpe ExecutionEnvironment DataSet FlatMapFunction
17 1
Flink-02 Flink Java 3分钟上手 Stream SingleOutputStreamOpe ExecutionEnvironment DataSet FlatMapFunction
|
8天前
|
Java 开发者
在Java的集合世界里,Set以其独特的特性脱颖而出,它通过“哈希魔法”和“红黑树防御”两大绝技
【10月更文挑战第13天】在Java的集合世界里,Set以其独特的特性脱颖而出。它通过“哈希魔法”和“红黑树防御”两大绝技,有效抵御重复元素的侵扰,确保集合的纯洁性和有序性。无论是“人海战术”还是“偷梁换柱”,Set都能从容应对,成为开发者手中不可或缺的利器。
24 6
|
5天前
|
Java 开发者
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素。通过哈希表和红黑树两种模式,Set能够高效地识别并拒绝重复元素的入侵,确保集合的纯净。无论是HashSet还是TreeSet,都能在不同的场景下发挥出色的表现,成为开发者手中的利器。
18 2
|
5天前
|
Java
Java Set以其“不重复”的特性,为我们提供了一个高效、简洁的处理唯一性约束数据的方式。
【10月更文挑战第16天】在Java编程中,Set接口确保集合中没有重复元素,每个元素都是独一无二的。HashSet基于哈希表实现,提供高效的添加、删除和查找操作;TreeSet则基于红黑树实现,不仅去重还能自动排序。通过这两个实现类,我们可以轻松处理需要唯一性约束的数据,提升代码质量和效率。
17 2