Java中Stream API的使用示例详解

 更新时间:2023年11月22日 14:00:55   作者:架构成长指南  
Java 在 Java 8 中提供了一个新的附加包,称为 java.util.stream,该包由类、接口和枚举组成,允许对元素进行函数式操作, 本文主要介绍了Java中Stream API的具体使用,感兴趣的小伙伴可以了解下

Java 在 Java 8 中提供了一个新的附加包,称为 java.util.stream。该包由类、接口和枚举组成,允许对元素进行函数式操作。 您可以通过在程序中导入 java.util.stream包来使用流。

Stream提供以下功能

Stream不存储元素。它只是通过计算操作的管道传送来自数据结构、数组或 I/O 通道等源的元素。

Stream本质上是函数式的,对流执行的操作不会修改其源。例如,过滤从集合获取的 Stream 会生成一个没有过滤元素的新 Stream,而不是从源集合中删除元素。

Stream是惰性的,仅在需要时才计算代码,在流的生命周期中,流的元素仅被访问一次。

与迭代器一样,必须生成新流才能重新访问源中的相同元素。

您可以使用 Stream 来 过滤、收集、打印以及 从一种数据结构转换为其他数据结构等。

Stream API 示例

1. 创建一个空的Stream

在创建空流时,应使用 empty() 方法:

Stream<String> stream = Stream.empty();
stream.forEach(System.out::println);

通常情况下,在创建时会使用 empty() 方法,以避免在没有元素的流中返回 null:

public Stream<String> streamOf(List<String> list) {
    return list == null || list.isEmpty() ? Stream.empty() : list.stream();
}

2.从集合中创建流

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;

public class StreamCreationExamples {
    public static void main(String[] args) throws IOException {

        Collection<String> collection = Arrays.asList("JAVA", "J2EE", "Spring", "Hibernate");
        Stream<String> stream2 = collection.stream();
        stream2.forEach(System.out::println);

        List<String> list = Arrays.asList("JAVA", "J2EE", "Spring", "Hibernate");
        Stream<String> stream3 = list.stream();
        stream3.forEach(System.out::println);

        Set<String> set = new HashSet<>(list);
        Stream<String> stream4 = set.stream();
        stream4.forEach(System.out::println);
    }
}

输出

JAVA
J2EE
Spring
Hibernate
JAVA
J2EE
Spring
Hibernate
JAVA
Hibernate
J2EE
Spring

3. 从数组中创建流对象

数组可以是流的源,也可以从现有数组或数组的一部分创建数组:

import java.util.Arrays;
import java.util.stream.Stream;

public class StreamCreationExample {
    public static void main(String[] args) {
        // 使用Arrays.stream()创建流
        int[] numbers = {1, 2, 3, 4, 5};
        Stream<Integer> stream1 = Arrays.stream(numbers);
        System.out.println("Using Arrays.stream():");
        stream1.forEach(System.out::println);

        // 使用Stream.of()创建流
        String[] names = {"Alice", "Bob", "Charlie"};
        Stream<String> stream2 = Stream.of(names);
        System.out.println("Using Stream.of():");
        stream2.forEach(System.out::println);

        // 使用Stream.builder()创建流
        String[] colors = {"Red", "Green", "Blue"};
        Stream.Builder<String> builder = Stream.builder();
        for (String color : colors) {
            builder.add(color);
        }
        Stream<String> stream3 = builder.build();
        System.out.println("Using Stream.builder():");
        stream3.forEach(System.out::println);
    }
}

输出

Using Arrays.stream():
1
2
3
4
5
Using Stream.of():
Alice
Bob
Charlie
Using Stream.builder():
Red
Green
Blue

4. 使用Stream过滤一个集合示例

在下面的示例中,我们不使用流过滤数据,看看代码是什么样的,同时我们在给出一个使用stream过滤的示例,对比一下

不使用Stream过滤一个集合示例

import java.util.ArrayList;
import java.util.List;

public class FilterWithoutStreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(40);
        numbers.add(50);

        List<Integer> filteredNumbers = new ArrayList<>();
        for (Integer number : numbers) {
            if (number > 30) {
                filteredNumbers.add(number);
            }
        }

        System.out.println("Filtered numbers (without Stream):");
        for (Integer number : filteredNumbers) {
            System.out.println(number);
        }
    }
}

输出:

Filtered numbers (without Stream):
40
50

使用 Stream 过滤集合示例:

import java.util.ArrayList;
import java.util.List;

public class FilterWithStreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(40);
        numbers.add(50);

        List<Integer> filteredNumbers = numbers.stream()
                .filter(number -> number > 30)
                .toList();

        System.out.println("Filtered numbers (with Stream):");
        filteredNumbers.forEach(System.out::println);
    }
}

输出:

Filtered numbers (with Stream):
40
50

前后我们对比一下,可以看到,使用 Stream 进行集合过滤可以更加简洁和直观,减少了手动迭代和添加元素的步骤。它提供了一种声明式的编程风格,使代码更易读、可维护和可扩展。

5. 使用Stream过滤和遍历集合

在下面的示例中,我们使用 filter() 方法进行过滤,使用 forEach() 方法对数据流进行迭代:

import java.util.ArrayList;
import java.util.List;

public class FilterAndIterateWithStreamExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");
        names.add("David");
        names.add("Eve");

        System.out.println("Filtered names starting with 'A':");
        names.stream()
                .filter(name -> name.startsWith("A"))
                .forEach(System.out::println);
    }
}

输出

Filtered names starting with 'A':
Alice

在上述示例中,我们有一个字符串列表 names,其中包含了一些名字。
我们使用 Stream 进行过滤和迭代操作以查找以字母 "A" 开头的名字。

6.使用Collectors方法求和

我们还可以使用Collectors计算数值之和。

在下面的示例中,我们使用Collectors类及其指定方法计算所有产品价格的总和。

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class SumByUsingCollectorsMethods {
    public static void main(String[] args) {
        List < Product > productsList = new ArrayList < Product > ();
        productsList.add(new Product(1, "HP Laptop", 25000f));
        productsList.add(new Product(2, "Dell Laptop", 30000f));
        productsList.add(new Product(3, "Lenevo Laptop", 28000f));
        productsList.add(new Product(4, "Sony Laptop", 28000f));
        productsList.add(new Product(5, "Apple Laptop", 90000f));
        
        double totalPrice3 = productsList.stream()
            .collect(Collectors.summingDouble(product -> product.getPrice()));
        System.out.println(totalPrice3);

    }
}

输出

201000.0

7. 使用Stream查找年龄最大和最小的学生

假设有一个 Student 类具有 name 和 age 属性。我们可以使用 Stream 来查找学生集合中年龄的最大和最小值,并打印出相应的学生信息。以下是一个示例:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

public class StudentStreamExample {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 20));
        students.add(new Student("Bob", 22));
        students.add(new Student("Charlie", 19));
        students.add(new Student("David", 21));

        // 查找年龄最大的学生
        Optional<Student> maxAgeStudent = students.stream()
                .max(Comparator.comparingInt(Student::getAge));

        // 查找年龄最小的学生
        Optional<Student> minAgeStudent = students.stream()
                .min(Comparator.comparingInt(Student::getAge));

        // 打印最大和最小年龄的学生信息
        System.out.println("Student with maximum age:");
        maxAgeStudent.ifPresent(System.out::println);

        System.out.println("Student with minimum age:");
        minAgeStudent.ifPresent(System.out::println);
    }
}

class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

输出:

Student with maximum age:
Student{name='Bob', age=22}
Student with minimum age:
Student{name='Charlie', age=19}

8. 使用Stream转换List为Map

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class StudentStreamToMapExample {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 20));
        students.add(new Student("Bob", 22));
        students.add(new Student("Charlie", 19));
        students.add(new Student("David", 21));

        // 将学生列表转换为 Map,以姓名为键,学生对象为值
        Map<String, Student> studentMap = students.stream()
                .collect(Collectors.toMap(Student::getName, student -> student));

        // 打印学生 Map
        for (Map.Entry<String, Student> entry : studentMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

输出

David: Student{name='David', age=21}
Bob: Student{name='Bob', age=22}
Charlie: Student{name='Charlie', age=19}
Alice: Student{name='Alice', age=20}

在上面示例中,我们使用Collectors.toMap() 方法将学生列表转换为 Map。我们指定了键提取器 Student::getName,将学生的姓名作为键。对于值提取器,我们使用了一个匿名函数 student -> student,它返回学生对象本身作为值。

9. 使用Stream把List对象转换为另一个List对象

假设我们有一个 Person 类,其中包含姓名和年龄属性。我们可以使用 Stream 来将一个 List 对象转换为另一个 List 对象,其中只包含人员的姓名。以下是一个示例:

  import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class ListTransformationExample {
    public static void main(String[] args) {
        List<Person> persons = new ArrayList<>();
        persons.add(new Person("Alice", 20));
        persons.add(new Person("Bob", 22));
        persons.add(new Person("Charlie", 19));

        // 将 Person 列表转换为只包含姓名的 String 列表
        List<String> names = persons.stream()
                .map(Person::getName)
                .collect(Collectors.toList());

        // 打印转换后的姓名列表
        System.out.println(names);
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

输出:

  [Alice, Bob, Charlie]

在上述示例中,我们有一个 Person 类,其中包含姓名和年龄属性。我们创建了一个 persons 列表,并添加了几个 Person 对象。

使用Stream,我们通过调用 map() 方法并传入一个方法引用 Person::getName,最后,我们使用 collect()方法和 Collectors.toList() 将转换后的姓名收集到一个新的列表中。

API

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

以上就是Java中Stream API的使用示例详解的详细内容,更多关于Java Stream API的资料请关注脚本之家其它相关文章!

相关文章

  • 详解SpringBoot+SpringSecurity+jwt整合及初体验

    详解SpringBoot+SpringSecurity+jwt整合及初体验

    这篇文章主要介绍了详解SpringBoot+SpringSecurity+jwt整合及初体验,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-06-06
  • 本地安装Nacos的踩坑过程及解决

    本地安装Nacos的踩坑过程及解决

    这篇文章主要介绍了本地安装Nacos的踩坑过程及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • Java 随机生成任意组电话号码过程解析

    Java 随机生成任意组电话号码过程解析

    这篇文章主要介绍了Java 随机生成任意组电话号码过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • Spring Boot超大文件上传实现秒传功能

    Spring Boot超大文件上传实现秒传功能

    这篇文章主要介绍了Spring Boot超大文件上传实现秒传功能,在实现分片上传的过程,需要前端和后端配合,比如前后端的上传块号的文件大小,前后端必须得要一致,否则上传就会有问题,需要的朋友可以参考下
    2022-12-12
  • 解决springboot MultipartFile文件上传遇到的问题

    解决springboot MultipartFile文件上传遇到的问题

    本文给大家带来了解决springboot MultipartFile文件上传遇到的问题,解决方法超简单,感兴趣的朋友参考下本文
    2018-08-08
  • 使用MultipartFile实现文件上传功能

    使用MultipartFile实现文件上传功能

    这篇文章主要介绍了使用MultipartFile实现文件上传功能,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • IntelliJ IDEA 安装 Grep Console插件 自定义控制台输出多颜色格式功能

    IntelliJ IDEA 安装 Grep Console插件 自定义控制台输出多颜色格式功能

    由于Intellij idea不支持显示ascii颜色,grep-console插件能很好的解决这个问题,下面就以开发JavaEE项目中,结合Log4j配置多颜色日志输出功能,感兴趣的朋友一起看看吧
    2020-05-05
  • java哈希算法HashMap经典面试题目汇总解析

    java哈希算法HashMap经典面试题目汇总解析

    这篇文章主要为大家介绍了java哈希算法HashMap的经典面试题目汇总及问题解析,帮助大家彻底征服面试官,实现薪资自由,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2022-03-03
  • Java编写实现九宫格应用

    Java编写实现九宫格应用

    这篇文章主要为大家详细介绍了Java编写实现九宫格应用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • 详谈Java 异常处理的误区和经验总结(分享)

    详谈Java 异常处理的误区和经验总结(分享)

    下面小编就为大家分享一篇Java 异常处理的误区和经验总结,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12

最新评论