Stream API案例

wen java案例 3

本文目录导读:

Stream API案例

  1. 基础操作案例
  2. 中间操作案例
  3. 终端操作案例
  4. 性能优化与最佳实践
  5. 完整综合案例

我来为你提供Java Stream API的完整案例,从基础到进阶。

基础操作案例

创建Stream

import java.util.*;
import java.util.stream.*;
public class CreateStreamExample {
    public static void main(String[] args) {
        // 从集合创建
        List<String> list = Arrays.asList("apple", "banana", "orange");
        Stream<String> stream1 = list.stream();
        // 从数组创建
        String[] array = {"a", "b", "c"};
        Stream<String> stream2 = Arrays.stream(array);
        Stream<String> stream3 = Stream.of("a", "b", "c");
        // 从值创建
        Stream<Integer> stream4 = Stream.of(1, 2, 3, 4, 5);
        // 无限流
        Stream<Double> randomStream = Stream.generate(Math::random).limit(5);
        Stream<Integer> iterateStream = Stream.iterate(0, n -> n + 2).limit(5);
        // Builder模式
        Stream<String> builderStream = Stream.<String>builder()
                .add("a").add("b").add("c").build();
    }
}

过滤与映射

public class FilterMapExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // 过滤偶数
        List<Integer> evenNumbers = numbers.stream()
                .filter(n -> n % 2 == 0)
                .collect(Collectors.toList());
        System.out.println("偶数: " + evenNumbers);
        // 映射:每个数乘以2
        List<Integer> doubled = numbers.stream()
                .map(n -> n * 2)
                .collect(Collectors.toList());
        System.out.println("乘以2: " + doubled);
        // 过滤+映射组合
        List<Integer> result = numbers.stream()
                .filter(n -> n > 5)
                .map(n -> n * n)
                .collect(Collectors.toList());
        System.out.println("大于5且平方: " + result);
        // flatMap示例
        List<List<Integer>> nestedList = Arrays.asList(
                Arrays.asList(1, 2),
                Arrays.asList(3, 4),
                Arrays.asList(5, 6)
        );
        List<Integer> flatList = nestedList.stream()
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
        System.out.println("扁平化: " + flatList);
    }
}

中间操作案例

排序与去重

public class SortingDistinctExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Charlie", "Alice", "Bob", "David", "Alice");
        // 排序
        List<String> sortedNames = names.stream()
                .sorted()
                .collect(Collectors.toList());
        System.out.println("默认排序: " + sortedNames);
        // 自定义排序(按长度)
        List<String> lengthSort = names.stream()
                .sorted(Comparator.comparingInt(String::length))
                .collect(Collectors.toList());
        System.out.println("按长度排序: " + lengthSort);
        // 去重
        List<String> distinctNames = names.stream()
                .distinct()
                .collect(Collectors.toList());
        System.out.println("去重: " + distinctNames);
        // 限制和跳过
        List<String> limited = names.stream()
                .distinct()
                .skip(1)  // 跳过1个
                .limit(2) // 最多取2个
                .collect(Collectors.toList());
        System.out.println("跳过和限制: " + limited);
        // peek调试
        List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> peekResult = nums.stream()
                .peek(n -> System.out.println("原始值: " + n))
                .filter(n -> n > 2)
                .peek(n -> System.out.println("过滤后: " + n))
                .collect(Collectors.toList());
    }
}

数值流特化操作

public class NumericStreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(5, 3, 8, 1, 9, 2, 7);
        // 求和
        int sum = numbers.stream()
                .mapToInt(Integer::intValue)
                .sum();
        System.out.println("总和: " + sum);
        // 最大值、最小值
        OptionalInt max = numbers.stream()
                .mapToInt(Integer::intValue)
                .max();
        OptionalInt min = numbers.stream()
                .mapToInt(Integer::intValue)
                .min();
        System.out.println("最大值: " + max.getAsInt() + ", 最小值: " + min.getAsInt());
        // 平均值
        OptionalDouble average = numbers.stream()
                .mapToDouble(Integer::doubleValue)
                .average();
        System.out.println("平均值: " + average.getAsDouble());
        // 统计信息
        IntSummaryStatistics stats = numbers.stream()
                .mapToInt(Integer::intValue)
                .summaryStatistics();
        System.out.println("统计信息: " + stats);
        // 数值范围
        IntStream.range(1, 5).forEach(n -> System.out.print(n + " "));
        System.out.println();
        IntStream.rangeClosed(1, 5).forEach(n -> System.out.print(n + " "));
    }
}

终端操作案例

收集器案例

public class CollectorsExample {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Alice", 25, "北京"),
                new Person("Bob", 30, "上海"),
                new Person("Charlie", 35, "北京"),
                new Person("David", 28, "广州"),
                new Person("Eve", 42, "上海")
        );
        // 收集到List
        List<String> names = people.stream()
                .map(Person::getName)
                .collect(Collectors.toList());
        // 收集到Set(去重)
        Set<String> cities = people.stream()
                .map(Person::getCity)
                .collect(Collectors.toSet());
        System.out.println("城市: " + cities);
        // 收集到Map
        Map<String, Integer> nameToAge = people.stream()
                .collect(Collectors.toMap(
                        Person::getName,
                        Person::getAge
                ));
        System.out.println("姓名年龄映射: " + nameToAge);
        // 分组
        Map<String, List<Person>> groupByCity = people.stream()
                .collect(Collectors.groupingBy(Person::getCity));
        System.out.println("按城市分组: " + groupByCity);
        // 分组并统计
        Map<String, Long> countByCity = people.stream()
                .collect(Collectors.groupingBy(
                        Person::getCity,
                        Collectors.counting()
                ));
        System.out.println("各城市人数: " + countByCity);
        // 分区
        Map<Boolean, List<Person>> partitioned = people.stream()
                .collect(Collectors.partitioningBy(p -> p.getAge() > 30));
        System.out.println("年龄大于30的分区: " + partitioned);
        // 字符串连接
        String joinedNames = people.stream()
                .map(Person::getName)
                .collect(Collectors.joining(", "));
        System.out.println("连接的名字: " + joinedNames);
        // 汇总信息
        IntSummaryStatistics ageStats = people.stream()
                .collect(Collectors.summarizingInt(Person::getAge));
        System.out.println("年龄统计: " + ageStats);
    }
}

复杂业务场景

public class ComplexBusinessExample {
    static class Order {
        String customer;
        List<OrderItem> items;
        public Order(String customer, List<OrderItem> items) {
            this.customer = customer;
            this.items = items;
        }
    }
    static class OrderItem {
        String product;
        double price;
        int quantity;
        public OrderItem(String product, double price, int quantity) {
            this.product = product;
            this.price = price;
            this.quantity = quantity;
        }
        double totalPrice() {
            return price * quantity;
        }
    }
    public static void main(String[] args) {
        List<Order> orders = createOrders();
        // 1. 计算所有订单的总金额
        double totalRevenue = orders.stream()
                .flatMap(order -> order.items.stream())
                .mapToDouble(OrderItem::totalPrice)
                .sum();
        System.out.println("总营收: " + totalRevenue);
        // 2. 按产品分组计算销售总额
        Map<String, Double> productSales = orders.stream()
                .flatMap(order -> order.items.stream())
                .collect(Collectors.groupingBy(
                        item -> item.product,
                        Collectors.summingDouble(OrderItem::totalPrice)
                ));
        System.out.println("产品销售统计: " + productSales);
        // 3. 找出最畅销的三个产品
        List<String> topProducts = orders.stream()
                .flatMap(order -> order.items.stream())
                .collect(Collectors.groupingBy(
                        item -> item.product,
                        Collectors.summingInt(item -> item.quantity)
                ))
                .entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
                .limit(3)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        System.out.println("畅销产品TOP3: " + topProducts);
        // 4. 找出每个客户的平均订单金额
        Map<String, Double> customerAvg = orders.stream()
                .collect(Collectors.groupingBy(
                        order -> order.customer,
                        Collectors.averagingDouble(order -> 
                            order.items.stream().mapToDouble(OrderItem::totalPrice).sum())
                ));
        System.out.println("客户平均消费: " + customerAvg);
    }
    private static List<Order> createOrders() {
        return Arrays.asList(
                new Order("Alice", Arrays.asList(
                        new OrderItem("手机", 2999, 1),
                        new OrderItem("耳机", 199, 2)
                )),
                new Order("Bob", Arrays.asList(
                        new OrderItem("电脑", 5999, 1),
                        new OrderItem("鼠标", 99, 1)
                )),
                new Order("Alice", Arrays.asList(
                        new OrderItem("手机壳", 39, 3),
                        new OrderItem("耳机", 199, 1)
                ))
        );
    }
}

并行流案例

public class ParallelStreamExample {
    public static void main(String[] args) {
        // 创建一个大列表
        List<Integer> numbers = IntStream.rangeClosed(1, 1000000)
                .boxed()
                .collect(Collectors.toList());
        // 串行流
        long startTime = System.nanoTime();
        long serialSum = numbers.stream()
                .mapToLong(Integer::longValue)
                .sum();
        long serialTime = System.nanoTime() - startTime;
        System.out.println("串行流结果: " + serialSum + ", 耗时: " + serialTime/1_000_000 + "ms");
        // 并行流
        startTime = System.nanoTime();
        long parallelSum = numbers.parallelStream()
                .mapToLong(Integer::longValue)
                .sum();
        long parallelTime = System.nanoTime() - startTime;
        System.out.println("并行流结果: " + parallelSum + ", 耗时: " + parallelTime/1_000_000 + "ms");
        // 并行流过滤
        long count = numbers.parallelStream()
                .filter(n -> n % 2 == 0)
                .count();
        System.out.println("偶数个数: " + count);
    }
}

实际应用场景

public class RealWorldExample {
    // 数据模型
    static class Employee {
        String name;
        String department;
        double salary;
        int age;
        List<String> skills;
        public Employee(String name, String department, double salary, int age, List<String> skills) {
            this.name = name;
            this.department = department;
            this.salary = salary;
            this.age = age;
            this.skills = skills;
        }
    }
    public static void main(String[] args) {
        List<Employee> employees = getEmployees();
        // 1. 按部门分组,计算每个部门的平均工资
        Map<String, Double> deptAvgSalary = employees.stream()
                .collect(Collectors.groupingBy(
                        e -> e.department,
                        Collectors.averagingDouble(e -> e.salary)
                ));
        System.out.println("各部门平均工资: " + deptAvgSalary);
        // 2. 找出所有掌握Java且工资低于平均工资的员工
        double avgSalary = employees.stream()
                .mapToDouble(e -> e.salary)
                .average()
                .orElse(0);
        List<String> javaLowPaid = employees.stream()
                .filter(e -> e.skills.contains("Java"))
                .filter(e -> e.salary < avgSalary)
                .map(e -> e.name)
                .collect(Collectors.toList());
        System.out.println("掌握Java且低于平均工资: " + javaLowPaid);
        // 3. 找出所有技能中最稀缺的三种技能
        List<String> rareSkills = employees.stream()
                .flatMap(e -> e.skills.stream())
                .collect(Collectors.groupingBy(
                        skill -> skill,
                        Collectors.counting()
                ))
                .entrySet().stream()
                .sorted(Map.Entry.comparingByValue())
                .limit(3)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        System.out.println("最稀缺技能: " + rareSkills);
        // 4. 按年龄分段统计
        Map<String, Long> ageSegment = employees.stream()
                .collect(Collectors.groupingBy(
                        e -> {
                            if (e.age < 30) return "青年";
                            else if (e.age < 40) return "中年";
                            else return "老年";
                        },
                        Collectors.counting()
                ));
        System.out.println("年龄段分布: " + ageSegment);
        // 5. 找出工资最高的3个员工
        List<Employee> topEarners = employees.stream()
                .sorted(Comparator.comparingDouble(Employee::getSalary).reversed())
                .limit(3)
                .collect(Collectors.toList());
        System.out.println("工资TOP3: " + topEarners);
    }
    private static List<Employee> getEmployees() {
        return Arrays.asList(
                new Employee("张三", "技术部", 15000, 28, Arrays.asList("Java", "Spring", "MySQL")),
                new Employee("李四", "技术部", 18000, 32, Arrays.asList("Java", "Python", "Redis")),
                new Employee("王五", "产品部", 12000, 26, Arrays.asList("Axure", "Sketch")),
                new Employee("赵六", "技术部", 22000, 38, Arrays.asList("Java", "架构", "Spark")),
                new Employee("孙七", "市场部", 10000, 29, Arrays.asList("PS", "营销")),
                new Employee("周八", "产品部", 13000, 35, Arrays.asList("SQL", "Python", "Tableau"))
        );
    }
}

性能优化与最佳实践

短路操作优化

public class ShortCircuitExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // findFirst - 找到第一个大于5的数
        Optional<Integer> first = numbers.stream()
                .filter(n -> n > 5)
                .findFirst();
        System.out.println("第一个大于5的数: " + first.orElse(-1));
        // findAny - 任意一个(适合并行流)
        Optional<Integer> any = numbers.parallelStream()
                .filter(n -> n % 2 == 0)
                .findAny();
        System.out.println("任意偶数: " + any.orElse(-1));
        // allMatch, anyMatch, noneMatch
        boolean allPositive = numbers.stream().allMatch(n -> n > 0);
        boolean anyBig = numbers.stream().anyMatch(n -> n > 8);
        boolean noneNegative = numbers.stream().noneMatch(n -> n < 0);
        System.out.println("全部正数: " + allPositive);
        System.out.println("有大于8的: " + anyBig);
        System.out.println("没有负数: " + noneNegative);
    }
}

自定义收集器

public class CustomCollectorExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // 自定义收集器:收集奇数和偶数
        Map<Boolean, Long> oddEvenCount = numbers.stream()
                .collect(Collectors.partitioningBy(
                        n -> n % 2 == 0,
                        Collectors.counting()
                ));
        System.out.println("奇偶数统计: " + oddEvenCount);
        // 自定义聚合操作
        String result = numbers.stream()
                .collect(
                        StringBuilder::new,
                        (sb, number) -> sb.append(number).append(", "),
                        StringBuilder::append
                ).toString();
        System.out.println("拼接结果: " + result);
        // 自定义收集器 - 多重分组
        Map<String, Map<String, Long>> complexGroup = numbers.stream()
                .collect(Collectors.groupingBy(
                        n -> n % 3 == 0 ? "被3整除" : "不被3整除",
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> {
                                    Map<String, Long> stats = new HashMap<>();
                                    stats.put("count", (long) list.size());
                                    stats.put("sum", list.stream().mapToInt(Integer::intValue).sum());
                                    return stats;
                                }
                        )
                ));
        System.out.println("复杂分组: " + complexGroup);
    }
}

异常处理模式

public class ErrorHandlingExample {
    public static void main(String[] args) {
        List<String> numbers = Arrays.asList("1", "2", "3", "abc", "4", "5");
        // 安全转换,过滤非法输入
        List<Integer> validNumbers = numbers.stream()
                .map(s -> {
                    try {
                        return Optional.of(Integer.parseInt(s));
                    } catch (NumberFormatException e) {
                        return Optional.<Integer>empty();
                    }
                })
                .filter(Optional::isPresent)
                .map(Optional::get)
                .collect(Collectors.toList());
        System.out.println("有效数字: " + validNumbers);
        // 使用Optional处理可能为null的情况
        List<String> names = Arrays.asList("Alice", null, "Bob", null, "Charlie");
        List<String> validNames = names.stream()
                .filter(Objects::nonNull)
                .map(String::toUpperCase)
                .collect(Collectors.toList());
        System.out.println("有效名字: " + validNames);
        // 使用orElseGet提供默认值
        int result = numbers.stream()
                .mapToInt(s -> {
                    try {
                        return Integer.parseInt(s);
                    } catch (NumberFormatException e) {
                        return 0;
                    }
                })
                .sum();
        System.out.println("总和(无效视为0): " + result);
    }
}

完整综合案例

数据分析综合案例

public class DataAnalysisExample {
    static class Product {
        String category;
        String name;
        double price;
        int sales;
        public Product(String category, String name, double price, int sales) {
            this.category = category;
            this.name = name;
            this.price = price;
            this.sales = sales;
        }
    }
    public static void main(String[] args) {
        List<Product> products = getProducts();
        // 1. 各品类总销售额
        Map<String, Double> categoryRevenue = products.stream()
                .collect(Collectors.groupingBy(
                        p -> p.category,
                        Collectors.summingDouble(p -> p.price * p.sales)
                ));
        System.out.println("各品类销售额:");
        categoryRevenue.forEach((k, v) -> System.out.printf("  %s: %.2f%n", k, v));
        // 2. 找出各品类最畅销的产品(按销量)
        Map<String, Product> bestSeller = products.stream()
                .collect(Collectors.groupingBy(
                        p -> p.category,
                        Collectors.collectingAndThen(
                                Collectors.maxBy(Comparator.comparingInt(p -> p.sales)),
                                Optional::get
                        )
                ));
        System.out.println("\n各品类最畅销产品:");
        bestSeller.forEach((k, v) -> System.out.printf("  %s: %s (销量: %d)%n", k, v.name, v.sales));
        // 3. 价格分析
        double avgPrice = products.stream()
                .mapToDouble(p -> p.price)
                .average()
                .orElse(0);
        Map<String, List<String>> priceRange = products.stream()
                .collect(Collectors.groupingBy(
                        p -> {
                            if (p.price < 500) return "低价位";
                            else if (p.price < 2000) return "中价位";
                            else return "高价位";
                        },
                        Collectors.mapping(p -> p.name, Collectors.toList())
                ));
        System.out.println("\n价格区间分布:");
        priceRange.forEach((k, v) -> System.out.printf("  %s: %s%n", k, v));
        // 4. 销售额排名
        List<Map.Entry<String, Double>> revenueRanking = products.stream()
                .collect(Collectors.groupingBy(
                        p -> p.name,
                        Collectors.summingDouble(p -> p.price * p.sales)
                ))
                .entrySet().stream()
                .sorted(Map.Entry.<String, Double>comparingByValue().reversed())
                .limit(5)
                .collect(Collectors.toList());
        System.out.println("\n销售额TOP5:");
        revenueRanking.forEach(entry -> 
            System.out.printf("  %s: %.2f%n", entry.getKey(), entry.getValue()));
        // 5. 销量占比分析
        double totalSales = products.stream()
                .mapToInt(p -> p.sales)
                .sum();
        Map<String, Double> salesShare = products.stream()
                .collect(Collectors.groupingBy(
                        p -> p.category,
                        Collectors.summingDouble(p -> (double) p.sales / totalSales * 100)
                ));
        System.out.println("\n各品类销量占比:");
        salesShare.forEach((k, v) -> System.out.printf("  %s: %.1f%%%n", k, v));
    }
    private static List<Product> getProducts() {
        return Arrays.asList(
                new Product("电子产品", "iPhone 15", 5999, 100),
                new Product("电子产品", "MacBook Pro", 12999, 50),
                new Product("电子产品", "AirPods", 1299, 200),
                new Product("服装", "羽绒服", 599, 80),
                new Product("服装", "牛仔裤", 299, 150),
                new Product("服装", "T恤", 99, 300),
                new Product("食品", "进口水果", 199, 120),
                new Product("食品", "坚果礼盒", 399, 90),
                new Product("食品", "巧克力", 159, 180)
        );
    }
}
  1. 使用Optional避免NPEOptional.ofNullable() + orElse()
  2. 合理使用并行流:数据量大时使用,注意线程安全
  3. 性能优化
    • 使用limit()skip()进行分页
    • 使用短路操作如findFirst()anyMatch()提高效率
    • 避免不必要的boxed操作
  4. 代码可读性
    • 使用方法引用
    • 复杂的lambda表达式提取为方法
    • 合理使用链式操作
  5. 错误处理
    • 处理可能为null的情况
    • 处理parse异常等Checked Exception
  6. 收集器选择
    • 简单场景用toList()toSet()
    • 分组用groupingBy()
    • 统计用summarizingInt()summarizingDouble()

这些案例覆盖了Stream API的主要特性,你可以根据需要选择使用,每个案例都注重实际应用场景,便于直接参考和使用。

抱歉,评论功能暂时关闭!