2016-05-09 4 views
2

Скажем, у нас есть Map<Key, Collection<Value>> myMap и метод, который удаляет значение из коллекции, связанной с ключом. Если удаление значения выходит из коллекции пустой, мы хотим избавиться от key записи в карте:Удалить ключ, если значение пуста

List<Value> removeValue(Key key, Value value) { 
    List<Value> v = myMap.get(key); 
    if (v != null) { 
     v.remove(value); 
     if (v.isEmpty()) 
      myMap.remove(key); 
    } 
    return v; 
} 

Есть ли Java 8 способы достижения описанного поведения с однострочником или коротким способом ?

+1

Ничто не приходит в голову сразу. Это может быть лучше подходит для http://codereview.stackexchange.com/. – markspace

+0

Ваш оригинальный метод кажется неправильным, но он все равно не слишком подробный ... – manouti

+1

'if (v.size() == 1) myMap.remove (key);' выглядит неправильно. Что делать, если список не содержит значения? – smac89

ответ

6

Вы можете использовать computeIfPresent для этого:

static <K, V> List<V> removeValue(K key, V value, Map<K, List<V>> map){ 
    return map.computeIfPresent(key, (k, l) -> l.remove(value) && l.isEmpty() ? null : l); 
} 

computeIfPresent применяет BiFunction к ключу и текущего значения в карте, если значение не null (если это nullcomputeIfPresent возвращается null сразу), а затем либо задает значение возвращаемому значению BiFunction, если возвращаемое значение не равно null или удаляет ключ с карты, если возвращаемое значение равно null и, наконец, возвращает новое значение.

Обратите внимание, что она ведет себя немного по-другому методу, у вас вопрос - это не будет удалить уже пустой List с карты, потому что remove вернется false. Если вы хотите удалить уже пустой List, вы можете использовать l.isEmpty() || (l.remove(value) && l.isEmpty()).

+0

Спасибо! Странно, что я лучше понимаю вторую форму (именно то, что я искал точно), чем первая. Кроме того, можно было бы сделать что-то подобное для размещения элементов? Я не могу представить, как, потому что я вижу, что нужно использовать как computeIfPresent', так и 'computeIfAbsent'. Или это может быть однострочным? – dabadaba

+1

@dabadaba, если вы хотите создать список, если он отсутствует, а затем добавить к нему, вы можете использовать 'map.computeIfAbsent (key, k -> new ArrayList <>()). Add (v)' – Alex

+0

@dabadaba За это вы должны просто использовать ['compute'] (https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#compute-K-java.util.function.BiFunction-), поэтому что для него это будет «null». Подобно 'myMap.compute (key, (k, l) -> {if (l == null) l = new ArrayList <>(); l.add (value); return l;});' – 4castle

Смежные вопросы