MST
星途 面试题库

面试题:Java Stream collect自定义Collector实现复杂数据统计

在Java中,需要对一个包含商品信息的List<Product>进行统计。Product类有name(商品名)、price(价格)、category(类别)属性。请自定义一个Collector,使用Stream的collect方法实现按商品类别分组,统计每个类别中价格最高的商品名称以及该类别所有商品的总价格,详细写出Collector的实现和使用collect方法的完整代码。
21.6万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

class Product {
    private String name;
    private double price;
    private String category;

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

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public String getCategory() {
        return category;
    }
}

public class ProductStatistics {
    public static void main(String[] args) {
        List<Product> products = Arrays.asList(
                new Product("Product1", 10.0, "Category1"),
                new Product("Product2", 15.0, "Category1"),
                new Product("Product3", 20.0, "Category2"),
                new Product("Product4", 25.0, "Category2")
        );

        Collector<Product, Map<String, ProductPriceInfo>, Map<String, ProductPriceInfo>> customCollector =
                Collector.of(
                        () -> new HashMap<>(),
                        (map, product) -> {
                            ProductPriceInfo info = map.computeIfAbsent(product.getCategory(), k -> new ProductPriceInfo());
                            if (product.getPrice() > info.maxPriceProduct.getPrice()) {
                                info.maxPriceProduct = product;
                            }
                            info.totalPrice += product.getPrice();
                        },
                        (map1, map2) -> {
                            map2.forEach((category, info) -> {
                                ProductPriceInfo existingInfo = map1.computeIfAbsent(category, k -> new ProductPriceInfo());
                                if (info.maxPriceProduct.getPrice() > existingInfo.maxPriceProduct.getPrice()) {
                                    existingInfo.maxPriceProduct = info.maxPriceProduct;
                                }
                                existingInfo.totalPrice += info.totalPrice;
                            });
                            return map1;
                        },
                        Collector.Characteristics.IDENTITY_FINISH
                );

        Map<String, ProductPriceInfo> result = products.stream().collect(customCollector);

        result.forEach((category, info) -> {
            System.out.println("Category: " + category);
            System.out.println("Highest price product name: " + info.maxPriceProduct.getName());
            System.out.println("Total price: " + info.totalPrice);
            System.out.println();
        });
    }

    static class ProductPriceInfo {
        private Product maxPriceProduct;
        private double totalPrice;

        ProductPriceInfo() {
            this.maxPriceProduct = new Product("", 0, "");
            this.totalPrice = 0;
        }
    }
}

代码解释

  1. Product类:定义了商品的基本信息,包括名称、价格和类别。
  2. ProductPriceInfo类:用于存储每个类别中的价格最高的商品信息以及该类别所有商品的总价格。
  3. 自定义Collector
    • Collector.of方法创建了一个自定义的Collector。
    • Supplier:创建一个空的HashMap,用于存储每个类别的统计信息。
    • Accumulator:遍历Product列表,更新每个类别中的最高价格商品和总价格。
    • Combiner:用于合并两个Map,当流并行处理时会用到。
    • Characteristics.IDENTITY_FINISH:表示收集器的最终结果就是累加器的结果,不需要额外转换。
  4. 使用collect方法:将Product列表通过stream()方法转换为流,并使用自定义的collector进行收集,最后打印出每个类别的统计信息。