java
复制代码
import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;
public class StreamFunctionExample {
public static void main(String[] args) {
// 准备数据
List<Student> students = Arrays.asList(
new Student("张三", 85, "计算机"),
new Student("李四", 58, "数学"),
new Student("王五", 92, "计算机"),
new Student("赵六", 45, "物理"),
new Student("小明", 78, "数学")
);
// 1. Predicate 使用:过滤及格的学生(成绩 >= 60)
Predicate<Student> isPass = student -> student.getScore() >= 60;
// 2. Function 使用:将 Student 转换为 String(姓名:成绩)
Function<Student, String> toNameScore = student ->
student.getName() + ":" + student.getScore();
// 3. Consumer 使用:打印信息
Consumer<String> printInfo = info -> System.out.println("及格学生: " + info);
// 4. Supplier 使用:生成默认学生对象(供给型)
Supplier<Student> defaultStudent = () -> new Student("默认学生", 0, "未知");
// ============ Stream 链式调用 ============
System.out.println("=== 及格学生列表 ===");
students.stream()
.filter(isPass) // Predicate: 过滤
.map(toNameScore) // Function: 转换
.forEach(printInfo); // Consumer: 消费打印
// ============ Predicate 组合使用 ============
System.out.println("\n=== 组合条件过滤 ===");
Predicate<Student> isComputer = student -> "计算机".equals(student.getMajor());
Predicate<Student> isHighScore = student -> student.getScore() >= 90;
students.stream()
.filter(isComputer.and(isHighScore)) // 计算机专业且高分(and组合)
// .filter(isComputer.or(isHighScore)) // 或者用 or 组合
.forEach(s -> System.out.println(s.getName() + " - " + s.getScore() + "分"));
// 输出: 王五 - 92分
// ============ Function 组合使用 ============
System.out.println("\n=== 成绩等级转换 ===");
Function<Integer, String> scoreToGrade = score -> {
if (score >= 90) return "A";
if (score >= 75) return "B";
if (score >= 60) return "C";
return "D";
};
// 组合: Student -> 成绩 -> 等级
Function<Student, String> studentToGrade =
student -> scoreToGrade.apply(student.getScore());
students.stream()
.filter(isPass)
.map(studentToGrade)
.forEach(grade -> System.out.print(grade + " ")); // 输出: C B A B
// ============ Consumer 使用:不同消费方式 ============
System.out.println("\n\n=== 多种消费方式 ===");
Consumer<Student> printDetail = s ->
System.out.printf("姓名:%-4s 成绩:%3d 专业:%s%n",
s.getName(), s.getScore(), s.getMajor());
Consumer<Student> collectFail = s ->
System.out.println("需要补考: " + s.getName());
students.stream()
.filter(s -> s.getScore() < 60)
.forEach(collectFail); // 输出: 需要补考: 李四, 需要补考: 赵六
// ============ Supplier 使用:orElseGet 提供默认值 ============
System.out.println("\n=== Supplier 提供默认值 ===");
// 查找数学专业最高分,如果不存在则使用 Supplier 提供默认值
Student topMathStudent = students.stream()
.filter(s -> "数学".equals(s.getMajor()))
.max(Comparator.comparingInt(Student::getScore))
.orElseGet(defaultStudent); // Supplier 在这里被调用
System.out.println("数学专业最高分: " + topMathStudent.getName()
+ " (" + topMathStudent.getScore() + "分)");
// 输出: 数学专业最高分: 李四 (58分) 注意:如果有多个数学专业,会取最高分
// 查找不存在专业的学生
Student topArtStudent = students.stream()
.filter(s -> "美术".equals(s.getMajor()))
.max(Comparator.comparingInt(Student::getScore))
.orElseGet(defaultStudent); // Supplier 提供默认值
System.out.println("美术专业最高分: " + topArtStudent.getName());
// 输出: 美术专业最高分: 默认学生
// ============ 综合实战:统计及格学生平均分 ============
System.out.println("\n=== 综合统计 ===");
double avgScore = students.stream()
.filter(isPass) // Predicate: 只统计及格的
.mapToInt(Student::getScore) // Function 特化版: 转换为 int
.average() // 计算平均值
.orElse(0.0); // Supplier: 没有数据时返回0
System.out.printf("及格学生平均分: %.2f%n", avgScore); // 输出: 85.00
// (85 + 92 + 78) / 3 = 85
}
}
// 学生实体类
class Student {
private String name;
private int score;
private String major;
public Student(String name, int score, String major) {
this.name = name;
this.score = score;
this.major = major;
}
public String getName() { return name; }
public int getScore() { return score; }
public String getMajor() { return major; }
}