Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.217.249.77] |
|
Сообщ.
#1
,
|
|
|
Всем привет, кто еще здесь остался ! Задача в следующем. Есть сложная мапа: Map<String, Object> где Object может быть String, Long, List<Object>, Map<String, Object>. Так вот, в дебрях этой мапы мне надо найти все значения, которые являются String и которые удовлетворяют некому условию, например, регулярному выражению, и произвести замену в строке (заменить часть строки), обновив исходный Map. Уровень вложенности объектов не большой - не более 4 уровней. Как заменить value в Map или List я знаю. Вопрос в том, как найти. Ничего умнее рекурсивного поиска в лоб я не придумал с базовой конструкцией вида:
void findInMap(Map<String, Object> map){ for(Map.Entry<String, Object> entry: map.entrySet()){ Object objValue = entry.getValue(); if(objValue instanceof String){ //определяем, соответствует ли строка условию, //если соответствует, производим замену }else if(objValue instanceof Long){ //пропускаем }else if(objValue instanceof List){ //ищем в List'е, отдельный метод, но по сути тоже самое что и findInMap }else if(objValue instanceof Map){ //ищем в Map findInMap( (Map<String, Object>)objValue ); }else{ //не понятный объект, кидаем исключение } } } Код получается не сказать что сложный, но не маленький. Может есть более красивое решение? Думал насчет стримов (Stream API), но так и не придумал как их использовать для данной задачи, правда я и не очень хорошо эти стримы понимаю. |
Сообщ.
#2
,
|
|
|
Цитата DRON666 @ Думал насчет стримов (Stream API) Они тут ничем не помогут. Цитата DRON666 @ Код получается не сказать что сложный, но не маленький. Да не, вполне небольшой. Зачем кидать исключение на непонятный объект? Может его просто пропускать мимо вместе с Long'ами? Добавлено Ну например: import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import java.util.function.UnaryOperator; import java.util.regex.Pattern; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; final class FindInMap { public static void main(String[] args) { final Map<String, Object> map = Map.of( "foo", "bar", "Foo", "Bar", "FOO", "BAZ", "gee", List.of(123, "bar", "BAZ"), "qux", Map.of("foo", "Bar", "gee", 567) ); printSortedMap(map); final var pattern = Pattern.compile("([bB])ar"); final var aaargh = new Updater<>(String.class, s -> pattern.matcher(s).matches() ? s.replace("ar", "AAARGH!!!") : s); final var aaarghedMap = aaargh.update(map); printSortedMap(aaarghedMap); } private static <K, V> void printSortedMap(Map<K, V> map) { System.out.println(new TreeMap<>(map)); } static final class Updater<T> { private final Class<T> cls; private final UnaryOperator<T> mapper; Updater(Class<T> cls, UnaryOperator<T> mapper) { this.cls = cls; this.mapper = mapper; } Map<String, Object> update(Map<String, Object> map) { return map.entrySet().stream() .map(this::update) .collect(toMap(Entry::getKey, Entry::getValue)); } List<Object> update(List<Object> list) { return list.stream() .map(this::update) .collect(toList()); } Entry<String, Object> update(Entry<String, Object> entry) { return new Pair<>(entry.getKey(), update(entry.getValue())); } Object update(Object o) { if (cls.isAssignableFrom(o.getClass())) { @SuppressWarnings("unchecked") final var value = (T) o; return mapper.apply(value); } else if (o instanceof List) { @SuppressWarnings("unchecked") final var list = (List<Object>) o; return update(list); } else if (o instanceof Map) { @SuppressWarnings("unchecked") final var map = (Map<String, Object>) o; return update(map); } else { return o; } } } private static final class Pair<A, B> implements Entry<A, B> { private final A first; private final B second; private Pair(A first, B second) { this.first = first; this.second = second; } @Override public A getKey() { return first; } @Override public B getValue() { return second; } @Override public B setValue(B value) { throw new UnsupportedOperationException("Immutable object"); } } } => {FOO=BAZ, Foo=Bar, foo=bar, gee=[123, bar, BAZ], qux={gee=567, foo=Bar}} {FOO=BAZ, Foo=BAAARGH!!!, foo=bAAARGH!!!, gee=[123, bAAARGH!!!, BAZ], qux={gee=567, foo=BAAARGH!!!}} |
Сообщ.
#3
,
|
|
|
Ого, очень интересно. О таком функциональном решении я не думал, углубиться в стримы пришлось, спасибо.
|