Как условно изменить карту в потоковом API Java 8?

Я пытаюсь изменить ключи Map на основе условной логики и проблем. Я новичок в API потоков Java 8. Допустим, у меня есть такая карта:

Map<String, String> map = new HashMap<>();

map.put("PLACEHOLDER", "some_data1");
map.put("Google", "some_data2");
map.put("Facebook", "some_data3");
map.put("Microsoft", "some_data4");

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

boolean condition = foo();

map = map.entrySet().stream().filter(entry -> "PLACEHOLDER".equals(entry.getKey()))
        .map(key -> {
            if (condition) {
                return "Apple";
            } else {
                return "Netflix";
            }
        }).collect(Collectors.toMap(e -> e.getKey(), Map.Entry::getValue));

Я нашел этот вопрос, который заставляет меня думать, что, возможно, я не могу сделать это с API потоков Java 8. Надеюсь, кто-то лучше меня знает, как это сделать. Ссылка на Ideone, если вы хотите поиграть с ним.

Не могли бы вы уточнить, хотите ли вы изменить ключ или значение?

YCF_L 21.07.2018 22:02

@YCF_L ключ, что делает вещи немного страннее.

boltup_im_coding 21.07.2018 22:05

Не могли бы вы отредактировать свой вопрос в этом случае - "... и условно изменить его значение на другое" - это то, что вызывало путаницу. Обычно это означает «изменить значение, связанное с этим ключом».

Boris the Spider 21.07.2018 22:06

Сообщите нам, если вы решили свою проблему. Если да, пожалуйста, принимать самый полезный ответ или добавьте свой собственный ответ, объясняющий, как вы его решили.

Tomasz Linkowski 28.07.2018 13:47
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
4
4 310
2

Ответы 2

Вы отфильтровали все элементы, которые неPLACEHOLDER. Вам нужно добавить эту логику фильтра к вашей операции map:

final Map<String, String> output = input.entrySet().stream()
        .map(e -> {
            if (!e.getKey().equals("PLACEHOLDER")) {
                return e;
            }
            if (condition) {
                return new AbstractMap.SimpleImmutableEntry<>("Apple", e.getValue());
            }
            return new AbstractMap.SimpleImmutableEntry<>("Netflix", e.getValue());
        }).collect(toMap(Map.Entry::getKey, Map.Entry::getValue));

Но поскольку у вас гарантированно будет только один экземпляр PLACEHOLDER в Map, вы можете просто сделать

String placeholderData = input.remove("PLACEHOLDER");
if (placeholderData != null) {
    input.put(condition ? "Apple" : "Netflix", placeholderData);
}

Если вы действительно хотите сделать это с помощью Stream, вам просто нужно переместить условную логику на этап сбора, например:

boolean condition = true;
map.entrySet().stream().collect(Collectors.toMap(
        entry -> mapKey(entry.getKey(), condition), Map.Entry::getValue
));

где:

private static String mapKey(String key, boolean condition) {
    if (!"PLACEHOLDER".equals(key)) {
        return key;
    }
    if (condition) {
        return "Apple";
    } else {
        return "Netflix";
    }
}

Однако вторая часть Борис паук ответ с использованием Map.remove и Map.put кажется лучшим вариантом.

Я думаю, что ваш подход к волшебству с функцией сопоставления клавиш лучше, чем мой подход, основанный на map.

Boris the Spider 21.07.2018 22:09

Другие вопросы по теме