英文:
Refactoring a Private Utility Method in Java
问题
我试图重构Java中的两个私有方法,它们本质上是相同的内容。我目前正在对足球平局的几种情况进行一些JUnit测试断言,并编写了一个实用方法,该方法可以流式处理结果,并返回一支队伍进球总数或失球总数。它们非常相似:
private Integer getTeamGoals(final LeagueTable leagueTable, final Team team, boolean scored) {
return leagueTable.getAllResults().stream()
.filter(t -> t.getHomeTeam().equals(team) || t.getAwayTeam().equals(team))
.map(Result::getOutcome)
.map(scored ? Outcome::getGoalsScoredByHomeTeam : Outcome::getGoalsScoredByAwayTeam)
.reduce(0, Integer::sum);
}
英文:
I'm trying to refactor two private methods in Java which are essentially the same thing. I am currently doing some JUnit test assertions on soccer tiebreakers and have written up a utility method which streams through results and brings back total goals scored or conceded by a team. They are very similar:
private Integer getTeamGoalsScored(final LeagueTable leagueTable, final Team team) {
return leagueTable.getAllResults().stream()
.filter(t -> t.getHomeTeam().equals(team))
.map(Result::getOutcome)
.map(Outcome::getGoalsScoredByHomeTeam).reduce(0, Integer::sum) +
leagueTable.getAllResults().stream()
.filter(t -> t.getAwayTeam().equals(team))
.map(Result::getOutcome)
.map(Outcome::getGoalsScoredByAwayTeam).reduce(0, Integer::sum);
}
private Integer getTeamGoalsAgainst(final LeagueTable leagueTable, final Team team) {
return leagueTable.getAllResults().stream()
.filter(t -> t.getHomeTeam().equals(team))
.map(Result::getOutcome)
.map(Outcome::getGoalsScoredByAwayTeam).reduce(0, Integer::sum) +
leagueTable.getAllResults().stream()
.filter(t -> t.getAwayTeam().equals(team))
.map(Result::getOutcome)
.map(Outcome::getGoalsScoredByHomeTeam).reduce(0, Integer::sum);
}
As you can see they are basically boilerplate, I'm wondering how to merge these two to become one method. I'm guessing a boolean for true/false, scored/against?
答案1
得分: 1
你可以提取执行筛选和映射操作的函数,并将它们作为参数传递给这个函数:
private Integer getSum(final LeagueTable leagueTable,
Function<Result, Boolean> filterFun, Function<Outcome, Integer> mapFun
) {
return leagueTable.getAllResults().stream()
.filter(filterFun)
.map(Result::getOutcome)
.map(mapFun).reduce(0, Integer::sum);
}
然后你可以在你的代码中这样使用它:
private Integer getTeamGoalsScored(final LeagueTable leagueTable, final Team team) {
return getSum(leagueTable,
t -> t.getHomeTeam().equals(team), Outcome::getGoalsScoredByHomeTeam) +
getSum(leagueTable,
t -> t.getAwayTeam().equals(team), Outcome::getGoalsScoredByAwayTeam);
}
更新
正如在评论中提到的使用ToIntFunction
和Predicate
,getSum
可以这样编写:
private Integer getSum(final LeagueTable leagueTable,
Predicate<Result> filterFun, ToIntFunction<Outcome> mapFun
) {
return leagueTable.getAllResults().stream()
.filter(filterFun)
.map(Result::getOutcome)
.mapToInt(mapFun).sum();
}
英文:
You can extract functions that do filter and map. And pass them as parameters in this function:
private Integer getSum(final LeagueTable leagueTable,
Function<Result, Boolean> filterFun, Function<Outcome, Integer> mapFun
) {
return leagueTable.getAllResults().stream()
.filter(filterFun)
.map(Result::getOutcome)
.map(mapFun).reduce(0, Integer::sum);
}
Then you can use is in your code like this:
private Integer getTeamGoalsScored(final LeagueTable leagueTable, final Team team) {
return getSum(leagueTable,
t -> t.getHomeTeam().equals(team), Outcome::getGoalsScoredByHomeTeam) +
getSum(leagueTable,
t -> t.getAwayTeam().equals(team), Outcome::getGoalsScoredByAwayTeam);
}
UPDATE
As it was mentioned in comment with ToIntFunction
and Predicate
; getSum
can be written in this way:
private Integer getSum(final LeagueTable leagueTable,
Predicate<Result> filterFun, ToIntFunction<Outcome> mapFun
) {
return leagueTable.getAllResults().stream()
.filter(filterFun)
.map(Result::getOutcome)
.mapToInt(mapFun).sum();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论