web-dev-qa-db-ja.com

Map <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);
49
Mawia

ObjectsStringsのみが含まれている場合は、次のようにできます。

_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());
          }
 }
_

すべてのObjectsStringではない場合、_(String) entry.getValue()_をentry.getValue().toString()に置き換えることができます。

25
Shreyos Adikari

Java 8/streamsができたので、リストにもう1つ考えられる答えを追加できます。

各値が実際にareStringオブジェクトであると仮定すると、Stringへのキャストは安全であるはずです。それ以外の場合は、オブジェクトを文字列にマッピングする他のメカニズムを使用できます。

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

ジェネリック型は、コンパイル時の抽象化です。実行時に、すべてのマップは同じタイプMap<Object, Object>を持ちます。したがって、値が文字列であることを確信している場合は、Javaコンパイラーをチートできます:

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

あるコレクションから別のコレクションにキーと値をコピーすることは冗長です。しかし、このアプローチはジェネリック型の安全性に違反するため、依然として良くありません。そのようなことを避けるために、コードを再検討する必要があるかもしれません。

18
Mikhail

これを行うには2つの方法があります。 1つは非常に単純ですが、安全ではありません。

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

もう1つの方法はコンパイラの警告がなく、実行時の型の安全性を保証します。これはより堅牢です。 (結局、元のマップに文字列値のみが含まれることを保証することはできません。さもなければ、そもそも_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);
_
6
cambecc

不可能

これは少し直感に反します。

「Apple is-a fruit」に遭遇していますが、「Every Fruit is a Apple」ではありません

新しいマップを作成して、instance of with String

2
Suresh Atta

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");
        }
    }
2
selig

ブルートキャストと抑制された警告でこれを行うことができますが

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(この場合は簡単です)-しかし、前半で弱い型付けを使用しているという事実を隠しています。悪い習慣、引数はありません。

ここには違いはありません(キャストするのがより困難です)。常に厳密な型指定を使用する必要があります。少なくともいくつかのベースタイプを使用します。その後、ジェネリックワイルドカード(「?extends BaseType」または「?super BaseType」)を使用して、タイプの互換性と自動キャストを行うことができます。さらに良いのは、正しい既知のタイプを使用することです。あらゆるタイプで実際に使用できる100%の一般化コードがない限り、Objectを使用しないでください。

お役に立てば幸いです! :) :)


注:汎用の厳密な型指定と型キャストは.Javaコードにのみ存在します。 .classにコンパイルした後、一般的な型パラメーターとキーと値の自動型キャストのない生の型(MapとHashMap)が残ります。ただし、.Javaコード自体は厳密に型指定されており簡潔であるため、非常に役立ちます。

1
Glen Best

ここでの優れたソリューションは、null値の処理を考慮したもう1つのオプションです。

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()));
1
Johnny

以下は、既存のエントリを変換します。

TransformedMap.decorateTransform(params, keyTransformer, valueTransformer)

どことして

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

新しいエントリのみをマップに変換します

1
yunspace

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()));
_
0
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;
}
0
Sky Tronics