2016-10-12 2 views
1
List<Entity> entities = ... 
Map<Boolean, List<Entity>> entitiesByIsTest = entities.stream() 
         .collect(Collectors.groupingBy(Entity::isTest)); 

Очевидно, что карта результата имеет единственные ключи, которые присутствуют в свойстве группировки. Он должен работать так же, как для типов с инфинитивным набором значений. Но как насчет перечислений/булевых/других определенных типов?StreamAPI Collectors.groupingBy пустая коллекция вместо нуля

Возможно ли реализовать инициализацию пустых коллекций более элегантно, чем в фрагменте ниже?

if (entitiesByIsTest.get(true) == null) { 
    entitiesByIsTest.put(true, new ArrayList()); 
} 
+1

трудно понять вопрос. Какова цель вашего кода? –

+0

Цель состоит в том, чтобы делить набор на два независимых набора, а затем выполнить несколько разных действий - например, сохранить обычные объекты, но сохранить только количество объектов тестирования –

ответ

5

Если вы хотите Boolean клавиш и оба отображения всегда инициализируются, используют partitioningBy, который имеет точно желаемые свойства.

Map<Boolean, List<Entity>> entitiesByIsTest = entities.stream() 
         .collect(Collectors.partitioningBy(Entity::isTest)); 

Если ключ является enum, вы должны остаться с groupingBy, но вы можете заменить последующие get операции с

List<Entity> value=map.computeIfAbsent(key, x->new ArrayList<>()); 

который будет построить и ввести новый ArrayList тогда и только тогда, когда существует не было предыдущего сопоставления и возвращало фактическое сопоставленное значение в любом случае (в отличие от putIfAbsent).

Конечно, вы можете добавить все отсутствующие значения в одной нетерпеливых операциях вместо:

EnumSet.allOf(KeyType.class).forEach(key->map.computeIfAbsent(key, x->new ArrayList<>())); 
4

Вы можете использовать entitiesByIsTest.putIfAbsent(true,new ArrayList());, которые должны добавить новый пустой ArrayList только тогда, когда нет ничего в карте для этого ключевого

+0

спасибо! хорошая точка зрения. Одно дело, что это не функциональный стиль. Моя основная цель - использовать все преимущества stream api, такие как четкий код, максимально избегая состояний –

+0

Не совсем понятно, о чем вы просите. У вас уже есть решение для 'groupingBy' - что _already_ работает для перечислений, булевых или других типов. Этот ответ отвечает на ваш второй вопрос, как инициализировать пустые коллекции на карте. –

0

Вы можете написать свой собственный коллектор.

Collectors.of(
    //**Initialize map with all of your values**//, 
    entity -> map.get(entity.isTest()).add(entity), 
    (left, right) -> right.forEach(r -> left.get(r.getKey()).addAll(r.getValue)); return r;) 
Смежные вопросы