3

これは基本的HashMapにキーに基づいてソートする方法ではありません。そのためTreeMapに、ウインクなしで直接使用できました:)

現時点で私が持っているのは

Map<String, Object> favoritesMap = new HashMap<String, Object>();
and its contents can be
["Wednesdays" : "abcd"]
["Mondays" : "1234"]
["Not Categorized" : "pqrs"]
["Tuesdays" : "5678"]

キーに基づいて HashMap をソートしたいのですが、これに加えて、最後に取得するために「分類されていません」が必要です。

したがって、keySet を繰り返し処理しているときに期待されるのは

["Mondays", "Tuesdays", "Wednesdays", "Not Categorized"] i.e. sorted on keys and "Not Categorized" is the last one

HashMap作成中と最後に追加することを考えまし["Not Categorized" : "pqrs"]たがHashMap、順序を保証するものではありません:)

解決策のための他の指針はありますか?

4

4 に答える 4

5

TreeMap何らかの外部的な理由で具体的に除外していますか?そうでない場合は、明らかにTreeMap特別に作られたで使用することができますComparator

他のいずれかを検討しましたSortedMapか?

間違いなく出ている場合TreeMapは、拡張HashMapして、常にもう1つのエントリがあるように見せますが、それは確かに些細な作業ではありません。SortedMapこの道を進む前に、を使用しないという非常に正当な理由があるはずです。

追加した

これは、特定のエントリを常に最後までソートする方法の例ですTreeMap

// This key should always appear at the end of the list.
public static final String AtEnd = "Always at the end";

// A sample map.
SortedMap<String, String> myMap =
        new TreeMap<>(
        new Comparator<String>() {
          @Override
          public int compare(String o1, String o2) {
            return o1.equals(AtEnd) ? 1 : o2.equals(AtEnd) ? -1 : o1.compareTo(o2);
          }
        });

private void test() {
  myMap.put("Monday", "abc");
  myMap.put("Tuesday", "def");
  myMap.put("Wednesday", "ghi");
  myMap.put(AtEnd, "XYZ");

  System.out.println("myMap: "+myMap);
  // {Monday=abc, Tuesday=def, Wednesday=ghi, Always at the end=XYZ}
}

あなたはその変種を探しているのだろうか?

于 2013-01-31T10:28:54.747 に答える
3

LinkedHashMap挿入順に結果を返すことを保証する asを使用することで、これを実現できます。

また、次の投稿を確認して、マップ タイプの違いを理解してください。

HashMap、LinkedHashMap、TreeMap の違い

または、値とは異なるキーを保持するカスタム クラスを作成します。そのクラスのキーに従ってソートします。あなたの場合、キーをその日と同じ値にし、「分類されていない」場合は、そのキーが他のどのキーよりも遅く開始するようにします。たとえば、「Z_Not Categorized」にします。

public ComplexKey
{
    String key;
    String value;
}

ComplexKey monday = new ComplexKey("monday", "monday");
ComplexKey notCategorized = new ComplexKey("Z_Not Categorized", "Not Categorized");

complexKey次に、クラスのキーに従って値をソートするカスタムコンパレータを作成できます。

于 2013-01-31T10:22:16.603 に答える
1

実際、キーは常にソートされています。マップを数回出力すると、結果は同じままであることがわかります。

最初に、ハッシュについてもう一度ゴシップします。

その理由はハッシングです。各オブジェクトにはhashCode()メソッドがあります。ハッシュ空間は、可能なすべてのハッシュ値をインデックスとして含む大きな配列のようなものです。新しい要素が に挿入されるHashSetか、新しいペアが に挿入されるHashMapと、そのハッシュ コードに従ってハッシュ空間に配置されます。2 つの要素のハッシュ コードが同じequals()場合、メソッドと比較され、等しくない場合、新しい要素がその隣に配置されます。

次に、そこで何が起こるかを知っていれば、以下のようなコードを実装できます。

import java.util.*;

class MyString {
    private String str;

    public MyString (String str) {
        this.str = str;
    }

    public String toString () {
        return str;
    }

    public boolean equals (Object obj) {
        if (obj.getClass().equals(MyString.class)) {
            return obj.toString().equals(str);
        }
        return false;
    }

    public int hashCode () {
        if (str.equalsIgnoreCase("Not Categorized")) {
            return Integer.MAX_VALUE;
        } else if (str.hashCode() == Integer.MAX_VALUE) {
            return 0;
        }
        return str.hashCode();
    }
}

public class Test {
    public static void main (String args[]) {
        Map<MyString, String> m = new HashMap<MyString, String>();
        m.put(new MyString("a"), "a");
        m.put(new MyString("c"), "c");
        m.put(new MyString("Not Categorized"), "NC");
        m.put(new MyString("b"), "b");
        Set<MyString> keys = m.keySet();
        for (MyString k : keys) {
            System.out.println(m.get(k));
        }
    }
}

その結果、「未分類」は常に最後に来ます。理由は簡単です。ハッシュ値は常に整数の最大値です。

String ラッパー クラスを作成する理由は、String クラスが最終的なものであり、拡張できないためです。したがって、この方法では、クラス構造が少し変更されますが、それほど大きくはなりません。


効率は劣りますが、TreeMap を使用することは可能です。

public static void main (String args[]) {
    Map<String, String> m = new TreeMap<String, String>(new Comparator<String>() {
        public int compare (String s1, String s2) {
            if (s1.equals(s2)) {
                return 0;
            }
            if (s1.equalsIgnoreCase("Not Categorized")) {
                return 1;
            }
            if (s2.equalsIgnoreCase("Not Categorized")) {
                return -1;
            }
            if (s1.hashCode() > s2.hashCode()) {
                return 1;
            } else if (s1.hashCode() < s2.hashCode()) {
                return -1
            } else {
                return 0;
            }
        }

        public boolean equals (Object obj) {
            return false;
        }
    });
    m.put("a", "a");
    m.put("c", "c");
    m.put("Not Categorized", "NC");
    m.put("b", "b");
    Set<String> keys = m.keySet();
    for (String k : keys) {
        System.out.println(m.get(k));
    }
}

結果は同じです。すべての要素を並べ替えますが、他の文字列のハッシュ順序は変更しません。「分類されていない」が常に最大のものになるようにするだけです。

于 2013-01-31T16:51:10.353 に答える
1

あなたの場合、私は TreeMap を使用します:

Map<DayOfWeek, Object> favoritesMap = new TreeMap<>();

DayOfWeek次のように宣言するクラスはどこですか:

class DayOfWeek implements Comparable<DayOfWeek> {

曜日を文字列として並べ替えるのは便利ではないためです。

于 2013-01-31T10:25:48.800 に答える