Подтвердить что ты не робот

Карта потока Java 8 на наборе записей

Я пытаюсь выполнить операцию карты для каждой записи в объекте Map.

Мне нужно взять префикс с ключа и преобразовать значение из одного типа в другой. Мой код принимает записи конфигурации из Map<String, String> и преобразование в Map<String, AttributeType> (AttributeType - это просто класс, содержащий некоторую информацию. Дальнейшее объяснение не имеет отношения к этому вопросу.)

Лучшее, что я смог придумать с использованием потоков Java 8, следующее:

private Map<String, AttributeType> mapConfig(Map<String, String> input, String prefix) {
   int subLength = prefix.length();
   return input.entrySet().stream().flatMap((Map.Entry<String, Object> e) -> {
      HashMap<String, AttributeType> r = new HashMap<>();
      r.put(e.getKey().substring(subLength), AttributeType.GetByName(e.getValue()));
      return r.entrySet().stream();
   }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

Невозможно построить Map.Entry из-за того, что он является интерфейсом, вызывает создание экземпляра единственной записи Map и использование flatMap(), что кажется уродливым.

Есть ли лучшая альтернатива? Кажется, лучше сделать это, используя цикл for:

private Map<String, AttributeType> mapConfig(Map<String, String> input, String prefix) {
   Map<String, AttributeType> result = new HashMap<>(); 
   int subLength = prefix.length(); 
   for(Map.Entry<String, String> entry : input.entrySet()) {
      result.put(entry.getKey().substring(subLength), AttributeType.GetByName( entry.getValue()));
   }
   return result;
}

Должен ли я избегать Stream API для этого? Или есть ли лучший способ, который я пропустил?

4b9b3361

Ответ 1

Просто переведите "old for loop way" в потоки:

private Map<String, String> mapConfig(Map<String, Integer> input, String prefix) {
    return input.entrySet().stream()
            .collect(Collectors.toMap(entry -> entry.getKey().substring(subLength), entry -> AttributeType.GetByName(entry.getValue())));
}

Ответ 2

Вопрос может быть немного устаревшим, но вы можете просто использовать AbstractMap.SimpleEntry < > следующим образом:

private Map<String, AttributeType> mapConfig(
    Map<String, String> input, String prefix) {
       int subLength = prefix.length();
       return input.entrySet()
          .stream()
          .map(e -> new AbstractMap.SimpleEntry<>(
               e.getKey().substring(subLength),
               AttributeType.GetByName(e.getValue()))
          .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

любой другой объект, похожий на пару, тоже будет работать (например, ApacheCommons Pair кортеж).

Ответ 3

Вот более короткое решение AbacusUtil

Stream.of(input).toMap(e -> e.getKey().substring(subLength), 
                       e -> AttributeType.GetByName(e.getValue()));