练习题

package org.example.b;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * Java Stream 练习 - 完整版
 *
 * 请完成下面所有标记为 // TODO: 的方法。
 * 每个方法都有详细的题目描述和提示使用哪些Stream API
 */
public class StreamPractice {

    public static void main(String[] args) {
        // --- 测试数据 ---
        ArrayList<Product> products = new ArrayList<>();
        products.add(new Product("P1", "笔记本电脑", "电子产品", 1200.0, 10));
        products.add(new Product("P2", "鼠标", "电子产品", 25.0, 150));
        products.add(new Product("P3", "机械键盘", "电子产品", 75.0, 80));
        products.add(new Product("P4", "T恤", "服装", 20.0, 200));
        products.add(new Product("P5", "牛仔裤", "服装", 80.0, 70));
        products.add(new Product("P6", "百年孤独", "图书", 15.0, 120));
        products.add(new Product("P7", "Java编程思想", "图书", 90.0, 50));
        products.add(new Product("P8", "显示器", "电子产品", 300.0, 40));
        products.add(new Product("P9", "运动鞋", "服装", 120.0, 0)); // 库存为0
        products.add(new Product("P10", "Python入门", "图书", 45.0, 30));
        products.add(new Product("P11", "智能手表", "电子产品", 800.0, 25));

        // --- 在这里可以调用你实现的方法进行测试 ---
        // 例如:
        // System.out.println("电子产品: " + findProductsByCategory(products, "电子产品"));
        // System.out.println("总库存价值: " + calculateTotalInventoryValue(products));
        // 记得取消注释来测试你的实现!
    }

    // =================================================================
    // ====================== 基础练习 (原题) ===========================
    // =================================================================

    /**
     * 题干 1: 按类别查找产品
     * 任务: 查找并返回属于指定类别的所有产品。
     * 提示: 使用 filter 和 collect(Collectors.toList())
     * @param products 产品列表
     * @param category 要查找的类别
     * @return 该类别下的产品列表
     */
    static List<Product> findProductsByCategory(List<Product> products, String category) {
        // TODO: 使用 Stream 的 filter 操作筛选出指定类别的产品,并收集为列表。
        return null;
    }

    /**
     * 题干 2: 计算总库存价值
     * 任务: 计算所有产品库存的总价值(每个产品的价格 * 库存量,然后求和)。
     * 提示: 使用 mapToDouble 和 sum
     * @param products 产品列表
     * @return 所有产品的总库存价值
     */
    static double calculateTotalInventoryValue(List<Product> products) {
        // TODO: 使用 Stream 的 mapToDouble 将每个产品转换为其库存价值,然后求和。
        return 0.0;
    }

    /**
     * 题干 3: 按类别对产品进行分组
     * 任务: 将所有产品按照它们的类别进行分组。
     * 提示: 使用 collect(Collectors.groupingBy())
     * @param products 产品列表
     * @return 一个 Map,其中 Key 是类别名称,Value 是该类别的产品列表。
     */
    static Map<String, List<Product>> groupProductsByCategory(List<Product> products) {
        // TODO: 使用 Collectors.groupingBy 按产品类别进行分组。
        return null;
    }

    /**
     * 题干 4: 查找最贵的产品
     * 任务: 从产品列表中找出价格最高的产品。
     * 提示: 使用 max(Comparator.comparing())
     * @param products 产品列表
     * @return 一个包含最贵产品的 Optional,如果列表为空则为空 Optional。
     */
    static Optional<Product> findMostExpensiveProduct(List<Product> products) {
        // TODO: 使用 Stream 的 max 操作和 Comparator 找出价格最高的产品。
        return Optional.empty();
    }

    /**
     * 题干 5: 获取所有缺货(库存为0)的产品名称
     * 任务: 查找所有库存量为 0 的产品,并返回它们的名称列表。
     * 提示: 先 filter 再 map
     * @param products 产品列表
     * @return 缺货产品的名称列表。
     */
    static List<String> getOutOfStockProductNames(List<Product> products) {
        // TODO: 先使用 filter 筛选出库存为0的产品,然后使用 map 提取产品名称。
        return null;
    }

    /**
     * 题干 6: 计算特定类别产品的平均价格
     * 任务: 计算指定类别的所有产品的平均价格。
     * 提示: 先 filter 再使用 Collectors.averagingDouble
     * @param products 产品列表
     * @param category 指定的类别
     * @return 该类别产品的平均价格
     */
    static double getAveragePriceByCategory(List<Product> products, String category) {
        // TODO: 先 filter 筛选出指定类别的产品,然后使用 Collectors.averagingDouble 计算平均价。
        return 0.0;
    }

    /**
     * 题干 7: 将产品列表转换为 Map
     * 任务: 将产品列表转换为一个 Map,其中 Key 是产品ID,Value 是产品对象本身。
     * 提示: 使用 Collectors.toMap 和 Function.identity()
     * @param products 产品列表
     * @return 一个以产品ID为键,产品对象为值的 Map。
     */
    static Map<String, Product> convertListToProductMap(List<Product> products) {
        // TODO: 使用 Collectors.toMap 将列表转换为 Map。
        return null;
    }

    // =================================================================
    // ====================== 进阶练习 (新增题目) =======================
    // =================================================================

    /**
     * 题干 8: 获取前N个最贵的产品
     * 任务: 返回价格最高的前N个产品,按价格从高到低排列。
     * 提示: 使用 sorted, limit
     * @param products 产品列表
     * @param n 要获取的产品数量
     * @return 前N个最贵的产品列表
     */
    static List<Product> getTopNExpensiveProducts(List<Product> products, int n) {
        // TODO: 使用 sorted 按价格降序排列,然后使用 limit 限制数量
        return null;
    }

    /**
     * 题干 9: 检查是否存在价格超过指定金额的产品
     * 任务: 判断产品列表中是否有至少一个产品的价格超过指定金额。
     * 提示: 使用 anyMatch
     * @param products 产品列表
     * @param price 价格阈值
     * @return 如果存在则返回true,否则false
     */
    static boolean hasProductsAbovePrice(List<Product> products, double price) {
        // TODO: 使用 anyMatch 检查是否有产品价格超过指定金额
        return false;
    }

    /**
     * 题干 10: 检查是否所有产品都有库存
     * 任务: 判断所有产品的库存量是否都大于0。
     * 提示: 使用 allMatch
     * @param products 产品列表
     * @return 如果所有产品都有库存则返回true,否则false
     */
    static boolean allProductsInStock(List<Product> products) {
        // TODO: 使用 allMatch 检查所有产品库存是否都大于0
        return false;
    }

    /**
     * 题干 11: 找到第一个价格超过指定金额的产品
     * 任务: 返回第一个价格超过指定金额的产品。
     * 提示: 使用 filter, findFirst
     * @param products 产品列表
     * @param price 价格阈值
     * @return 包含第一个符合条件产品的Optional
     */
    static Optional<Product> findFirstProductAbovePrice(List<Product> products, double price) {
        // TODO: 先filter筛选价格超过阈值的产品,然后使用findFirst找到第一个
        return Optional.empty();
    }

    /**
     * 题干 12: 将所有产品名称用指定分隔符连接
     * 任务: 将所有产品的名称用指定的分隔符连接成一个字符串。
     * 提示: 使用 map, collect(Collectors.joining())
     * @param products 产品列表
     * @param delimiter 分隔符
     * @return 连接后的字符串
     */
    static String joinProductNames(List<Product> products, String delimiter) {
        // TODO: 使用map提取产品名称,然后用Collectors.joining连接
        return "";
    }

    /**
     * 题干 13: 获取所有唯一价格并排序
     * 任务: 获取所有产品的唯一价格,并按从低到高排序。
     * 提示: 使用 map, distinct, sorted
     * @param products 产品列表
     * @return 排序后的唯一价格列表
     */
    static List<Double> getUniquePricesSorted(List<Product> products) {
        // TODO: map提取价格,distinct去重,sorted排序
        return null;
    }

    /**
     * 题干 14: 计算产品总数
     * 任务: 统计产品列表中的产品总数。
     * 提示: 使用 count
     * @param products 产品列表
     * @return 产品总数
     */
    static long getTotalProductCount(List<Product> products) {
        // TODO: 使用count统计产品数量
        return 0;
    }

    // =================================================================
    // ====================== 高级练习 (复杂操作) =======================
    // =================================================================

    /**
     * 题干 15: 获取库存的统计信息
     * 任务: 获取所有产品库存的统计信息(总和、平均值、最大值、最小值、数量)。
     * 提示: 使用 collect(Collectors.summarizingInt())
     * @param products 产品列表
     * @return 库存的统计信息
     */
    static IntSummaryStatistics getStockStatistics(List<Product> products) {
        // TODO: 使用Collectors.summarizingInt获取库存统计信息
        return null;
    }

    /**
     * 题干 16: 按类别统计总库存
     * 任务: 计算每个类别的总库存量。
     * 提示: 使用 collect(Collectors.groupingBy + Collectors.summingInt)
     * @param products 产品列表
     * @return 每个类别的总库存映射
     */
    static Map<String, Integer> getCategoryStockMap(List<Product> products) {
        // TODO: 按类别分组,然后对每组的库存求和
        return null;
    }

    /**
     * 题干 17: 按是否有库存分区
     * 任务: 将产品按是否有库存分为两个区:有库存的和无库存的。
     * 提示: 使用 collect(Collectors.partitioningBy())
     * @param products 产品列表
     * @return 分区结果,key为true表示有库存,false表示无库存
     */
    static Map<Boolean, List<Product>> partitionByStock(List<Product> products) {
        // TODO: 使用partitioningBy按库存是否大于0进行分区
        return null;
    }

    /**
     * 题干 18: 获取产品名称及其长度的映射
     * 任务: 创建一个映射,key是产品名称,value是名称的长度。
     * 提示: 使用 collect(Collectors.toMap())
     * @param products 产品列表
     * @return 产品名称到长度的映射
     */
    static Map<String, Integer> getProductNameLengths(List<Product> products) {
        // TODO: 使用toMap,key为产品名称,value为名称长度
        return null;
    }

    /**
     * 题干 19: 扁平化操作 - 获取所有产品名称的字符流
     * 任务: 将所有产品名称展开为字符流。
     * 提示: 使用 flatMap, chars(), mapToObj
     * @param products 产品列表
     * @return 所有产品名称字符的流
     */
    static Stream<Character> flatMapToCharacters(List<Product> products) {
        // TODO: 先map到产品名称,再flatMap到字符流
        return Stream.empty();
    }

    /**
     * 题干 20: 跳过前N个产品,取接下来M个产品的名称
     * 任务: 跳过前N个产品,然后取接下来M个产品的名称。
     * 提示: 使用 skip, limit, map
     * @param products 产品列表
     * @param skip 要跳过的数量
     * @param take 要取的数量
     * @return 指定范围的产品名称列表
     */
    static List<String> skipAndTakeProductNames(List<Product> products, int skip, int take) {
        // TODO: 使用skip跳过指定数量,limit限制数量,map提取名称
        return null;
    }

    /**
     * 题干 21: 统计价格在指定范围内的产品数量
     * 任务: 统计价格在[minPrice, maxPrice]范围内的产品数量。
     * 提示: 使用 filter, count
     * @param products 产品列表
     * @param minPrice 最低价格
     * @param maxPrice 最高价格
     * @return 符合价格范围的产品数量
     */
    static long countProductsInPriceRange(List<Product> products, double minPrice, double maxPrice) {
        // TODO: filter筛选价格范围内的产品,然后count统计数量
        return 0;
    }

    // =================================================================
    // ====================== 额外挑战练习 =============================
    // =================================================================

    /**
     * 挑战题 1: 创建数字流并进行操作
     * 任务: 计算指定范围内所有偶数的和。
     * 提示: 使用 IntStream.range, filter, sum
     * @param start 起始数字(包含)
     * @param end 结束数字(不包含)
     * @return 范围内偶数的和
     */
    static int sumOfEvenNumbersInRange(int start, int end) {
        // TODO: 使用IntStream.range创建数字流,filter筛选偶数,sum求和
        return 0;
    }

    /**
     * 挑战题 2: 使用 reduce 操作计算产品总价值
     * 任务: 使用reduce操作而不是sum来计算所有产品的总库存价值。
     * 提示: 使用 map, reduce
     * @param products 产品列表
     * @return 总库存价值
     */
    static double calculateTotalValueUsingReduce(List<Product> products) {
        // TODO: map到库存价值,然后使用reduce求和
        return 0.0;
    }

    /**
     * 挑战题 3: 找到每个类别中最便宜的产品
     * 任务: 对于每个类别,找出该类别中价格最低的产品。
     * 提示: 使用 collect(Collectors.groupingBy + Collectors.minBy)
     * @param products 产品列表
     * @return 每个类别最便宜产品的映射
     */
    static Map<String, Optional<Product>> getCheapestProductByCategory(List<Product> products) {
        // TODO: 按类别分组,每组内使用minBy找最便宜的产品
        return null;
    }

    /**
     * 挑战题 4: 使用 peek 进行调试输出
     * 任务: 找出所有价格超过阈值的产品,并在过程中输出调试信息。
     * 提示: 使用 filter, peek, collect
     * @param products 产品列表
     * @param threshold 价格阈值
     * @return 价格超过阈值的产品列表
     */
    static List<Product> getExpensiveProductsWithLogging(List<Product> products, double threshold) {
        // TODO: filter筛选贵重商品,使用peek输出调试信息
        return null;
    }

    /**
     * 挑战题 5: 使用 noneMatch 检查负价格
     * 任务: 检查是否没有任何产品的价格为负数。
     * 提示: 使用 noneMatch
     * @param products 产品列表
     * @return 如果没有负价格产品返回true,否则false
     */
    static boolean hasNoNegativePriceProducts(List<Product> products) {
        // TODO: 使用noneMatch检查是否没有负价格产品
        return false;
    }

    /**
     * 挑战题 6: 获取类别中产品数量超过N的类别列表
     * 任务: 找出产品数量超过指定数量的所有类别。
     * 提示: 使用 collect(groupingBy + counting), filter, map
     * @param products 产品列表
     * @param minCount 最小产品数量
     * @return 产品数量超过阈值的类别列表
     */
    static List<String> getCategoriesWithMinProducts(List<Product> products, long minCount) {
        // TODO: 先按类别分组并统计数量,然后筛选出数量超过阈值的类别
        return null;
    }

    /**
     * 挑战题 7: 获取价格第二高的产品
     * 任务: 找到价格第二高的产品。
     * 提示: 使用 sorted, skip, findFirst
     * @param products 产品列表
     * @return 价格第二高的产品Optional
     */
    static Optional<Product> getSecondMostExpensiveProduct(List<Product> products) {
        // TODO: 按价格降序排列,跳过第一个,取第二个
        return Optional.empty();
    }

    /**
     * 挑战题 8: 计算每个类别的平均库存
     * 任务: 计算每个产品类别的平均库存量。
     * 提示: 使用 collect(groupingBy + averagingInt)
     * @param products 产品列表
     * @return 每个类别的平均库存映射
     */
    static Map<String, Double> getAverageStockByCategory(List<Product> products) {
        // TODO: 按类别分组,计算每组的平均库存
        return null;
    }
}

/**
 * 产品类 (辅助类)
 */
class Product {
    private String productId;
    private String name;
    private String category;
    private double price;
    private int stock;

    public Product(String productId, String name, String category, double price, int stock) {
        this.productId = productId;
        this.name = name;
        this.category = category;
        this.price = price;
        this.stock = stock;
    }

    // Getters
    public String getProductId() { return productId; }
    public String getName() { return name; }
    public String getCategory() { return category; }
    public double getPrice() { return price; }
    public int getStock() { return stock; }

    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                ", category='" + category + '\'' +
                ", price=" + price +
                ", stock=" + stock +
                '}';
    }
}

答案

package org.example.a;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * Java Stream 练习 - 完整版
 *
 * 包含原有题目的解答和更多覆盖Stream API的练习题
 */
public class StreamPractice {

    public static void main(String[] args) {
        // --- 测试数据 ---
        ArrayList<Product> products = new ArrayList<>();
        products.add(new Product("P1", "笔记本电脑", "电子产品", 1200.0, 10));
        products.add(new Product("P2", "鼠标", "电子产品", 25.0, 150));
        products.add(new Product("P3", "机械键盘", "电子产品", 75.0, 80));
        products.add(new Product("P4", "T恤", "服装", 20.0, 200));
        products.add(new Product("P5", "牛仔裤", "服装", 80.0, 70));
        products.add(new Product("P6", "百年孤独", "图书", 15.0, 120));
        products.add(new Product("P7", "Java编程思想", "图书", 90.0, 50));
        products.add(new Product("P8", "显示器", "电子产品", 300.0, 40));
        products.add(new Product("P9", "运动鞋", "服装", 120.0, 0)); // 库存为0
        products.add(new Product("P10", "Python入门", "图书", 45.0, 30));
        products.add(new Product("P11", "智能手表", "电子产品", 800.0, 25));

        // --- 测试所有方法 ---
        System.out.println("=== 基础练习 ===");
        System.out.println("1. 电子产品: " + findProductsByCategory(products, "电子产品"));
        System.out.println("2. 总库存价值: " + calculateTotalInventoryValue(products));
        System.out.println("3. 按类别分组: " + groupProductsByCategory(products));
        System.out.println("4. 最贵的产品: " + findMostExpensiveProduct(products));
        System.out.println("5. 缺货产品: " + getOutOfStockProductNames(products));
        System.out.println("6. 图书平均价格: " + getAveragePriceByCategory(products, "图书"));
        System.out.println("7. 产品ID映射: " + convertListToProductMap(products).keySet());

        System.out.println("\n=== 进阶练习 ===");
        System.out.println("8. 前3个最贵的产品: " + getTopNExpensiveProducts(products, 3));
        System.out.println("9. 是否有贵于500的产品: " + hasProductsAbovePrice(products, 500.0));
        System.out.println("10. 是否所有产品都有库存: " + allProductsInStock(products));
        System.out.println("11. 第一个超过100元的产品: " + findFirstProductAbovePrice(products, 100.0));
        System.out.println("12. 产品名称拼接: " + joinProductNames(products, ", "));
        System.out.println("13. 价格去重排序: " + getUniquePricesSorted(products));
        System.out.println("14. 产品总数: " + getTotalProductCount(products));

        System.out.println("\n=== 高级练习 ===");
        System.out.println("15. 库存统计: " + getStockStatistics(products));
        System.out.println("16. 类别库存映射: " + getCategoryStockMap(products));
        System.out.println("17. 分区(有库存vs无库存): " + partitionByStock(products).keySet());
        System.out.println("18. 产品名称长度映射: " + getProductNameLengths(products));
        System.out.println("19. 扁平化所有字符: " + flatMapToCharacters(products).limit(20).collect(Collectors.toList()));
        System.out.println("20. 跳过前5个产品的名称: " + skipAndTakeProductNames(products, 5, 3));
        System.out.println("21. 价格范围产品数量: " + countProductsInPriceRange(products, 20.0, 100.0));
    }

    // =================================================================
    // ====================== 基础练习 (原题解答) =======================
    // =================================================================

    /**
     * 题干 1: 按类别查找产品
     */
    static List<Product> findProductsByCategory(List<Product> products, String category) {
        return products.stream()
                .filter(product -> product.getCategory().equals(category))
                .collect(Collectors.toList());
    }

    /**
     * 题干 2: 计算总库存价值
     */
    static double calculateTotalInventoryValue(List<Product> products) {
        return products.stream()
                .mapToDouble(product -> product.getPrice() * product.getStock())
                .sum();
    }

    /**
     * 题干 3: 按类别对产品进行分组
     */
    static Map<String, List<Product>> groupProductsByCategory(List<Product> products) {
        return products.stream()
                .collect(Collectors.groupingBy(Product::getCategory));
    }

    /**
     * 题干 4: 查找最贵的产品
     */
    static Optional<Product> findMostExpensiveProduct(List<Product> products) {
        return products.stream()
                .max(Comparator.comparing(Product::getPrice));
    }

    /**
     * 题干 5: 获取所有缺货(库存为0)的产品名称
     */
    static List<String> getOutOfStockProductNames(List<Product> products) {
        return products.stream()
                .filter(product -> product.getStock() == 0)
                .map(Product::getName)
                .collect(Collectors.toList());
    }

    /**
     * 题干 6: 计算特定类别产品的平均价格
     */
    static double getAveragePriceByCategory(List<Product> products, String category) {
        return products.stream()
                .filter(product -> product.getCategory().equals(category))
                .collect(Collectors.averagingDouble(Product::getPrice));
    }

    /**
     * 题干 7: 将产品列表转换为 Map
     */
    static Map<String, Product> convertListToProductMap(List<Product> products) {
        return products.stream()
                .collect(Collectors.toMap(Product::getProductId, Function.identity()));
    }

    // =================================================================
    // ====================== 进阶练习 (新增题目) =======================
    // =================================================================

    /**
     * 题干 8: 获取前N个最贵的产品
     * 使用: sorted, limit
     */
    static List<Product> getTopNExpensiveProducts(List<Product> products, int n) {
        return products.stream()
                .sorted(Comparator.comparing(Product::getPrice).reversed())
                .limit(n)
                .collect(Collectors.toList());
    }

    /**
     * 题干 9: 检查是否存在价格超过指定金额的产品
     * 使用: anyMatch
     */
    static boolean hasProductsAbovePrice(List<Product> products, double price) {
        return products.stream()
                .anyMatch(product -> product.getPrice() > price);
    }

    /**
     * 题干 10: 检查是否所有产品都有库存
     * 使用: allMatch
     */
    static boolean allProductsInStock(List<Product> products) {
        return products.stream()
                .allMatch(product -> product.getStock() > 0);
    }

    /**
     * 题干 11: 找到第一个价格超过指定金额的产品
     * 使用: filter, findFirst
     */
    static Optional<Product> findFirstProductAbovePrice(List<Product> products, double price) {
        return products.stream()
                .filter(product -> product.getPrice() > price)
                .findFirst();
    }

    /**
     * 题干 12: 将所有产品名称用指定分隔符连接
     * 使用: map, collect(Collectors.joining)
     */
    static String joinProductNames(List<Product> products, String delimiter) {
        return products.stream()
                .map(Product::getName)
                .collect(Collectors.joining(delimiter));
    }

    /**
     * 题干 13: 获取所有唯一价格并排序
     * 使用: map, distinct, sorted
     */
    static List<Double> getUniquePricesSorted(List<Product> products) {
        return products.stream()
                .map(Product::getPrice)
                .distinct()
                .sorted()
                .collect(Collectors.toList());
    }

    /**
     * 题干 14: 计算产品总数
     * 使用: count
     */
    static long getTotalProductCount(List<Product> products) {
        return products.stream()
                .count();
    }

    // =================================================================
    // ====================== 高级练习 (复杂操作) =======================
    // =================================================================

    /**
     * 题干 15: 获取库存的统计信息
     * 使用: collect, Collectors.summarizingInt
     */
    static IntSummaryStatistics getStockStatistics(List<Product> products) {
        return products.stream()
                .collect(Collectors.summarizingInt(Product::getStock));
    }

    /**
     * 题干 16: 按类别统计总库存
     * 使用: collect, Collectors.groupingBy, Collectors.summingInt
     */
    static Map<String, Integer> getCategoryStockMap(List<Product> products) {
        return products.stream()
                .collect(Collectors.groupingBy(
                        Product::getCategory,
                        Collectors.summingInt(Product::getStock)
                ));
    }

    /**
     * 题干 17: 按是否有库存分区
     * 使用: collect, Collectors.partitioningBy
     */
    static Map<Boolean, List<Product>> partitionByStock(List<Product> products) {
        return products.stream()
                .collect(Collectors.partitioningBy(product -> product.getStock() > 0));
    }

    /**
     * 题干 18: 获取产品名称及其长度的映射
     * 使用: collect, Collectors.toMap, String::length
     */
    static Map<String, Integer> getProductNameLengths(List<Product> products) {
        return products.stream()
                .collect(Collectors.toMap(
                        Product::getName,
                        product -> product.getName().length()
                ));
    }

    /**
     * 题干 19: 扁平化操作 - 获取所有产品名称的字符流
     * 使用: flatMap
     */
    static Stream<Character> flatMapToCharacters(List<Product> products) {
        return products.stream()
                .map(Product::getName)
                .flatMap(name -> name.chars().mapToObj(c -> (char) c));
    }

    /**
     * 题干 20: 跳过前N个产品,取接下来M个产品的名称
     * 使用: skip, limit, map
     */
    static List<String> skipAndTakeProductNames(List<Product> products, int skip, int take) {
        return products.stream()
                .skip(skip)
                .limit(take)
                .map(Product::getName)
                .collect(Collectors.toList());
    }

    /**
     * 题干 21: 统计价格在指定范围内的产品数量
     * 使用: filter, count
     */
    static long countProductsInPriceRange(List<Product> products, double minPrice, double maxPrice) {
        return products.stream()
                .filter(product -> product.getPrice() >= minPrice && product.getPrice() <= maxPrice)
                .count();
    }

    // =================================================================
    // ====================== 额外挑战练习 =============================
    // =================================================================

    /**
     * 挑战题 1: 创建数字流并进行操作
     * 使用: IntStream, range, filter, sum
     */
    static int sumOfEvenNumbersInRange(int start, int end) {
        return IntStream.range(start, end)
                .filter(n -> n % 2 == 0)
                .sum();
    }

    /**
     * 挑战题 2: 使用 reduce 操作计算产品总价值
     * 使用: map, reduce
     */
    static double calculateTotalValueUsingReduce(List<Product> products) {
        return products.stream()
                .map(product -> product.getPrice() * product.getStock())
                .reduce(0.0, Double::sum);
    }

    /**
     * 挑战题 3: 找到每个类别中最便宜的产品
     * 使用: collect, Collectors.groupingBy, Collectors.minBy
     */
    static Map<String, Optional<Product>> getCheapestProductByCategory(List<Product> products) {
        return products.stream()
                .collect(Collectors.groupingBy(
                        Product::getCategory,
                        Collectors.minBy(Comparator.comparing(Product::getPrice))
                ));
    }

    /**
     * 挑战题 4: 使用 peek 进行调试输出
     * 使用: filter, peek, collect
     */
    static List<Product> getExpensiveProductsWithLogging(List<Product> products, double threshold) {
        return products.stream()
                .filter(product -> product.getPrice() > threshold)
                .peek(product -> System.out.println("找到贵重商品: " + product.getName()))
                .collect(Collectors.toList());
    }

    /**
     * 挑战题 5: 使用 noneMatch
     * 使用: noneMatch
     */
    static boolean hasNoNegativePriceProducts(List<Product> products) {
        return products.stream()
                .noneMatch(product -> product.getPrice() < 0);
    }
}

/**
 * 产品类 (辅助类)
 */
class Product {
    private String productId;
    private String name;
    private String category;
    private double price;
    private int stock;

    public Product(String productId, String name, String category, double price, int stock) {
        this.productId = productId;
        this.name = name;
        this.category = category;
        this.price = price;
        this.stock = stock;
    }

    // Getters
    public String getProductId() { return productId; }
    public String getName() { return name; }
    public String getCategory() { return category; }
    public double getPrice() { return price; }
    public int getStock() { return stock; }

    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                ", category='" + category + '\'' +
                ", price=" + price +
                ", stock=" + stock +
                '}';
    }
}