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
相关产品推荐
相关产品推荐

