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

Java私有工具方法重构:合并相似足球赛事统计方法

解决方案:合并重复的进球统计方法

当然可以用布尔参数来区分进球/失球统计,但这种方式虽然能减少代码重复,却可能让调用方的代码可读性下降(谁能一眼记住true是进球还是失球呢?)。下面先展示布尔参数的实现,再给你推荐更清晰、更易维护的优化方案。

1. 布尔参数实现方案

直接通过一个boolean参数切换统计逻辑,合并后的方法如下:

private Integer calculateTeamGoals(final LeagueTable leagueTable, final Team team, boolean isScored) {
    // 统计球队作为主场时的对应进球数
    int homeGoals = leagueTable.getAllResults().stream()
            .filter(result -> result.getHomeTeam().equals(team))
            .map(Result::getOutcome)
            .mapToInt(outcome -> isScored ? outcome.getGoalsScoredByHomeTeam() : outcome.getGoalsScoredByAwayTeam())
            .sum();
    
    // 统计球队作为客场时的对应进球数
    int awayGoals = leagueTable.getAllResults().stream()
            .filter(result -> result.getAwayTeam().equals(team))
            .map(Result::getOutcome)
            .mapToInt(outcome -> isScored ? outcome.getGoalsScoredByAwayTeam() : outcome.getGoalsScoredByHomeTeam())
            .sum();
    
    return homeGoals + awayGoals;
}

调用时只需传入true(统计进球)或false(统计失球):

// 统计球队进球数
int scored = calculateTeamGoals(leagueTable, myTeam, true);
// 统计球队失球数
int against = calculateTeamGoals(leagueTable, myTeam, false);

2. 更优雅的枚举方案(推荐)

布尔参数的最大问题是语义模糊,调用者需要查看方法注释才能理解参数含义。用枚举明确定义统计类型,既能消除重复代码,又能保证代码可读性和类型安全:

第一步:定义统计类型枚举

private enum GoalStatType {
    GOALS_SCORED,
    GOALS_AGAINST
}

第二步:实现合并后的方法

private Integer calculateTeamGoals(final LeagueTable leagueTable, final Team team, GoalStatType statType) {
    return leagueTable.getAllResults().stream()
            .mapToInt(result -> {
                if (result.getHomeTeam().equals(team)) {
                    // 球队是主场时,根据统计类型取对应数值
                    return switch (statType) {
                        case GOALS_SCORED -> result.getOutcome().getGoalsScoredByHomeTeam();
                        case GOALS_AGAINST -> result.getOutcome().getGoalsScoredByAwayTeam();
                    };
                } else if (result.getAwayTeam().equals(team)) {
                    // 球队是客场时,根据统计类型取对应数值
                    return switch (statType) {
                        case GOALS_SCORED -> result.getOutcome().getGoalsScoredByAwayTeam();
                        case GOALS_AGAINST -> result.getOutcome().getGoalsScoredByHomeTeam();
                    };
                }
                // 该结果与当前球队无关,贡献0球
                return 0;
            })
            .sum();
}

调用方式

int scored = calculateTeamGoals(leagueTable, myTeam, GoalStatType.GOALS_SCORED);
int against = calculateTeamGoals(leagueTable, myTeam, GoalStatType.GOALS_AGAINST);

这个方案的优势很明显:

  • 语义清晰,调用方一眼就能看懂要统计的类型
  • 编译时就能检查参数合法性,避免传错布尔值的低级错误
  • 只遍历一次结果集,比原代码的两次遍历性能更优

3. 额外优化:提取辅助函数(可选)

如果想让方法内的逻辑更简洁,还可以把“根据球队角色和统计类型取进球数”的逻辑提取成一个小辅助函数:

private int getGoalCountForTeamRole(Outcome outcome, boolean isHomeTeam, GoalStatType statType) {
    if (isHomeTeam) {
        return statType == GoalStatType.GOALS_SCORED ? outcome.getGoalsScoredByHomeTeam() : outcome.getGoalsScoredByAwayTeam();
    } else {
        return statType == GoalStatType.GOALS_SCORED ? outcome.getGoalsScoredByAwayTeam() : outcome.getGoalsScoredByHomeTeam();
    }
}

这样主方法会更清爽:

private Integer calculateTeamGoals(final LeagueTable leagueTable, final Team team, GoalStatType statType) {
    return leagueTable.getAllResults().stream()
            .mapToInt(result -> {
                boolean isHome = result.getHomeTeam().equals(team);
                boolean isAway = result.getAwayTeam().equals(team);
                if (!isHome && !isAway) return 0;
                
                return getGoalCountForTeamRole(result.getOutcome(), isHome, statType);
            })
            .sum();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 22:27:29