Как преобразовать 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);
Как преобразовать 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);
Если ваш 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()
.
Теперь, когда у нас есть 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()));
Общие типы - это абстракция времени компиляции. Во время выполнения все карты будут иметь тот же тип Map<Object, Object>
. Поэтому, если вы уверены, что значения являются строками, вы можете обмануть java-компилятор:
Map<String, Object> m1 = new HashMap<String, Object>();
Map<String, String> m2 = (Map) m1;
Копирование ключей и значений из одной коллекции в другую избыточно. Но этот подход по-прежнему не очень хорош, поскольку он нарушает безопасность типа дженериков. Может быть, вы должны пересмотреть свой код, чтобы избежать таких вещей.
Есть два способа сделать это. Один из них очень прост, но небезопасен:
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);
Невозможно.
Это немного противоречит интуиции.
Вы сталкиваетесь с "Яблоком - это плод", но "Every Fruit is not a Apple"
Пойдите для создания новой карты и проверки с помощью instance of with String
По мере того как вы выполняете от 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");
}
}
Пока вы можете сделать это с грубым литьем и подавленными предупреждениями
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 строго типизирован и краток.
Ниже перечислены существующие записи.
TransformedMap.decorateTransform(params, keyTransformer, valueTransformer)
Где
MapUtils.transformedMap(java.util.Map map, keyTransformer, valueTransformer)
только преобразует новые записи в вашу карту.
Отличные решения здесь, еще один вариант, который учитывает обработку 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()));
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;
}
Используйте 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()));