Java 流中的三元运算符

Ternary operator within Java Streams

我有以下函数,它利用流和收集器创建地图,并且根据布尔输入参数执行不同 isMultiSelectableQuiz:

private Map<Integer, Long> getCountPerAnswerChoice(boolean isMultiSelectableQuiz, int questionId, List<QuizResponse> quizResponses) {
     return isMultiSelectableQuiz
        ? quizResponses.stream()
            .flatMap(response -> response.getAnswersByQuestions().stream())
            .filter(answerByQuestion -> answerByQuestion.getQuestionId() == questionId)
            .collect(
                Collectors.flatMapping(
                    (QuizQuestionAnswer answerByQuestion) -> answerByQuestion.getAnswerSelectionsList().stream(),
                    Collectors.groupingBy(selection -> selection, Collectors.counting())))
        : quizResponses.stream()
            .flatMap(response -> response.getAnswersByQuestions().stream())
            .filter(answerByQuestion -> answerByQuestion.getQuestionId() == questionId)
            .collect(
                Collectors.groupingBy(QuizQuestionAnswer::getAnswerSelection, Collectors.counting()));
    }

有没有办法简化此代码并使其更优雅,因为以下部分在两个 if/else 分支中重复出现

quizResponses.stream()
            .flatMap(response -> response.getAnswersByQuestions().stream())
            .filter(answerByQuestion -> answerByQuestion.getQuestionId() == questionId)

我曾尝试在 collect() 中移动 isMultiSelection ? : 检查,但这会引发编译时错误

private Map<Integer, Long> getCountPerAnswerChoice(boolean isMultiSelectableQuiz, int questionId, List<QuizResponse> quizResponses) {
     return quizResponses.stream()
        .flatMap(response -> response.getAnswersByQuestions().stream())
        .filter(answerByQuestion -> answerByQuestion.getQuestionId() == questionId)
        .collect(
            isMultiSelectableQuiz
                ? Collectors.groupingBy(
                    QuizQuestionAnswer::getAnswerSelection, Collectors.counting())
                : Collectors.flatMapping(
                    (QuizQuestionAnswer answerByQuestion) -> answerByQuestion.getAnswerSelectionsList().stream(),
                    Collectors.groupingBy(selection -> selection, Collectors.counting())));
    }

我发现 java 编译器难以推断类型参数,因为它们从流流向收集器。您的两个用例之间的唯一区别是使用的收集器。我会将收集器拉出到一个单独的方法中,以 return 为每种情况选择合适的收集器。这不仅有助于清理代码,提供收集器的方法的 return 类型明确了类型,避免了错误。

private Map<Integer, Long> getCountPerAnswerChoice(boolean isMultiSelectableQuiz,
        int questionId, List<QuizResponse> quizResponses) {
    return quizResponses.stream()
        .flatMap(response -> response.getAnswersByQuestions().stream())
        .filter(answerByQuestion -> answerByQuestion.getQuestionId() == questionId)
        .collect(getCollectorForQuizType(isMultiSelectableQuiz));
}

private Collector<? super QuizQuestionAnswer, ?, Map<Integer, Long>> getCollectorForQuizType(
        boolean isMultiSelectableQuiz) {
    return isMultiSelectableQuiz
        ? Collectors.groupingBy(QuizQuestionAnswer::getAnswerSelection, Collectors.counting())
        : Collectors.flatMapping(
            answerByQuestion -> answerByQuestion.getAnswerSelectionsList().stream(),
            Collectors.groupingBy(selection -> selection, Collectors.counting()));
}

我什至会考虑进一步分解它,也许将收集器存储在字段中,然后 return 按名称收集一个。那里的三元组对我来说仍然太忙了。或者 return 一个在 if 块中,如果它落空,return 另一个。