Java順序付けマップ


322

Javaでは、キーと値のペアを格納およびアクセスするためのマップのように機能するが、キーと値のリストが同じ順序になるように、キーの順序付きリストと値の順序付きリストを返すことができるオブジェクトはありますか?

コードによる説明として、私は架空のOrderedMapのように動作するものを探しています。

OrderedMap<Integer, String> om = new OrderedMap<>();
om.put(0, "Zero");
om.put(7, "Seven");

String o = om.get(7); // o is "Seven"
List<Integer> keys = om.getKeys();
List<String> values = om.getValues();

for(int i = 0; i < keys.size(); i++)
{
    Integer key = keys.get(i);
    String value = values.get(i);
    Assert(om.get(key) == value);
}

4
あなたがやりたいことがすべて同時に両方を繰り返すことである場合、Map.entrySet()を使用すると、どのマップでもそれを実行できます。LinkedHashMapには明確に定義された順序がありますが、マップの場合、エントリセットはキーと値のペアを反映しています。
ピートカーカム

5
Mapの実装はサンプルコードとして動作するため、このコードは良い例ではありません。並べ替え、並べ替えの有無。
Peter Lawrey

2
Sun JDK実装では、getKeysおよびgetValues()セットによって返されるセットはマップ内のentrySet()によってサポートされるため、サンプルがテストするのと同じ反復順序になります。
ピートカーカム

4
まあそれは面白いです、私はそれに気づかなかった。それでも、クレイジーだと思いますが、インターフェイスによって明示的に検証されていない実装については想定しないでください。過去に何度もやけどをしました。
Whatsit 2009年

2
Ordered Mapは何か違うので、Java Sorted Mapという名前にする必要があります-を参照してくださいLinkedHashMap
OndraŽižka

回答:


397

SortedMapの(実装とのインタフェースのTreeMapは)あなたの友人である必要があります。

インターフェースにはメソッドがあります:

  • keySet() キーのセットを昇順で返します
  • values() 対応するキーの昇順ですべての値のコレクションを返します

したがって、このインターフェースはお客様の要件を正確に満たします。ただし、キーには意味のある順序が必要です。それ以外の場合は、挿入順序によって順序が決定されるLinkedHashMapを使用できます。


2
例:SortedMap <String、Object> map = new TreeMap <>();
Ben

7
TreeMapを使用するには、キークラスがComparableインターフェースを実装する必要があります。そうでない場合は、何らかのRuntimeExceptionがスローされます。TreeMapはソートされたマップでもありますが、作者は順序付けされた(ソートされていない)マップを使用したいと思います。LinkedHashMap順序付けられたマップのみを取得することをお勧めします(「挿入順序によって決定される」とおっしゃっていました)。
K.ゴル

1
この回答は、keySet()を反復する方法を示すことで改善できます

4
java 8 docから。LinkedHashMap反復の順序は、エントリが最後にアクセスされ
TRiNE

1
@TRiNE私はあなたのコメントをフォローしていませんが、いくつかの文脈を見逃したかもしれません。デフォルトでLinkedHashMapは、反復順序は挿入順ですが、代わりに別のコンストラクタを使用してアクセス順序を指定できます。docs.oracle.com/javase/8/docs/api/java/util/...
ロブ・

212

キーと値のペアを格納およびアクセスするためのマップのように機能するが、キーと値のリストが同じ順序になるように、キーの順序付きリストと値の順序付きリストを返すことができるオブジェクトはありますか?

java.util.LinkedHashMapを探しています。Map.Entry <K、V>ペアのリストを取得します。これは常に同じ順序で繰り返されます。その順序は、アイテムを配置した順序と同じです。または、java.util.SortedMapを使用します。キーが自然順序付けされているか、によって指定されている必要があるしますComparator


14
そして、これをダブルチェックするリーダーを保存するためだけに、テストでは検証するのが難しいため、keySet()メソッドput()は呼び出しの順序を反映するLinkedHashSetを効果的に返します。put()同じキーを繰り返し呼び出しても、remove()事前にキーを指定しない限り、順序は変わりません。
Glenn Lawrence

java 8 docから。LinkedHashMap反復の順序
TRiNE

24

LinkedHashMapはキーの順序を維持します。

それ以外は、java.util.LinkedHashMapは通常のHashMapと同じように機能します。


1
これは質問に対する答えを提供しません。批評したり、著者に説明を要求したりするには、投稿の下にコメントを残します。自分の投稿にはいつでもコメントできます。十分な評判を得ると、どの投稿にもコメントできるようになります。
ianaya89

2
@ ianaya89これは本当の答えだと思いますが、John Feminellaの答えとよく似ています。
T30 2015年

1
エントリがマップに配置されるときにエントリがその順序で格納される、順序付けられたマップを取得する場合は、LinkedHashMapが正しい答えです。マップ内のエントリを入力順に並べ替える場合は、SortedMapが適切です。
Ralph

@TRiNEリンクしたJava 8のドキュメントでは、挿入順序とアクセス順序という2つの順序付けモードが考えられます。特別なコンストラクターpublic LinkedHashMap(int initialCapacity、float loadFactor、boolean accessOrder)を使用して呼び出される後者について考えます。デフォルトのコンストラクターは、挿入順のLinkedHashMapインスタンスを作成します。
ArturŁysik

1
@ArturŁysikはい、そうです。それは私が数日前にした間違いでした。修正します。コメントを削除します。編集できなくなったため
TRiNE

7

フレームワークから取得する最も近いコレクションはSortedMapだと思います


3
ポイントを失う価値があると思った場合、私はこの回答に反対票を投じます。上記の回答が指摘しているように、あなたの回答にはLinkedHashMapに関する適切な情報が欠けているため、SortedMapの簡単な説明も役立ちます。
CorayThan 2013年

@CorayThan、その場合、あなたは最良の回答に賛成票を投じ、正しいかもしれないが最良ではない他者に反対票を投じない...
bruno conde

1
それは私がやったことです。誰かが反対票を投じる理由が理解できると言っているだけです。
CorayThan 2013年

5

キーの昇順または降順でアクセスおよびトラバースできるNavigableMapインターフェースを利用できます。このインターフェースは、これに代わるものです。、SortedMapインターフェースいます。ナビゲート可能なマップは、通常、そのキーの自然な順序に従って、またはマップの作成時に提供されるコンパレーターによってソートされます。

それの3つの最も有用な実装があります:TreeMapImmutableSortedMap、およびConcurrentSkipListMap

TreeMapの例:

TreeMap<String, Integer> users = new TreeMap<String, Integer>();
users.put("Bob", 1);
users.put("Alice", 2);
users.put("John", 3);

for (String key: users.keySet()) {
  System.out.println(key + " (ID = "+ users.get(key) + ")");
}

出力:

Alice (ID = 2)
Bob (ID = 1)
John (ID = 3)



2

tl; dr

Map< Integer , String >キーでソートされた順序を維持するには、SortedMap/ NavigableMapインターフェースを実装する2つのクラスのいずれかを使用します。

  • TreeMap
  • ConcurrentSkipListMap

シングルスレッド内でマップを操作する場合は、最初のを使用しTreeMapます。スレッド間で操作する場合は、2番目のを使用しConcurrentSkipListMapます。

詳細については、下の表と次の説明を参照してください。

細部

これは、MapJava 11にバンドルされている10の実装の機能を示すために作成した図表です。

NavigableMapインタフェースは何であるSortedMap最初の場所にされている必要があります。のSortedMap論理的に削除する必要がありますが、いくつかのサードパーティ製のマップの実装は、インタフェースを使用している可能性があるようにすることはできません。

この表からわかるように、2つのクラスだけがSortedMap/ NavigableMapインターフェースを実装しています。

ソートされた順序でこれらのキープキーの両方の、いずれかの彼らの自然な順序で(使用compareToの方法Comparablehttps://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/をComparable.html)インターフェース)またはComparator渡す実装によって。これら2つのクラスの違いは、2番目のクラスConcurrentSkipListMapスレッドセーフであり並行性が高いことです。

以下の表の「反復順序」列も参照してください。

  • LinkedHashMapこのクラスは、彼らがされた順序でそのエントリを返しもともと挿入します
  • EnumMapキーの列挙型クラスが定義されている順序でエントリを返します。たとえば、どの従業員がどの曜日をカバーしているかのマップ(Map< DayOfWeek , Person >)は、DayOfWeekJavaに組み込まれたenumクラスを使用しています。その列挙型は、月曜日を最初に、日曜日を最後に定義されています。したがって、イテレータのエントリはその順序で表示されます。

他の6つの実装は、エントリを報告する順序について何の約束もしません。

Java 11のマップ実装の表、それらの機能の比較


0

私が使用している単純なハッシュマップ、リンクリストやコレクションを値によって地図をソートします。

import java.util.*;
import java.util.Map.*;
public class Solution {

    public static void main(String[] args) {
        // create a simple hash map and insert some key-value pairs into it
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("Python", 3);
        map.put("C", 0);
        map.put("JavaScript", 4);
        map.put("C++", 1);
        map.put("Golang", 5);
        map.put("Java", 2);
        // Create a linked list from the above map entries
        List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(map.entrySet());
        // sort the linked list using Collections.sort()
        Collections.sort(list, new Comparator<Entry<String, Integer>>(){
        @Override
         public int compare(Entry<String, Integer> m1, Entry<String, Integer> m2) {
        return m1.getValue().compareTo(m2.getValue());
        }
      });
      for(Entry<String, Integer> value: list) {
         System.out.println(value);
     }
   }
}

出力は次のとおりです。

C=0
C++=1
Java=2
Python=3
JavaScript=4
Golang=5
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.