java - 根据某些规则对 Map 进行排序

标签 java sorting dictionary alphabetical

我有一张 map ,我想根据一些规则对其内容进行排序:

  1. Sort the map Alphabetically (From A to Z) according to its Values and not its Keys.
  2. Ignore the Case Sensitivity of the Values while sorting them.
  3. Put duplicate words into consideration(Words having exact letters Spelling & Case).
  4. Sort the Alpha numeric words right(Cbc2ee should appear before Cbc100ee).
  5. Handle non English words(área should appear in the words starting with "a" letter but actually it appears after words starting with "z" letter, considering á another letter).

我认为我想要的都是合乎逻辑的。我能够通过此代码完成第 1、2 和 3 点:

public <K, V extends Comparable<? super 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 ) {
                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;  // Special fix to preserve words with similar 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;
}

第(4)点我已经找到了它的脚本,但我无法将它与我的代码合并: http://www.davekoelle.com/alphanum.html

第(5)点我也找到了它的脚本,但我无法将它与我的代码合并: http://www.javapractices.com/topic/TopicAction.do?Id=207

因为这些点会影响compare(...)方法。 有人可以帮我吗?

最佳答案

几点...

方法签名应该是:

public static <K, V> Map<K, V> sortMapByValues(Map<K, V> map)

注意: - 删除对 Comparable 的绑定(bind),因为您正在比较 toString() map 值,而不是值本身 - 抽象类型规范Map<...> ,而不是具体的LinkedHashMap ,根据良好的设计指南 -static因为它不会改变状态 - 它“只是代码”

那么,你的解决方案非常好。它只需要更多的代码来实现这些额外的点。

这里有一些代码可以实现您想要的功能:

public static <K, V> Map<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>>() {
        public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) {
            String aRaw = e1.getValue().toString();
            String bRaw = e2.getValue().toString();
            String a = standardize(aRaw);
            String b = standardize(bRaw);

            // Check for hex
            try
            {
                Integer ai = Integer.parseInt(a, 16);
                Integer bi = Integer.parseInt(b, 16);
                int diff = ai.compareTo(bi);
                if (diff != 0)
                    return diff;
            }
            catch (NumberFormatException ignore)
            {
            }

            int diff = a.compareTo(b);
            if (diff != 0)
                return diff;
            return aRaw.compareTo(bRaw);
        }

        /** This method removes all accent (diacritic) marks and changes to lower case */
        String standardize(String input) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < input.length(); i++) {
                char c = input.charAt(i);
                sb.append(Normalizer.normalize(c + "", Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", ""));
            }
            return sb.toString().toLowerCase();
        }
    });

    // The rest is your code left as it was, cos it's fine
    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;
}

测试代码如下:

public static void main(String[] args) {
    Map<String, String> map = new HashMap<String, String>();
    map.put("a", "CC96");
    map.put("b", "CC97");
    map.put("c", "CC102");
    map.put("d", "CC103");
    map.put("e", "aabbcc");
    map.put("f", "aabbCC");
    map.put("g", "atabends");
    map.put("h", "aaBBcc");
    map.put("i", "AABBcc");
    map.put("j", "aabbcc");
    map.put("k", "Cc102");
    map.put("l", "baldmöglichst");
    map.put("m", "bar");
    map.put("n", "barfuss");
    map.put("o", "barfuß");
    map.put("p", "spätabends");
    map.put("q", "ätabends");
    map.put("r", "azebra");

    System.out.println(sortMapByValues(map).toString()
        .replaceAll(", ", "\r").replaceAll("(\\{|\\})", ""));
}

输出:

a=CC96
b=CC97
c=CC102
k=Cc102
d=CC103
i=AABBcc
h=aaBBcc
f=aabbCC
e=aabbcc
g=atabends
q=ätabends
r=azebra
l=baldmöglichst
m=bar
n=barfuss
o=barfuß
p=spätabends

关于java - 根据某些规则对 Map 进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8628747/

相关文章:

java - java中使用DataOutputStream发送文件

javascript - 如何在我的 Angular 代码中使用 angular-sortable-view?

c++ - 对用户生成的数组进行排序有垃圾数据

c# - 如何让我的通用比较器 (IComparer) 处理空值?

javascript - 从 Map.values() 选择一个属性

Python将包含列表的字典对象转换为包含字典的列表

python - 如何在python中将数据框的列和行添加为字典的键和值

java - 如何在 Eclipse 中自动完成 Drools?

java - 将 FreeType 字体传递给 LibGDX 中的 Assets 加载器

java - Spark SQL : Window function lag until a condition met