【问题标题】:Java: Sorting Map of Type Map<String, ArrayList<String>>Java:Map<String, ArrayList<String>> 类型的排序映射
【发布时间】:2014-09-27 05:41:42
【问题描述】:

我有一个 Map 有一个 String 作为 Key 和一个 ArrayList 作为 Value。 ArrayList 基本上是一个以某种方式链接到 key 的四个值的列表。

我的样本数据是:

String : [ArrayList<String>] 

"USA":    ["25", "5", "20", "4"]
"India":  ["15", "7", "8", "2"]
"Canada": ["29", "17", "8", "6"]

我需要按照 ArrayList 中的第一个值对这个 Map 进行降序排序,如下所示:

"Canada": ["29", "17", "8", "6"]
"USA":    ["25", "5",  "20","4"]
"India":  ["15", "7",  "8", "2"]

我正在尝试下面的函数,但它不适用于 ArrayList 类型的 Map 值:

public class MapUtil
{
    public static <K, V extends Comparable<? super V>> Map<K, V> 
        sortByValue( Map<K, V> map )
    {
        List<Map.Entry<K, V>> list =
            new LinkedList<Map.Entry<K, V>>( map.entrySet() );
        Collections.sort( list, new Comparator<Map.Entry<K, V>>()
        {
            public int compare( Map.Entry<K, V> o1, Map.Entry<K, V> o2 )
            {
                return (o1.getValue()).compareTo( o2.getValue() );
            }
        } );

        Map<K, V> result = new LinkedHashMap<K, V>();
        for (Map.Entry<K, V> entry : list)
        {
            result.put( entry.getKey(), entry.getValue() );
        }
        return result;
    }
}

如何修改这个函数来实现我需要的功能?

【问题讨论】:

  • “它不工作”不是问题描述。

标签: java collections arraylist map


【解决方案1】:

修改代码如下以满足我的要求。

还必须将 Map 值更改为 ArrayList&lt; Integer&gt; 以进行高效排序。

public static <K, V extends Comparable<? super V>> Map<String, ArrayList<Integer>> sortByValue(Map<String, ArrayList<Integer>> map)
    {
        List<Map.Entry<String, ArrayList<Integer>>> list = new LinkedList<Map.Entry<String, ArrayList<Integer>>>(
                map.entrySet());
        Collections.sort(list,new Comparator<Map.Entry<String, ArrayList<Integer>>>() 
                {
                    public int compare(Map.Entry<String, ArrayList<Integer>> o1,Map.Entry<String, ArrayList<Integer>> o2)
                    {
                        return (o2.getValue().get(0)).compareTo(o1.getValue().get(0));
                    }
                });

        Map<String, ArrayList<Integer>> result = new LinkedHashMap<String, ArrayList<Integer>>();
        for (Map.Entry<String, ArrayList<Integer>> entry : list) 
        {
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }

【讨论】:

    【解决方案2】:

    您正在比较整个 ArrayList&lt;String&gt; 值,但您希望按每个 ArrayList 中的第一个值进行比较。

    你应该这样做:

        public int compare(Map.Entry<String, ArrayList<String>> o1, Map.Entry<String, ArrayList<String>> o2)
        {
            return (o1.getValue().get(0)).compareTo( o2.getValue().get(0) );
        }
    

    当然你应该添加空检查,以防 o1.getValue() 返回空或空列表。

    但是,您应该注意,这会将值作为字符串进行比较(例如“5”>“23”),而不是数字。如果你想要一个数字比较,你应该将字符串转换为整数,或者首先将它们存储为整数。

    【讨论】:

    • +1 ...但由于所需的顺序是降序,比较器必须执行 o2.getValue().get(0).compareTo( o1.getValue().get( 0) ) 我还建议对 list 使用 ArrayList 而不是 LinkedList,如 Collections.sort() i> 将对其调用 toArray(),而 ArrayList 会更快地执行它。
    • @Eran get(0) 显然没有为 V 类型定义。我不需要在任何地方将V 更改为ArrayList&lt;V&gt; 吗?
    • @foobar 从您问题的标题和描述看来,您似乎想对Map&lt;String, ArrayList&lt;String&gt;&gt; 进行排序。我不确定您的代码与您要实现的目标有何关系。你应该实现一个Comparator&lt;Map.Entry&lt;String, ArrayList&lt;String&gt;&gt;
    • @Eran 感谢您的帮助。我已经发布了我的解决方案。
    猜你喜欢
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    • 2017-06-01
    • 1970-01-01
    • 2013-05-11
    • 2015-02-24
    • 1970-01-01
    相关资源
    最近更新 更多