【JavaSE高级】Java8新特性 - Stream

Java8新特性 - Stream

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

Stream介绍

Stream是一个流,在Java.util.Stream包路径下,他的主要作用就是对集合数据进行查找过滤等操作。通俗解释就是一种高效且易用的数据处理方式。大数据领域也有一个Steam实时流计算框架,不过和这个可不一样。别搞混了。

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

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

Stream操作步骤

Stream执行流程很简单,主要有三个:

  • 1、创建一个Stream:从一个数据源,如集合、数组中获取流。
  • 2、使用Stream操作数据:一个操作的中间链,对数据源的数据进行操作。
  • 3、终止Stream:一个终止操作,执行中间操作链,并产生结果。

要注意的是,对流的操作完成后需要进行关闭操作。

数据准备

  • 首先创建一个Student类,以对该类的使用来了解Stream流。
public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private Double score;
 
    public Student(Integer id, String name, Integer age, Double score) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.score = score;
    }
}
  • 创建一个StudentData类用于获取数据。
public class StudentData {
    public static List<Student> getStudents(){
        ArrayList <Student> students = new ArrayList <>();
        students.add(new Student(1,"小白",23,89.5));
        students.add(new Student(2,"小蔡",22,90.9));
        students.add(new Student(3,"小惠",22,87.1));
        students.add(new Student(4,"小韩",25, 89.6));
        return students;
    }
}

创建Stream

  • 方式一:通过集合创建Stream。
//通过一个集合创建stream
public static void test1() {
     List <Student> students =StudentData.getStudents();
     //第一种:返回一个顺序流
     Stream  <Student> stream = students.stream();
     //第二种:返回一个并行流
     Stream  <Student> stream1 = students.parallelStream();
}
  • 方式二:通过一个数组创建stream。
//通过一个数组创建stream
 public static void test2() {
   //获取一个整形stream
   int[]arr = {1, 34, 2, 54, 56, 34};
   IntStream stream = Arrays.stream(arr);
 }
 
  • 方式三:通过Stream.of。
//通过Stream.of
public static void test3() {
   Stream <String> stringStream = Stream.of("1", "4", "34", "23");
   Stream <Student> studentStream = Stream.of(
       new Student(1, "小白", 23, 89.5),
       newStudent(2, "小蔡", 22, 90.9)
   );
}
  • 方式四:创建一个无限流。
//创建无限流
public static void test4() {
   //每隔5个数取一个,从0开始,此时就会无限循环
   Stream<Integer> iterate = Stream.iterate(0,t -> t + 5);
   //取出一个随机数
   Stream<Double> generate = Stream.generate(Math::random);
}

Stream操作数据

  • 操作1:筛选和切片。
    • filter - - 接收Lambda,从流中排除某些操作;
    • limit - - 截断流,使其元素不超过给定对象;
    • skip(n) - - 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补;
    • distinct - - 筛选,通过流所生成元素的hashCode()和equals()去除重复元素。
public static void test5() {
    /**
     * 写成System.out::println,这种语法叫做方法引用。该功能特性也是JDK8以后引入的,你可以把它看做lambdas表达式的语法糖。
     * 可以用lambdas表达式改写成以下代码:list.forEach((t) -> System.out.println(t));
     * 还不明白的话,也可以这样:list.forEach((String t) -> System.out.println(t));
     * 这样的效果跟System.out::println是一样的。
     */
    List <Student> list = StudentData.getStudents();
    //过滤:过滤出所有年龄大于22岁的同学
    list.stream().filter(item -> item.getAge() > 22).forEach(System.out::println);
    //截断流:筛选出前3条
    list.stream().limit(3).forEach(System.out::println);
    //跳过元素:跳过前2个元素
    list.stream().skip(2).forEach(System.out::println);
    //过滤重复元素
    list.stream().distinct().forEach(System.out::println);
}
  • 操作2:映射。
    • map - - 接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
    • flatMap - - 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
public static void test6() {
    //map操作
    List <String> list = Arrays.asList("hello", "word", "tulun");
    Stream <String> stream = list.stream();
    //将每一个小写字母的都转化为大写字母映射
    stream.map(str -> str.toUpperCase()).forEach(System.out::println);

    //筛选出所有的年龄,再过滤所有大于23的年龄有哪些
    List <Student> students = StudentData.getStudents();
    Stream <Student> stream1 = students.stream();
    //将流中的每一值转化为另一个值
    Stream <Integer> stream2 = stream1.map(Student::getAge);
    stream2.filter(age -> age > 23).forEach(System.out::println);
}
  • 操作3:排序。
    • sorted() - - 自然排序(Comparable);
    • sorted(Comparator com) - - 定制排序(Comparator);
public static void test7() {
    //自然排序
    List <Integer> list = Arrays.asList(4, 7, 1, 3, 6, 8, 9, 3);
    Stream <Integer> stream = list.stream();
    stream.sorted().forEach(System.out::println);

    //对象排序,对象排序可以先实现comparable接口或者直接指定
    //第一种:先实现comparable接口
    List <Student> students = StudentData.getStudents();
    students.stream().sorted().forEach(System.out::println);
    //第二种:直接指定comparable
    List <Student> students1 = StudentData.getStudents();
    students1.stream().sorted((e1,e2)-> (int) (e1.getScore()-e2.getScore())).forEach(System.out::println);
}

终止Stream

  • 操作1:匹配和查找。
    • allMatch - - 检查是否匹配所有元素;
    • anyMatch - - 检查是否至少匹配一个元素;
    • noneMatch - - 检查是否没有匹配所有元素;
    • findFirst - - 返回第一个元素;
    • findAny - - 返回当前流中的任意元素;
    • count - - 返回流中元素的总个数;
    • max - - 返回流中最大值;
    • min - - 返回流中最小值;
public static void test8() {
    List <Student> list = StudentData.getStudents();
    //判断所有的学生年龄是否都大于20岁
    boolean allMatch = list.stream().allMatch(student -> student.getAge() > 20);
    //判断是否存在学生的年龄大于20岁
    boolean anyMatch = list.stream().anyMatch(student -> student.getAge() > 20);
    //判断是否不存在学生叫小白
    boolean noneMatch = list.stream().noneMatch(student -> student.getName().equals("小白"));
    //查找第一个学生
    Optional <Student> first = list.stream().findFirst();
    //查找当前流中的元素
    Optional <Student> any = list.stream().findAny();
    //查找所有的学生数量
    long count = list.stream().count();
    //查找成绩高于90分的同学数量
    long count1 = list.stream().filter(student -> student.getScore() > 90).count();
    //查找学生的最高分数
    Stream <Double> doubleStream = list.stream().map(student -> student.getScore());
    Optional <Double> max = doubleStream.max(Double::compareTo);
}
  • 操作2:归约。
    • reduce - - 归约操作可以将流中元素反复结合起来,得到一个值。
public static void test9() {
    //计算数的总和
    List <Integer> list = Arrays.asList(4, 7, 1, 3, 6, 8, 9, 3);
    list.stream().reduce(0, Integer::sum);

    //计算学生总分
    List <Student> students = StudentData.getStudents();
    Stream <Double> doubleStream = students.stream().map(Student::getScore);
    doubleStream.reduce(Double::sum);
}
  • 操作3:收集。
    • collect - - 将流转换为其他形式,接收一个Collector接口实现 ,用于给Stream中汇总的方法。
public static void test10() {
    //返回一个list
    List <Student> students = StudentData.getStudents();
    List <Student> list = students.stream()
            .filter(student -> student.getScore() > 88)
            .collect(Collectors.toList());

    //返回一个set
    Set <Student> set = students.stream()
    		.filter(s -> s.getAge() > 23)
            .collect(Collectors.toSet());
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值