重构 Java 中的私有实用方法

huangapple go评论62阅读模式
英文:

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);
    }

更新

正如在评论中提到的使用ToIntFunctionPredicategetSum可以这样编写:

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&lt;Result, Boolean&gt; filterFun, Function&lt;Outcome, Integer&gt; 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 -&gt; t.getHomeTeam().equals(team), Outcome::getGoalsScoredByHomeTeam) + 
           getSum(leagueTable,
            t -&gt; 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&lt;Result&gt; filterFun, ToIntFunction&lt;Outcome&gt; mapFun 
) {
        return leagueTable.getAllResults().stream()
                .filter(filterFun)
                .map(Result::getOutcome)
                .mapToInt(mapFun).sum();
    }

huangapple
  • 本文由 发表于 2020年8月19日 16:51:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/63483373.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定