简体   繁体   English

Java-如何根据地图值的首字母排序?

[英]Java - How to sort a map values according to their first letter?

I have a Java map that i use this code to sort its String values alphabetically: 我有一个Java映射,使用此代码按字母顺序对其字符串值进行排序:

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;
}

Since the Map has thousands of values, the above code works fast enough giving the result that i want rapidly. 由于Map具有成千上万个值,因此上述代码可以足够快地运行,从而给出我想要的快速结果。 Now i need to change this code and update it to sort the Map values according to another condition instead of sorting it alphabetically. 现在,我需要更改此代码并更新它,以便根据另一种条件而不是按字母顺序对Map值进行排序。

I have a variant ArrayList of letters, like: 我有一个字母的变体ArrayList,例如:

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

The letter values inside this ArrayList are specified by the user so they might have any other letter values and order. 该ArrayList中的字母值由用户指定,因此它们可能具有任何其他字母值和顺序。 I need to sort the String values of the Map according to this ArrayList, so the words starting with "E" come first, then comes the ones that start with "C", and so on. 我需要根据此ArrayList对Map的String值进行排序,因此,以“ E”开头的单词首先出现,然后出现以“ C”开头的单词,依此类推。 Is this possible? 这可能吗?

First of all, your comparator is incorrect: 首先,您的比较器不正确:

return diff != 0 ? diff : 1;

If a and b have the same spelling, comparing a to b gives 1, meaning that a > b , and comparing b to a also gives 1, meaning that b > a . 如果ab具有相同的拼写,比较ab给出1,这意味着a > b ,以及比较ba还给出了1,这意味着b > a You could use 你可以用

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

to be (almost) correct. 是(几乎)正确的。 This could still make two entries equal when they're actually different if you're using an awful lot of memory and two separate objects happen to end up with the same system hashcode, which is very, very unlikely. 如果您使用大量内存,并且两个单独的对象碰巧以相同的系统哈希码结尾,那么当两个条目实际上不同时,这仍然可以使它们相等。

Now, to answer your question, all you need is to compare the indices of the first letters of your two entries: 现在,要回答您的问题,您所需要做的就是比较两个条目的第一个字母的索引:

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);

This will work but will be extremely inefficient, because 这会起作用,但效率极低,因为

  • indexOf() is O(n) indexOf()是O(n)
  • you'd better use Character rather that String to store a single character. 您最好使用Character而不是String来存储单个字符。

So, instead of a List<String> to store the letters, you should use a HashMap<Character, Integer> , where each letter would be associated with its position. 因此,应该使用HashMap<Character, Integer>而不是List<String>来存储字母,其中每个字母都将与其位置相关联。 A lookup in this map would be O(1), making the comparator much faster. 此映射中的查找为O(1),使比较器快得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM