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

Преобразование карты <String, Object> в Map <String, String>

Как преобразовать Map<String,Object> в Map<String,String>?

Это не работает:

Map<String,Object> map = new HashMap<String,Object>(); //Object is containing String
Map<String,String> newMap =new HashMap<String,String>(map);
4b9b3361

Ответ 1

Если ваш Objects содержит только Strings, вы можете сделать это следующим образом:

Map<String,Object> map = new HashMap<String,Object>(); //Object is containing String
Map<String,String> newMap =new HashMap<String,String>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
       if(entry.getValue() instanceof String){
            newMap.put(entry.getKey(), (String) entry.getValue());
          }
 }

Если каждый Objects не String, вы можете заменить (String) entry.getValue() на entry.getValue().toString().

Ответ 2

Теперь, когда у нас есть Java 8/streams, мы можем добавить еще один возможный ответ в список:

Предполагая, что каждое из значений фактически является объектами String, приведение в String должно быть безопасным. В противном случае может использоваться другой механизм для сопоставления объектов в строки.

Map<String,Object> map = new HashMap<>();
Map<String,String> newMap = map.entrySet().stream()
     .collect(Collectors.toMap(Map.Entry::getKey, e -> (String)e.getValue()));

Ответ 3

Общие типы - это абстракция времени компиляции. Во время выполнения все карты будут иметь тот же тип Map<Object, Object>. Поэтому, если вы уверены, что значения являются строками, вы можете обмануть java-компилятор:

Map<String, Object> m1 = new HashMap<String, Object>();
Map<String, String> m2 = (Map) m1;

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

Ответ 4

Есть два способа сделать это. Один из них очень прост, но небезопасен:

Map<String, Object> map = new HashMap<String, Object>();
Map<String, String> newMap = new HashMap<String, String>((Map)map);  // unchecked warning

Другой способ не содержит предупреждений компилятора и обеспечивает безопасность типа во время выполнения, что является более надежным. (В конце концов, вы не можете гарантировать, что исходная карта содержит только значения String, иначе почему бы не быть Map<String, String> в первую очередь?)

Map<String, Object> map = new HashMap<String, Object>();
Map<String, String> newMap = new HashMap<String, String>();
@SuppressWarnings("unchecked") Map<String, Object> intermediate =
    (Map)Collections.checkedMap(newMap, String.class, String.class);
intermediate.putAll(map);

Ответ 5

Невозможно.

Это немного противоречит интуиции.

Вы сталкиваетесь с "Яблоком - это плод", но "Every Fruit is not a Apple"

Пойдите для создания новой карты и проверки с помощью instance of with String

Ответ 6

По мере того как вы выполняете от Object to String, я рекомендую вам улавливать и сообщать (каким-то образом здесь я просто печатаю сообщение, которое обычно плохо).

    Map<String,Object> map = new HashMap<String,Object>(); //Object is containing String
    Map<String,String> newMap =new HashMap<String,String>();

    for (Map.Entry<String, Object> entry : map.entrySet()) {
        try{
            newMap.put(entry.getKey(), (String) entry.getValue());
        }
        catch(ClassCastException e){
            System.out.println("ERROR: "+entry.getKey()+" -> "+entry.getValue()+
                               " not added, as "+entry.getValue()+" is not a String");
        }
    }

Ответ 7

Пока вы можете сделать это с грубым литьем и подавленными предупреждениями

Map<String,Object> map = new HashMap<String,Object>();
// Two casts in a row.  Note no "new"!
@SuppressWarnings("unchecked")
Map<String,String> newMap = (HashMap<String,String>)(Map)map;  

что действительно не хватает всего.:)

Попытка конвертировать узкий общий тип в более общий общий тип означает, что вы используете неправильный тип в первую очередь.

В качестве аналогии: представьте, что у вас есть программа, которая выполняет объемную обработку текста. Представьте, что вы делаете первую половину обработки с помощью Objects (!!), а затем решаете сделать вторую половину с правильной типизацией как String, поэтому вы сокращаете от Object до String. К счастью, вы можете сделать это java (легко в этом случае), но это просто маскирует тот факт, что вы используете слабое типирование в первом тайме. Плохая практика, никаких аргументов.

Никакой разницы здесь (просто сложнее бросить). Вы всегда должны использовать сильную типизацию. При минимальном использовании какой-либо базовый тип - можно использовать подстановочные знаки generics ( "extends BaseType" или "super BaseType" ), чтобы обеспечить совместимость типов и автоматическое кастинг. Еще лучше, используйте правильный тип. Никогда не используйте Object, если у вас нет 100% обобщенного кода, который действительно может использоваться с любым типом.

Надеюсь, что это поможет!:):)


Примечание. Общая сильная типизация и литье типов будут существовать только в .java-коде. После компиляции в .class мы остаемся с необработанными типами (Map и HashMap) без каких-либо типичных параметров типа и автоматического выбора типов ключей и значений. Но это очень помогает, потому что сам код .java строго типизирован и краток.

Ответ 8

Ниже перечислены существующие записи.

TransformedMap.decorateTransform(params, keyTransformer, valueTransformer)

Где

MapUtils.transformedMap(java.util.Map map, keyTransformer, valueTransformer)

только преобразует новые записи в вашу карту.

Ответ 9

Отличные решения здесь, еще один вариант, который учитывает обработку null значений:

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

Map<String,String> stringifiedMap = map.entrySet().stream()
             .filter(m -> m.getKey() != null && m.getValue() !=null)
             .collect(Collectors.toMap(Map.Entry::getKey, e -> (String)e.getValue()));

Ответ 10

private Map<String, String> convertAttributes(final Map<String, Object> attributes) {
    final Map<String, String> result = new HashMap<String, String>();
    for (final Map.Entry<String, Object> entry : attributes.entrySet()) {
        result.put(entry.getKey(), String.valueOf(entry.getValue()));
    }
    return result;
}

Ответ 11

Используйте Java 8 способ преобразования Map<String, Object> в Map<String, String>. Это решение обрабатывает null значения.

Map<String, String> keysValuesStrings = keysValues.entrySet().stream()
    .filter(m -> m.getValue() !=null)
    .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().toString()));