一、前言

在现代Java开发中,Stream API已经成为了处理集合数据的强大工具之一。它提供了一种声明式编程方式,使得我们可以以更简洁、更易读的方式编写代码。本文将通过一系列示例来介绍如何使用Java Streams来操作List集合。

二、简介

在Java 8中引入的Stream API允许我们以一种更加自然和高效的方式来处理集合。与传统的循环或迭代不同,Stream API允许我们通过管道式的方法来处理数据流。这些操作可以分为中间操作(如filter, map, distinct等)和终端操作(如collect, forEach, reduce等)。

三、项目实践

1.创建实体

package com.example.springbootdemo.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Student {

    /**
     * 名字
     */
    private String name;
    /**
     * 年龄
     */
    private int age;
    /**
     * 年级
     */
    private String grade;

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.

2.初始化数据工具类

package com.example.springbootdemo.util;

import com.example.springbootdemo.domain.Student;

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

public class StudentUtil {


    public static List<Student> getStudentList() {
        List<Student> list = new ArrayList<Student>();
        list.add(new Student("aa", 20, "大一"));
        list.add(new Student("bb", 21, "大二"));
        list.add(new Student("cc", 23, "大三"));
        list.add(new Student("dd", 24, "大四"));
        list.add(new Student("ee", 21, "大二"));
        return list;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

3.过滤Filter操作

假设我们要找到所有年龄大于21岁的学生:

package com.example.springbootdemo.test;

import com.example.springbootdemo.domain.Student;
import com.example.springbootdemo.util.StudentUtil;

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

public class StudentDemo {
    public static void main(String[] args) {
        List<Student> studentList = StudentUtil.getStudentList();
        List<Student> students = studentList.stream().filter(s -> s.getAge() > 21).collect(Collectors.toList());
        System.out.println(students);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

运行结果:

Java8的Stream流对List操作的最佳实践_Java

4.映射Map操作

如果我们想获取所有学生的名字:

package com.example.springbootdemo.test;

import com.example.springbootdemo.domain.Student;
import com.example.springbootdemo.util.StudentUtil;

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

public class StudentDemo {
    public static void main(String[] args) {
        List<Student> studentList = StudentUtil.getStudentList();
        List<String> nameList = studentList.stream().map(s -> s.getName()).collect(Collectors.toList());
        System.out.println(nameList);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

运行结果:

Java8的Stream流对List操作的最佳实践_Stream_02

5.排序Sorted操作

我们可以按照学生年龄进行排序:

package com.example.springbootdemo.test;

import com.example.springbootdemo.domain.Student;
import com.example.springbootdemo.util.StudentUtil;

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

public class StudentDemo {
    public static void main(String[] args) {
        List<Student> studentList = StudentUtil.getStudentList();
        List<Student> students = studentList.stream().sorted((s1, s2) -> s1.getAge() - s2.getAge()).collect(Collectors.toList());
        System.out.println(students);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

运行结果:

Java8的Stream流对List操作的最佳实践_Java_03

6.分组Grouping操作

我们可以按年级分组学生:

package com.example.springbootdemo.test;

import com.example.springbootdemo.domain.Student;
import com.example.springbootdemo.util.StudentUtil;

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

public class StudentDemo {
    public static void main(String[] args) {
        List<Student> studentList = StudentUtil.getStudentList();
        Map<String, List<Student>> map = studentList.stream().collect(Collectors.groupingBy(s -> s.getGrade()));
        for (Map.Entry<String, List<Student>> entry : map.entrySet()) {
            System.out.println(entry.getKey() + "=>" + entry.getValue());
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

运行结果:

Java8的Stream流对List操作的最佳实践_Java_04

7.并行流 Parallel Streams

并行流可以提高处理大量数据时的性能:

package com.example.springbootdemo.test;

import com.example.springbootdemo.domain.Student;
import com.example.springbootdemo.util.StudentUtil;

import java.util.List;

public class StudentDemo {
    public static void main(String[] args) {
        List<Student> studentList = StudentUtil.getStudentList();
        //年龄求和
        int sumTotal = studentList.parallelStream().mapToInt(s -> s.getAge()).sum();
        System.out.println(sumTotal);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

运行结果:

Java8的Stream流对List操作的最佳实践_Java_05

8.Reduce

我们可以使用reduce方法来计算所有学生的平均年龄:

package com.example.springbootdemo.test;

import com.example.springbootdemo.domain.Student;
import com.example.springbootdemo.util.StudentUtil;

import java.util.List;
import java.util.OptionalDouble;

public class StudentDemo {
    public static void main(String[] args) {
        List<Student> studentList = StudentUtil.getStudentList();
        //求平均年龄
        OptionalDouble optionalDouble = studentList.stream().mapToInt(s -> s.getAge()).average();
        if (optionalDouble.isPresent()) {
            System.out.println(optionalDouble.getAsDouble());
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

运行结果:

Java8的Stream流对List操作的最佳实践_Stream_06

四、总结

通过上述示例,我们可以看到Stream API不仅简化了集合处理的代码,还提供了强大的工具来处理数据。从简单的过滤到复杂的分组和并行处理,Stream API都是现代Java开发不可或缺的一部分。