web-dev-qa-db-ja.com

JavaでMap値をキーでソートする方法

キーと値の両方の文字列を持つMapがあります。

データは以下のようなものです。

"質問1"、 "1"
「質問9」、「1」
「質問2」、「4」
「質問5」、「2」

キーに基づいて地図を並べ替えたいです。だから、結局、私はquestion1, question2, question3....などになるでしょう。


結局、私はこのMapから2つの文字列を取得しようとしている.

  • 最初の文字列:質問(1 .. 10の順序で)
  • 2番目の文字列:回答(質問と同じ順序で)

今、私は以下の通りです:

Iterator it = paramMap.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry pairs = (Map.Entry) it.next();
    questionAnswers += pairs.getKey() + ",";
}

これは私に質問を文字列にしますが、それらは順番通りではありません。

324
n00bstackie

短い答え

TreeMap を使用してください。これこそまさにその目的です。

この地図があなたに渡され、あなたがタイプを決定することができないならば、あなたは以下をすることができます:

SortedSet<String> keys = new TreeSet<>(map.keySet());
for (String key : keys) { 
   String value = map.get(key);
   // do something
}

これはキーの自然な順序でマップを横切って繰り返すでしょう。


長い答え

技術的には、SortedMapを実装するものなら何でも使用できますが、まれにTreeMapの実装を使用するのが通常Mapの場合と同様に、これがHashMapになります。

キーがComparableを実装していない複雑な型である場合や自然な順序を使用したくない場合は、TreeMapTreeSetComparatorを渡すことができる追加のコンストラクタがあります。

// placed inline for the demonstration, but doesn't have to be a lambda expression
Comparator<Foo> comparator = (Foo o1, Foo o2) -> {
        ...
    }

SortedSet<Foo> keys = new TreeSet<>(comparator);
keys.addAll(map.keySet());

TreeMapまたはTreeSetを使用するときは、HashMapまたはHashSetとはパフォーマンス特性が異なることに注意してください。大まかに言って、要素を見つけたり挿入したりする操作は O(1) から O(Log(N)) になります。

HashMapでは、1000アイテムから10,000アイテムに移動しても要素を検索する時間には実際には影響しませんが、TreeMapの場合、検索時間は約3倍遅くなります(Logを仮定して)。2) 1000から100,000に移動すると、すべての要素検索で約6倍遅くなります。

567
Jherico

TreeMapはあなたにとって良くないと思います(そしてジェネリックを使うことができないと思います):

List sortedKeys=new ArrayList(yourMap.keySet());
Collections.sort(sortedKeys);
// Do what you need with sortedKeys.
126
TrayMan

TreeMapを使ってマップをソートすることができます。

Map<String, String> map = new HashMap<>();        
Map<String, String> treeMap = new TreeMap<>(map);
for (String str : treeMap.keySet()) {
    System.out.println(str);
}
48
Manoj Singh

TreeMap !を使用してください。

34
AgileJon

あなたがすでにマップを持っていて、それをキーでソートしたいのであれば、単に使用してください

Map<String, String> treeMap = new TreeMap<String, String>(yourMap);

完全な実用的な例:

import Java.util.HashMap;
import Java.util.Set;
import Java.util.Map;
import Java.util.TreeMap;
import Java.util.Iterator;

class SortOnKey {

public static void main(String[] args) {
   HashMap<String,String> hm = new HashMap<String,String>();
   hm.put("3","three");
   hm.put("1","one");
   hm.put("4","four");
   hm.put("2","two");
   printMap(hm);
   Map<String, String> treeMap = new TreeMap<String, String>(hm);
   printMap(treeMap);
}//main

public static void printMap(Map<String,String> map) {
    Set s = map.entrySet();
    Iterator it = s.iterator();
    while ( it.hasNext() ) {
       Map.Entry entry = (Map.Entry) it.next();
       String key = (String) entry.getKey();
       String value = (String) entry.getValue();
       System.out.println(key + " => " + value);
    }//while
    System.out.println("========================");
}//printMap

}//class
32
M-D

TreeMapを使うだけ

new TreeMap<String, String>(unsortMap);

TreeMapはその「キー」の自然な順序に従ってソートされていることに注意してください。

28
Aliti

Java 8 TreeMapを使用できない場合、次のパラメータを取るCollectorswhiteの toMap() メソッドを使用できます。

  • キーマッパー :キーを生成するためのマッピング関数
  • valuemapper :値を生成するためのマッピング関数
  • mergeFunction :同じキーに関連付けられた値間の衝突を解決するために使用されるマージ関数
  • mapSupplier :結果が挿入される新しい空のMapを返す関数。

Java 8の例

Map<String,String> sample = new HashMap<>();  // Push some values to map  
Map<String, String> newMapSortedByKey = sample.entrySet().stream()
                    .sorted(Map.Entry.<String,String>comparingByKey().reversed())
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
Map<String, String> newMapSortedByValue = sample.entrySet().stream()
                        .sorted(Map.Entry.<String,String>comparingByValue().reversed())
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1,e2) -> e1, LinkedHashMap::new));

カスタムコンパレータを使用し、キーに基づいてソートするように例を変更できます。

Map<String, String> newMapSortedByKey = sample.entrySet().stream()
                .sorted((e1,e2) -> e1.getKey().compareTo(e2.getKey()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1,e2) -> e1, LinkedHashMap::new));
12
i_am_zero

Java 8を使用する:

Map<String, Integer> sortedMap = unsortMap.entrySet().stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                    (oldValue, newValue) -> oldValue, LinkedHashMap::new));
6
Taras Melnyk

このコードは、キーと値のマップを昇順と降順の両方の順序でソートできます。

<K, V extends Comparable<V>> Map<K, V> sortByValues
     (final Map<K, V> map, int ascending)
{
     Comparator<K> valueComparator =  new Comparator<K>() {         
        private int ascending;
        public int compare(K k1, K k2) {
            int compare = map.get(k2).compareTo(map.get(k1));
            if (compare == 0) return 1;
            else return ascending*compare;
        }
        public Comparator<K> setParam(int ascending)
        {
            this.ascending = ascending;
            return this;
        }
    }.setParam(ascending);

    Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
    sortedByValues.putAll(map);
    return sortedByValues;
}

例として:

Map<Integer,Double> recommWarrVals = new HashMap<Integer,Double>();
recommWarrVals = sortByValues(recommWarrVals, 1);  // Ascending order
recommWarrVals = sortByValues(recommWarrVals,-1);  // Descending order
5
M. Mashaye

Java 8では

Map<K, V>をキーでソートし、キーをList<K>に入れるには、次のようにします。

List<K> result = map.keySet().stream().sorted().collect(Collectors.toList());

キーでMap<K, V>をソートし、エントリをList<Map.Entry<K, V>>に入れるには、次のようにします。

List<Map.Entry<K, V>> result =
    map.entrySet()
       .stream()
       .sorted(Map.Entry.comparingByKey())
       .collect(Collectors.toList());

大事なことを言い忘れましたが: 文字列 をロケールに応じた方法でソートするには - Collat​​or (コンパレータ)クラスを使用します。

Collator collator = Collator.getInstance(Locale.US);
collator.setStrength(Collator.PRIMARY); // case insensitive collator

List<Map.Entry<String, String>> result =
    map.entrySet()
       .stream()
       .sorted(Map.Entry.comparingByKey(collator))
       .collect(Collectors.toList());
5
Oleksandr
List<String> list = new ArrayList<String>();
Map<String, String> map = new HashMap<String, String>();
for (String str : map.keySet()) {
 list.add(str);
}
Collections.sort(list);
for (String str : list) {
 System.out.println(str);
}
1
Manoj Singh

Arrays.sortメソッドを使ってキーをソートすることもできます。

Map<String, String> map = new HashMap<String, String>();
Object[] objArr = new Object[map.size()];
for (int i = 0; i < map.size(); i++) {
objArr[i] = map.get(i);
}
Arrays.sort(objArr);
for (Object str : objArr) {
System.out.println(str);
}
0
Manoj Singh

機能的なスタイルでは以下のようになります:

 Map<String , String> nameMap = new HashMap<>();
        nameMap.put("question1","1");
        nameMap.put("question9","1");
        nameMap.put("question2","4");
        nameMap.put("question5","2");
        nameMap.entrySet().stream()
            .sorted(Comparator.comparing(x->x.getKey()))
            .map(x->x.getKey())
            .forEach(System.out::println);

出力:

質問1

質問2

質問5

質問9

0
Common Man

Java 8では、.stream()。sorted()も使用できます。

myMap.keySet().stream().sorted().forEach(key -> {
        String value = myMap.get(key);

        System.out.println("key: " + key);
        System.out.println("value: " + value);
    }
);
0
Jonas_Hess