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 另一个。
我有以下函数,它利用流和收集器创建地图,并且根据布尔输入参数执行不同 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 另一个。