Java - 如何根据第一个字母对地图值进行排序?

时间:2016-01-23 13:19:56

标签: java sorting dictionary linkedhashmap

我有一个Java映射,我使用此代码按字母顺序对其String值进行排序:

public <K, V> LinkedHashMap<K, V> sortMapByValues( Map<K, V> map ) {
    SortedSet<Map.Entry<K, V>> sortedEntries = new TreeSet<Map.Entry<K, V>>(
        new Comparator<Map.Entry<K, V>>() {
            @Override 
            public int compare( Map.Entry<K, V> e1, Map.Entry<K, V> e2 ) {
                // Sort this word alphabetically in the map : 
                String a = (String)e1.getValue();
                String b = (String)e2.getValue();

                int diff = a.compareToIgnoreCase( b );

                if (diff == 0) 
                    diff = a.compareTo(b);  

                return diff != 0 ? diff : 1;  // Fix words having the same spelling.
            }
        }
    );

    sortedEntries.addAll( map.entrySet() );

    LinkedHashMap<K, V> sortedMap = new LinkedHashMap<K, V>();

    for( Map.Entry<K, V> sortedEntry: sortedEntries )
        sortedMap.put( sortedEntry.getKey(), sortedEntry.getValue() );

    return sortedMap;
}

由于Map有数千个值,因此上述代码的工作速度足够快,可以快速得到我想要的结果。现在我需要更改此代码并更新它以根据其他条件对Map值进行排序,而不是按字母顺序对其进行排序。

我有一个字母变体ArrayList,如:

ArrayList lettersArrayList = new ArrayList<String>( Arrays.asList( "E", "C", "A", "Z", "Q", "R", "B", "L", "D", ... ) );

此ArrayList中的字母值由用户指定,因此它们可能具有任何其他字母值和顺序。 我需要根据此ArrayList对Map的String值进行排序,因此首先出现以“E”开头的单词,然后出现以“C”开头的单词,依此类推。这可能吗?

1 个答案:

答案 0 :(得分:1)

首先,您的比较器不正确:

return diff != 0 ? diff : 1;

如果ab具有相同的拼写,则将ab进行比较得出1,意味着a > b,并且比较ba也给1,意思是b > a。你可以用

return diff != 0 ? diff : Integer.compare(System.identityHashCode(e1), System.identityHashCode(e2));

(几乎)正确。如果您使用大量内存并且两个单独的对象碰巧使用相同的系统哈希码,这仍然可以使两个条目实际上不同,这是非常非常不可能的。

现在,要回答您的问题,您只需要比较两个条目的首字母的索引:

String a = (String)e1.getValue();
String b = (String)e2.getValue();

int index1 = list.indexOf(a.substring(0, 1));
int index2 = list.indexOf(b.substring(0, 1));

int diff = Integer.compare(index1, index2);

这样可行,但效率极低,因为

  • indexOf()是O(n)
  • 您最好使用Character而不是String来存储单个字符。

因此,不应使用List<String>来存储字母,而应使用HashMap<Character, Integer>,其中每个字母都与其位置相关联。此映射中的查找将为O(1),使比较器更快。