Как заменить нулевые значения в карте длиной ключа, используя поток java 8 - PullRequest
4 голосов
/ 23 апреля 2020

У меня есть Map<String, Integer>, который имеет некоторые ключи и значения. Я хочу связать все ключи со значениями как длину ключа. Мне удалось решить это в чистом виде java и java -8, но почему-то я не думаю, что добавление терминальной операции в конце, как .collect(Collectors.toList());, не требуется для меня в моем коде.

Мой код: (Java) отлично работает

 Map<String, Integer> nameLength = new HashMap<>();
   nameLength.put("John", null);
    nameLength.put("Antony", 6);
    nameLength.put("Yassir", 6);
    nameLength.put("Karein", 6);
    nameLength.put("Smith", null);
    nameLength.put("JackeyLent",null);
    for(Entry<String, Integer> length: nameLength.entrySet()){
      if(length.getValue() == null){
        nameLength.put(length.getKey(),length.getKey().length());
      }
    }

Java -8 тоже отлично работает, но работа терминала бесполезна, как мне избежать этого без использования .foreach().

nameLength.entrySet().stream().map(s->{
  if(s.getValue() == null){
    nameLength.put(s.getKey(),s.getKey().length());
  }
  return nameLength;
}).collect(Collectors.toList());
System.out.println(nameLength);

Любым другим способом, которым я могу сделать вышеупомянутые логики c в Java -8 и выше ??

Ответы [ 2 ]

5 голосов
/ 23 апреля 2020

Если вы собираетесь использовать потоки, вам следует избегать побочных эффектов . Функциональное программирование - все о чистых операциях, где выход зависит только от входа, а функции не имеют побочных эффектов. Другими словами, создайте новую карту вместо изменения существующей.

Если вы сделаете это, вы можете просто выбросить частично заполненную карту и пересчитать все с нуля. Вызов String.length() является дешевым, и на самом деле не стоит усилий, чтобы выяснить, какие значения равны нулю, а какие нет. Пересчитайте все длины.

Map<String, Integer> newMap = nameLength.keySet().stream()
    .collect(Collectors.toMap(
        name -> name,
        name -> name.length()
    ));

С другой стороны, если вы просто хотите исправить свои текущие потоки на карте, на самом деле вы ничего не купите. Я бы просто изменил его на месте без использования потоков.

for (Map.Entry<String, Integer> entry: nameLength.entrySet()) {
  if (entry.getValue() == null) {
    entry.setValue(entry.getKey().length());
  }
}

Или, как обсуждалось выше, вы могли бы упростить ситуацию, заменив все длины:

nameLength.replaceAll((name, __) -> name.length());

(__ обозначает переменную, которая не используется, и поэтому не получает значащего имени .)

0 голосов
/ 23 апреля 2020

Вы почти там, просто используйте фильтр , чтобы идентифицировать записи с нулевыми значениями, а затем используйте Collectors.toMap , чтобы собрать их в Map с длиной ключа в качестве значения * 1006. *

Map<String, Integer> nameLengths = nameLength.entrySet()
                 .stream()
                 .filter(entry->entry.getValue()==null)
                 .collect(Collectors.toMap(Map.Entry::getKey, entry->entry.getKey().length()));

Или более простой способ проверки Collectors.toMap

  Map<String, Integer> nameLengths = nameLength.entrySet()
                 .stream()
                 .collect(Collectors.toMap(Map.Entry::getKey, entry->entry.getValue() == null ? entry.getKey().length() : entry.getValue()));
...