2012-03-04 7 views
0

Map<String, String[]>を扱うクラスを記述し、そのキーを数値順に処理する必要があります。傷害に侮辱を加えるために、いくつかの鍵は有効な整数ではなく、最終的に辞書編集順にアクセスする必要があります。マップの文字列キーを数値で並べ替える

キーがある場合たとえば、:

["10", "2", "100", "duck", "black"] 

彼らはこの順序で繰り返しによって必要があります -

["2", "10", "100", "black", "duck"] 

反復以外のJava、でそれを行うとしようとする最もエレガントな方法は何 - キャッチNumberFormatException?明らかに、私は与えられたマップのフォーマットを制御することはできません。

答えて

6

入力マップの自然順序ではない特定の順序で反復する必要があるため、別のマップ(または各キーに関連する値が必要ない場合はリスト)にダンプする必要があります。 。 TreeMapとカスタムコンパレータを組み合わせて使用​​します。

class NumbersThenWordsComparator implements Comparator<String> { 
    private static Integer intValue(String s) { 
     try { 
      return Integer.valueOf(s); 
     } catch (NumberFormatException e) { 
      return null; 
     } 
    } 

    @Override 
    public int compare(String s1, String s2) { 
     Integer i1 = intValue(s1); 
     Integer i2 = intValue(s2); 
     if (i1 == null && i2 == null) { 
      return s1.compareTo(s2); 
     } else if (i1 == null) { 
      return -1; 
     } else if (i2 == null) { 
      return 1; 
     } else { 
      return i1.compareTo(i2); 
     } 
    }  
} 

public void myMethod(Map<String, String[]> originalMap) { 
    TreeMap<String, String[]> t = 
     new TreeMap<String, String[]>(new NumbersThenWordsComparator()); 
    t.putAll(originalMap); 
    // now iterate over t, which will produce entries in the desired order 
} 
+0

+1を除いてInteger.valueOfを直接呼び出すことはできませんが、非数値文字列を扱うのは例外的な状況ではないためです。例外はこのように使用されることは想定されていません。 –

+0

合意。残念ながら、標準のJava APIは適切な代替手段を提供していません。 (本当に気にしているのであれば、チェックを行うメソッドを自分で実装できます - http://stackoverflow.com/questions/237159/whats-the-best-way-to-check-to-see-if-aを参照してください。 -stringはJavaの整数を表しますが、これは痛みであるという事実はよく知られたAPI疣贅です。 – jacobm

+0

実際に私はこのベンチマークがRegexの使用が悪い考えではないことを示していると考えています:http ://stackoverflow.com/a/7324087/82609 –

0

SortedMapを使用します。これは、自然順序付けに基づいてキーを並べ替えます。文字列の場合、それは辞書編集的です。数字が文字の前に来るかどうか分からないが、いずれの方法でもソートがよく定義され、一貫しているので、数字を最初から最後に(つまりArrayList<String> keys = yourMap.keySet()のようにしてから、数字の文字列が '最初に)。

+2

100は、辞書順で2つ前に来ることになります。 –

+0

数字が特定のサイズになることがわかっている場合は、DecimalFormatを使用して数値に0を埋め込むことができます。私。 'DecimalFormat format = new DecimalFormat(" 00000 ");'これは辞書形式で正しくソートされる '00100'と' 00002'を生成します。これには、データに関する追加の前提が必要です。 – smessing

+1

また、そうしたくない場合、簡単な解決策は独自のカスタムコンパレータを作成し、それを使って 'SortedMap'のキーをソートすることです。 – smessing

関連する問題