Что возвращает выражение с тернарным оператором при фильтрации коллекции в Java
Что проверяют
Понимаете ли вы, что тернарный оператор это выражение со своим типом, а не сокращённый if, и знаете ли грабли автоупаковки, которые он приносит в стримы. Вопрос почти всегда идёт с кодом на бумаге, и от вас ждут разбора, а не пересказа синтаксиса.
Как отвечать
условие ? a : b вычисляет ровно одну ветку и возвращает её значение. В работе с коллекцией он встречается в двух ролях: внутри filter, где результат обязан быть boolean, и внутри map, где он преобразует элемент.
List<String> marks = users.stream()
.map(u -> u.getAge() >= 18 ? "adult" : "minor")
.toList();Главное, что хотят услышать: тип всего выражения компилятор выводит из обеих веток сразу. Если ветки числовые, работают обычные правила приведения, и true ? 1 : 2.0 даст 1.0, а не 1. Если одна ветка Integer, а другая int, выражение разворачивается в примитив, и null там превращается в NullPointerException:
Integer age = null;
int a = flag ? age : 0; // NPE при flag == trueПоэтому в предикате безопаснее обычная проверка на null через &&, а не тернарник. И стоит помнить, что filter возвращает новый стрим, исходная коллекция не меняется, а toList у стрима отдаёт неизменяемый список, в отличие от Collectors.toList.
Где спотыкаются
Не видят распаковку. Код с Integer в одной из веток выглядит безобидно, тесты на непустых данных зелёные, а на проде прилетает NPE без внятного стектрейса.
Второе: пишут cond ? true : false или cond ? false : someCheck вместо булева выражения. Формально верно, но это сразу читается как неуверенность в работе с boolean.
Третье: путают роли map и filter. Ставят тернарник в map и возвращают null для ненужных элементов, а потом чистят список от null. Отбор делает filter, и цепочка получается на шаг короче.