簡體   English   中英

轉換地圖<String,Object>到地圖<String,String>

[英]Convert Map<String,Object> to 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);

現在我們有了 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()));

如果您的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()

泛型類型是編譯時抽象。 在運行時,所有地圖都將具有相同的類型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);

不可能。

這有點違反直覺。

你遇到了“蘋果是水果”,但“每個水果都不是蘋果”

去創建一個新地圖並檢查instance of with String

當您從 Object 轉換為 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");
        }
    }
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;
}

這里有很好的解決方案,還有一個考慮到處理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()));

雖然您可以通過強制轉換和抑制警告來做到這一點

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后半部分,因此您將范圍從ObjectString 幸運的是,您可以使用 java(在這種情況下很容易)來做到這一點——但這只是掩蓋了您在前半部分使用弱類型的事實。 不好的做法,沒有爭論。

這里沒有區別(只是更難投射)。 您應該始終使用強類型。 至少使用一些基本類型 - 然后可以使用泛型通配符(“?擴展 BaseType”或“?超級 BaseType”)來提供類型兼容性和自動轉換。 更好的是,使用正確的已知類型。 除非你有 100% 通用代碼可以真正用於任何類型,否則永遠不要使用 Object。

希望有幫助! :) :)


注意:通用強類型和類型轉換僅存在於 .java 代碼中。 編譯為 .class 后,我們只剩下原始類型(Map 和 HashMap),沒有泛型類型參數以及鍵和值的自動類型轉換。 但它非常有幫助,因為 .java 代碼本身是強類型且簡潔的。

以下內容將轉換您現有的條目。

TransformedMap.decorateTransform(params, keyTransformer, valueTransformer)

然而

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

僅將新條目轉換為您的地圖

使用 Java 8 方式將Map<String, Object>Map<String, String> 此解決方案處理null值。

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

我發現使用番石榴最簡單的方法:

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>30.1-jre</version>
    </dependency>

那么你可以這樣做:

Map<String,Object> map = new HashMap<String,Object>(); 
Map<String,String> newMap = Maps.transformValues(map, Functions.toStringFunction());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM