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

如何基于两层嵌套属性对List去重并优化Java处理逻辑?

问题:优化嵌套属性的列表处理逻辑

我不确定该如何称呼这种位于两层嵌套结构中的属性。

假设我们有一个List<FruitColor>,其中Fruit和Color是两个实体(均为示例实体)。一种fruit可以对应多种color,一种color也可以对应多种fruit。

实体代码如下:

public class FruitColor {
    private String fruitColorId;
    private Fruit fruit;
    private Color color;
    private int ripe; //1到3,1代表未成熟,2代表正常成熟,3代表完全成熟

    // 更多属性、getter等方法
}

public class Fruit {
    private String fruitId;
    private String fruitName;

    // getter等方法
}

public class Color {
    private String colorId;
    private String colorName;

    // getter等方法
}

我设想的处理步骤如下:

  • 基于fruitName筛选所有重复条目
  • 从两个“重复项”中选择保留一个。这里的“重复项”指仅fruitName相同但color不同的条目。选择规则由季节/时间过渡指标systemTransition(取值范围为0到100的double类型属性)决定。
  • 移除另一个“重复项”。
  • 若存在重复项,将果实成熟度降低0.5。
  • 设置factorialRipeness,其值为ripe * systemTransition或ripe * (100 - systemTransition),具体取决于季节进度,以50为分界点。
  • 返回包含对应Color的目标FruitColors列表,并按FactorialRipeness排序。

我知道用大量for循环可以实现,但想了解是否有更高效的实现方式。我曾找到一篇关于按属性过滤的资料,但该方案不支持基于嵌套属性(如fruitName)的过滤。

我已编写了可运行的代码示例(使用了不同实体),但想知道是否有可优化的部分。这里的“更高效”指代码更简洁或执行速度更快。后续我会将方法拆分为更小的模块,因无法使用真实实体,部分逻辑可能存在不合理之处,敬请谅解。

现有代码逻辑:

//方法内逻辑
{   
    List<FruitColor> fruitColors = getAllFCs();
    
    //移除不属于指定两种颜色的FruitColor
    fruitColors.removeIf(fc -> fc.getColor().getColorId() != presentColor.getColor().getColorId()
            && fc.getColor().getColorId() != futureColor.getColor().getColorId());
    List<FruitColor> suggestedFruits = new ArrayList<>();

    //systemTransition代表季节/时间进度(0到100),100表示果实应完全成熟并对应目标颜色
    //若进度低于50,应选择当前颜色(成熟度较低的颜色)
    boolean getPresentColorFruit = systemTransition < 50;

    // ---&gt;我希望优化这段for-if-if-else-elseif-if-else逻辑 &lt;---
    for (FruitColor fruitColor : fruitColors) {
        //首先检查重复的FruitColor
        List<FruitColor> sameNameFruits = fruitColors.stream()
                .filter(fc -> fc.getFruit().getName().equals(itemColor.getFruit().getName()))
                .collect(Collectors.toList());
                
        //若该果实仅存在一个条目,且未添加至结果列表,则按规则设置成熟度后添加
        //factorialRipeness为“真实”成熟度
        if (sameNameFruits.size() == 1 && !suggestedFruits.stream().anyMatch(fc -> fc.getFruit().getName().equals(sameNameFruits.get(0).getFruit().getName()))) {
            FruitColor onlyOne = sameNameFruits.get(0);
            if (onlyOne.getColor().getColorId() == presentColor.getColor().getColorId()) {
                onlyOne.setFactorialRipeness(onlyOne.getRipeness() * systemTransition);
            } else {
                onlyOne.setFactorialRipeness(onlyOne.getRipeness() * (100 - systemTransition));
            }
            suggestedFruits.add(onlyOne);
          //若存在多个条目,需降低成熟度(此逻辑在示例实体中可能不合理,敬请谅解)
        } else if(!suggestedFruits.stream().anyMatch(fc -> fc.getFruit().getName().equals(sameNameFruits.get(0).getFruit().getName()))){
            if (getPresentColorFruit) {
                FruitColor fcWithPresentColor = sameNameFruits.stream()
                        .filter(fc -> fc.getColor().getColorId() == presentColor.getColor().getColorId()).findFirst()
                        .get();
                fcWithPresentColor.setFactorialRipeness((fcWithPresentColor.getRipeness() - 0.5) * systemTransition);
                suggestedFruits.add(fcWithPresentColor);
            } else {
                FruitColor fcWithFutureColor = sameNameFruits.stream()
                        .filter(fc -> fc.getColor().getColorId() == futureColor.getColor().getColorId()).findFirst()
                        .get();
                //此逻辑也可能不合理,若未选择当前颜色,则需用100-systemTransition进行计算
                fcWithFutureColor.setFactorialRipeness((fcWithFutureColor.getRipeness() - 0.5) * (100 - systemTransition)); 
                suggestedFruits.add(fcWithFutureColor);
            }
        }
    }
    //按“真实”成熟度从低到高排序
    Collections.sort(suggestedFruits, new FruitColorRipenessComparator());
    return suggestedFruits;
}

/**
 * @source https://stackoverflow.com/questions/2839137/how-to-use-comparator-in-java-to-sort
 */
public class FruitColorRipenessComparator implements Comparator<FruitColor> {
    @Override
    public int compare(FruitColor a, FruitColor b){
        return a.getFactorialRipeness() < b.getFactorialRipeness() ? -1 : a.getFactorialRipeness() == b.getFactorialRipeness() ? 0 : 1;
    }
}
优化方案

1. 核心优化思路

  • 先按fruitName分组,避免循环中重复遍历整个列表
  • 用HashSet记录已处理的果实名称,替代低效的stream判断
  • 拆分逻辑为独立方法,提高代码可读性和可维护性

优化后的代码示例

// 方法内逻辑
{
    List<FruitColor> fruitColors = getAllFCs();
    String presentColorId = presentColor.getColor().getColorId();
    String futureColorId = futureColor.getColor().getColorId();

    // 过滤仅保留指定两种颜色的条目
    List<FruitColor> filtered = fruitColors.stream()
            .filter(fc -> presentColorId.equals(fc.getColor().getColorId()) || futureColorId.equals(fc.getColor().getColorId()))
            .collect(Collectors.toList());

    // 按fruitName分组,一次操作完成所有分组
    Map<String, List<FruitColor>> groupedByFruitName = filtered.stream()
            .collect(Collectors.groupingBy(fc -> fc.getFruit().getFruitName()));

    boolean choosePresent = systemTransition < 50;
    Set<String> processedFruits = new HashSet<>();
    List<FruitColor> suggestedFruits = new ArrayList<>();

    for (Map.Entry<String, List<FruitColor>> entry : groupedByFruitName.entrySet()) {
        String fruitName = entry.getKey();
        if (processedFruits.contains(fruitName)) {
            continue;
        }
        processedFruits.add(fruitName);

        List<FruitColor> sameNameList = entry.getValue();
        // 选择要保留的条目
        FruitColor selected = selectTargetFruit(sameNameList, choosePresent, presentColorId, futureColorId);
        // 计算并设置成熟度
        calculateFactorialRipeness(selected, sameNameList.size() > 1, systemTransition, presentColorId);
        suggestedFruits.add(selected);
    }

    // 用Lambda简化排序逻辑,替代自定义Comparator
    suggestedFruits.sort(Comparator.comparingDouble(FruitColor::getFactorialRipeness));
    return suggestedFruits;
}

// 封装选择目标条目逻辑
private FruitColor selectTargetFruit(List<FruitColor> sameNameList, boolean choosePresent, String presentColorId, String futureColorId) {
    if (sameNameList.size() == 1) {
        return sameNameList.get(0);
    }
    // 按规则筛选目标颜色的条目,添加兜底避免空指针
    return sameNameList.stream()
            .filter(fc -> choosePresent ? presentColorId.equals(fc.getColor().getColorId()) : futureColorId.equals(fc.getColor().getColorId()))
            .findFirst()
            .orElse(sameNameList.get(0));
}

// 封装成熟度计算逻辑
private void calculateFactorialRipeness(FruitColor fruitColor, boolean hasDuplicate, double systemTransition, String presentColorId) {
    double baseRipe = hasDuplicate ? fruitColor.getRipe() - 0.5 : fruitColor.getRipe();
    double multiplier = presentColorId.equals(fruitColor.getColor().getColorId()) ? systemTransition : (100 - systemTransition);
    fruitColor.setFactorialRipeness(baseRipe * multiplier);
}

优化效果说明

  • 性能提升:分组操作仅执行一次,将原O(n²)的时间复杂度降至O(n);HashSet判断已处理果实的时间复杂度为O(1),替代原O(n)的stream判断
  • 代码简洁性:拆分逻辑到独立方法,主流程清晰易懂;用Stream API和Lambda简化过滤、排序逻辑
  • 鲁棒性增强:添加findFirst()的兜底处理,避免空指针异常;提取颜色ID常量,减少重复调用getter

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 07:10:27