Map<String, String>
String
キーは「123」などの数値にすぎません。この値はJSFコンポーネントのUIから取得されているため、数値を取得しています。 UIコンポーネントのコントラクトを変更したくない。
次に、Map<Long, String>
上記のMap
に基づいて、transform
クラスにいくつかのMaps
メソッドがあることを確認しましたが、すべてがキーではなく変換値に焦点を当てています。
より良い変換方法はありますかMap<String, String>
からMap<Long, String>
?
Java 8の更新
ストリームを使用してこれを行うことができます:
_Map<Long, String> newMap = oldMap.entrySet().stream()
.collect(Collectors.toMap(e -> Long.parseLong(e.getKey()), Map.Entry::getValue));
_
これは、すべてのキーがLong
sの有効な文字列表現であることを前提としています。また、変換時に衝突が発生する可能性があります。たとえば、_"0"
_と_"00"
_はどちらも_0L
_にマップされます。
私はあなたがマップを反復する必要があると思います:
_Map<Long, String> newMap = new HashMap<Long, String>();
for(Map.Entry<String, String> entry : map.entrySet()) {
newMap.put(Long.parseLong(entry.getKey()), entry.getValue());
}
_
このコードは、map
のすべての値をサニタイズしたことを前提としています(したがって、無効なlong値はありません)。
より良い解決策があることを願っています。
[〜#〜]編集[〜#〜]
Commons Collection-Utilsの さらに言えば、CollectionUtils#transformedCollection(Collection, Transformer)
メソッドに出くわしましたが、それはあなたが望むことをするかもしれないようです。Collection
を実装するクラスに対してのみ機能します。
@Vivinの答えは正しいですが、GuavaにMap
のキーを変換できる(またはSet
をまったく変換できない)メソッドがない理由を説明すると役立つと思います。
Guavaの変換とフィルタリングのすべてのメソッドは、遅延した結果を生成します...関数/述語は、オブジェクトが使用されるときに必要な場合にのみ適用されます。彼らはコピーを作成しません。そのため、しかし、変換はSet
の要件を簡単に破ることができます。
たとえば、「1」と「01」の両方をキーとして含む_Map<String, String>
_があるとします。これらは両方とも別個のString
sであるため、Map
は両方をキーとして合法的に含めることができます。ただし、Long.valueOf(String)
を使用して変換すると、どちらも値_1
_にマッピングされます。それらはもはや別個のキーではありません。マップのコピーを作成してエントリを追加しても、重複したキーはそのキーの以前のエントリを上書きするため、これによって問題が発生することはありません。ただし、遅延変換されたMap
には一意のキーを適用する方法がないため、Map
の規約に違反します。
これで、Java 8ストリーム、マップ、収集を使用して、これをより読みやすくクリーンな方法で実行できます。
Map<String, String> oldMap
Map<Long, String> newMap = oldMap.entrySet().stream()
.collect(Collectors.toMap(entry -> Long.parseLong(entry.getKey()), Map.Entry::getValue));
以下は、結果のマップを変更できないようにするための、以下の回答のいずれかの更新バージョンです(いいえ、Guavaを使用せず、単純にJava 8):
import static Java.util.stream.Collectors.collectingAndThen;
import static Java.util.stream.Collectors.toMap;
...
newMap = oldMap.entrySet().stream().collect(collectingAndThen(
toMap((Map.Entry<String, String> entry) -> transformKey(entry.getKey()),
(Map.Entry<String, String> entry) -> transformValue(entry.getValue())),
Collections::unmodifiableMap)));
短い答えはノーです、グアバは箱から出してこれを提供しません。
簡単な方法は以下のようになります。ただし、注意事項がいくつかあります。
public static <K, V, L, W> Map<L, W> transformMap(Map<K, V> map, Function<K, L> keyFunction, Function<V, W> valueFunction) {
Map<L, W> transformedMap = newHashMap();
for (Entry<K, V> entry : map.entrySet()) {
transformedMap.put(
keyFunction.apply(entry.getKey()),
valueFunction.apply(entry.getValue()));
}
return transformedMap;
}
public static <K, V, L> Map<L, V> transformKeys(Map<K, V> map, Function<K, L> keyFunction) {
return transformMap(map, keyFunction, Functions.<V>identity());
}
Guavaのトランスフォーマーはすべて「遅延」またはビューベースです。マップキートランスフォーマーを実装するには、双方向の関数が必要になると思います。私の理解では、Guavaチームの作業中に、その問題を解決するコンバーターがあるということです。
あなたが遭遇する他の問題は、 " Jimmy-proof "になるために、重複の可能性に対処しなければならないということです。これは、別のグアバの原則です。これを処理する1つの方法は Multimap ;を返すことです。もう1つは、重複が発生したときに例外をスローすることです。私がお勧めしないのは、問題を隠すことです。重複するキーを持つ後続のエントリを無視するか、重複したキーで新しいエントリを上書きします。
Java 8および jOOλ を使用して回答
private static <K1, K2, V> Map<K2, V> mapKeys(Map<K1, V> map, Function<K1, K2> keyMapper) {
return Seq.seq(map).map(t -> t.map1(keyMapper)).toMap(Tuple2::v1, Tuple2::v2);
}
これに対する既製の実用的なソリューションを提供する史上最高の投稿は、次の場所にあります。
このサイトには、考えられる3つのケースがすべて示されています。