You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java 8 StreamAPI优化实现带折扣的图书总价计算?

问题分析与优化方案

原代码的核心问题

你的代码存在两个关键问题:

  • 多次遍历集合:前后三次调用books.stream(),相当于遍历了三次图书列表,大数据量场景下效率偏低。
  • 逻辑错误:books.stream().skip(2)是跳过原集合的前2个元素,而非排序后的最贵两本。如果原列表不是按价格从高到低排列,剩余价格的计算会完全错误,直接导致最终总价出错。

关于“是否必须排序”的疑问

要找出最贵的两本图书,不一定需要对整个列表排序:

  • 全排序的时间复杂度是O(n logn),但我们只需要前两大的值,完全可以通过一次遍历记录最大的两个价格,时间复杂度O(n),效率更高。
  • 如果偏好Stream API,排序是最直观的实现方式,但要注意只排一次,避免重复操作。

优化实现方式

方式一:一次遍历完成所有计算(最优效率)

这种方式仅遍历一次图书列表,同时计算总价、记录最贵的两个价格,适合大数据量场景:

public int getTotalPrice(ArrayList<Book> books) {
    if (books.size() < 5) {
        return books.stream().mapToInt(Book::getPrice).sum();
    }

    int total = 0;
    int firstMax = 0;
    int secondMax = 0;

    for (Book book : books) {
        int price = book.getPrice();
        total += price;

        // 更新最贵的两个价格
        if (price > firstMax) {
            secondMax = firstMax;
            firstMax = price;
        } else if (price > secondMax) {
            secondMax = price;
        }
    }

    if (total >= this.minimumPrice) {
        // 总价减去最贵两本的半价(等价于原价总和 - (firstMax + secondMax)/2)
        return total - (firstMax + secondMax) / 2;
    }
    return total;
}

方式二:基于Stream的优化(更简洁,避免多次遍历)

如果偏好Stream API,可以只排序一次后拆分处理,避免重复遍历:

public int getTotalPrice(ArrayList<Book> books) {
    int size = books.size();
    if (size < 5) {
        return books.stream().mapToInt(Book::getPrice).sum();
    }

    int total = books.stream().mapToInt(Book::getPrice).sum();
    if (total < this.minimumPrice) {
        return total;
    }

    // 仅排序一次,获取降序排列的价格列表
    List<Integer> sortedPrices = books.stream()
            .mapToInt(Book::getPrice)
            .boxed()
            .sorted(Collections.reverseOrder())
            .collect(Collectors.toList());

    // 计算折扣后总价:前两本半价 + 剩余图书原价
    int discountedSum = (int) (sortedPrices.get(0) * 0.5 + sortedPrices.get(1) * 0.5);
    int restSum = sortedPrices.stream().skip(2).mapToInt(Integer::intValue).sum();
    return discountedSum + restSum;
}

补充说明

  • 方式一效率更高,无排序开销;方式二更简洁,适合数据量不大的场景。
  • 注意价格为int类型时,半价计算会丢失小数部分(如3元半价转int为1元),这和你原代码逻辑一致,若需保留精度可改用double类型返回。

内容的提问来源于stack exchange,提问作者satanmoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:14:51