重複するキーをJavaマップに保存する方法は?
How Store Duplicate Keys Java Map
1。概要
このチュートリアルでは、重複するキーの処理について説明します。 地図 利用可能なオプション、つまり、単一のキーに複数の値を保存することができます 地図 。
2.標準マップ
Javaにはいくつかのインターフェースがあります マップの実装 それぞれに独自の特殊性があります。
だが、 既存のJavaコアマップの実装は許可されていません 地図 1つのキーに対して複数の値を処理する 。
同じキーに2つの値を挿入しようとすると、2番目の値が保存され、最初の値が削除されることがわかります。
また、(*経由で)返されます 置く(Kキー、V値) *メソッドの各正しい実装):
Map map = new HashMap() assertThat(map.put('key1','value1')).isEqualTo(null) assertThat(map.put('key1','value2')).isEqualTo('value1') assertThat(map.get('key1')).isEqualTo('value2')
では、どうすれば目的の動作を実現できるでしょうか。
3.価値としての収集
明らかに、そうです 地図 各値を使用する コレクション この作業を行うことができます:
Map map = new HashMap() List list = new ArrayList() map.put('key1', list) map.get('key1').add('value1') map.get('key1').add('value2') assertThat(map.get('key1').get(0)).isEqualTo('value1') assertThat(map.get('key1').get(1)).isEqualTo('value2')
ただし、この長いソリューションにはいくつかの欠点があり、エラーが発生しやすくなります。これは、値ごとに1つインスタンス化する必要があることを意味します コレクション 、値を追加または削除する前に値の存在を確認し、値が残っていない場合は手動で削除するなど。
Java 8以降、* compute()*メソッドを利用して改善することができます。
Map map = new HashMap() map.computeIfAbsent('key1', k -> new ArrayList()).add('value1') map.computeIfAbsent('key1', k -> new ArrayList()).add('value2') assertThat(map.get('key1').get(0)).isEqualTo('value1') assertThat(map.get('key1').get(1)).isEqualTo('value2')
これは理解する必要がありますが、そうしない正当な理由がない限り、避ける必要があります。たとえば、企業の制限ポリシーにより、サードパーティのライブラリを使用できません。
そうでなければ、私たち自身の習慣を書く 地図 ホイールを実装して再発明する前に、いくつかのオプションから選択する必要があります。
4. ApacheCommonsコレクション
いつものように、 Apache 私たちの問題を解決する方法があります。
まず、最新バージョンをインポートしましょう 共通コレクション (CCは今始まります):
org.apache.commons commons-collections4 4.1
4.1複数のマッピング
* org.apache.commons.collections4。 マルチマップ *インターフェースは、各キーの値のコレクションを含むマップを定義します。
*で構成されています org.apache.commons.collections4.map 成し遂げる 。 **** MultiValueMap *ほとんどのテンプレートのカバーを自動的に処理するクラス:
MultiMap map = new MultiValueMap() map.put('key1','value1') map.put('key1','value2') assertThat((Collection) map.get('key1')).contains('value1', 'value2')
このクラスはCC3.2以降で利用できますが、 しかし、それはスレッドセーフではありません 、そして CC4.1で非推奨 。新しいバージョンにアップグレードできない場合にのみ使用されます。
4.2 MultiValuedMap
マルチマップ 後継者は* org.apache.commons.collections4。 MultiValuedMap *インターフェース。使用できる複数の実装があります。
複数の値をに保存する方法を見てみましょう 配列リスト 、 配列リスト 重複するアイテムは予約されています:
MultiValuedMap map = new ArrayListValuedHashMap() map.put('key1', 'value1') map.put('key1', 'value2') map.put('key1', 'value2') assertThat((Collection) map.get('key1')).containsExactly('value1', 'value2', 'value2')
または使用できます HashSet 、重複を削除します:
MultiValuedMap map = new HashSetValuedHashMap() map.put('key1', 'value1') map.put('key1', 'value1') assertThat((Collection) map.get('key1')).containsExactly('value1')
上 二 実装はスレッドセーフではありません 。
使い方を見てみましょう UnmodizableMultiValuedMap デコレータはそれらを不変にします:
@Test(expected = UnsupportedOperationException.class) public void givenUnmodifiableMultiValuedMap_whenInserting_thenThrowingException() { MultiValuedMap map = new ArrayListValuedHashMap() map.put('key1', 'value1') map.put('key1', 'value2') MultiValuedMap immutableMap = MultiMapUtils.unmodifiableMultiValuedMap(map) immutableMap.put('key1', 'value3') }
5.グアバのマルチマップ
Guavaは、JavaAPIのGoogleコアライブラリです。
* com.google.common.collect。 バージョン2以降 マルチマップ インターフェイスが表示されます。この記事の執筆時点では、最新バージョンは25ですが、バージョン23以降に分割されました。 jre と アンドロイド*( 25.0-jre と 25.0-android )異なるブランチ、引き続きサンプルバージョン23を使用します。
私たちのプロジェクトで最初にGuavaをインポートしましょう:
com.google.guava guava 23.0
Guavaは、最初から複数の実装パスに従いました。
最も一般的なのは* com.google.common.collect。 ArrayListMultimap 、それはによって各値に使用されます 配列リスト サポートされています HashMap *:
Multimap map = ArrayListMultimap.create() map.put('key1', 'value2') map.put('key1', 'value1') assertThat((Collection) map.get('key1')).containsExactly('value2', 'value1')
いつものように、マルチマップインターフェイスの不変の実装を優先する必要があります。 com.google.common.collect。 ImmutableListMultimap と com.google.common.collect。 ImmutableSetMultimap 。
5.1一般的なマップの実装
特定のものが必要なとき 地図 実装するとき、Guavaが実装した可能性があるため、最初に行うことは、それが存在するかどうかを確認することです。
たとえば、*を使用できます com.google.common.collect。 LinkedHashMultimap *、キーと値の挿入順序を保持します。
Multimap map = LinkedHashMultimap.create() map.put('key1', 'value3') map.put('key1', 'value1') map.put('key1', 'value2') assertThat((Collection) map.get('key1')).containsExactly('value3', 'value1', 'value2')
または、*を使用できます com.google.common.collect。 TreeMultimap *、キーと値を自然な順序で繰り返します:
Multimap map = TreeMultimap.create() map.put('key1', 'value3') map.put('key1', 'value1') map.put('key1', 'value2') assertThat((Collection) map.get('key1')).containsExactly('value1', 'value2', 'value3')
5.2カスタムを構築する マルチマップ
他の多くの実装が利用可能です。
しかし、私たちは未実現のものを飾りたいかもしれません 地図 および/または リスト 。
幸い、Guavaには、これを実行できるファクトリメソッドがあります。 Multimap.newMultimap() 。
6結論
既存のすべての主要な方法で、キーの複数の値をマップに保存する方法を見てきました。
Apache Commons CollectionsとGuavaの最も一般的な実装を調査しましたが、可能であれば、カスタムソリューションよりも優先する必要があります。
元のリンク
https://mp.weixin.qq.com/s/lcUKd-AMXGPix7CEplRmkg
WeChatの注意: Javaの信頼できる
Javaの知識を毎日更新し、到着を楽しみにしています!