У меня есть следующая функция, которая использует потоки и коллекторы для создания карты и отличается выполнением на основе логического входного параметра 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)
Я попытался переместить проверку isMultiSelection ? :
внутри collect()
, но это выдает ошибку времени компиляции.
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())));
}
Я пробовал это, но в сборе() no suitable method found for collect
возникает ошибка компиляции.
Было бы хорошо, если бы вы могли отредактировать свой вопрос, добавив, как выглядел код после вашей попытки. Возможно, вы сделали что-то вроде нарушения вложенности скобок.
getAnswersByQuestions
нужен ()
после него.
Я обнаружил, что компилятор java с трудом выводит аргументы типа, когда они передаются от потока к сборщику. Единственная разница между вашими двумя вариантами использования заключается в используемом сборщике. Я бы вынес коллекторы в отдельный метод, чтобы возвращать соответствующий коллектор для каждого случая. Это не только помогает очистить код, возвращаемый тип метода, предоставляющего сборщик, уточняет типы, избегая ошибки.
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()));
}
Я бы даже подумал о том, чтобы разбить его дальше, возможно, сохранив коллекторы в полях и просто вернув их по имени. Он все еще выглядит слишком занятым для меня с троичным там. Или верните один внутри блока if, и если он провалится, верните другой.
return isMultiSelectableQuiz ? group() : flattenAndGroup();
Если вы переместите крючок внутри вызова
collect
, вы можете избавиться от первых четырех строк дублирования (отquizResponses
доcollect
).