重複するキーを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-jre25.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の知識を毎日更新し、到着を楽しみにしています!

画像