【问题标题】:How are identical values sorted with this code?如何使用此代码对相同的值进行排序?
【发布时间】:2017-01-03 02:47:46
【问题描述】:

本题代码属于this答案。

我的问题是:如何用下面的代码对相同的值进行排序?

import java.util.*;

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

【问题讨论】:

  • 你试过运行它吗?
  • @Oliver 是的,我做到了。而且我找不到特定的模式。
  • 您是否尝试过进行一些先前的研究?
  • 相同的值应该保持与排序前相同的顺序

标签: java sorting dictionary hashmap


【解决方案1】:

来自Collections.sort()http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#sort-java.util.List-)的文档:

这种排序保证是稳定的:相同的元素不会因为排序而重新排序。

所以相等元素的顺序(即在这种情况下具有相等值的条目)将与 map.entrySet() 返回的原始条目集中相同。

【讨论】:

  • 正确。反过来,条目集是一个集合,没有任何特定的顺序,因此条目可以以任何顺序进入列表。难怪 OP 看不到任何特定的模式。
  • @Ole 确实,我看不到任何特定的模式。但是,最终结果是总是以相同的顺序。
  • ... 直到下一个 Java 版本问世。 ;-) 说真的,虽然顺序不太可能改变,但只要您只在一台运行一个 Java 版本的计算机上尝试过,就不要过分依赖它总是相同的。
  • 如果您需要依赖相等值的特定排序,您应该扩展 Comparator 以反映该行为。
  • @Florian 谢谢。可以举个例子吗?
【解决方案2】:

这个答案部分是对某些 cmets 的回答。

首先,虽然原始发布者 Dake 观察到相同输入的相同顺序,但通常不同的Map 实现(如HashMapLinkedHashMapTreeMap)通常会分发它们的元素不同顺序的条目集,这足以让原始发布者的代码在包含相同映射的地图上给出不同的结果。

其次,有人在评论中要求我使用 Comparator 使相等的值按添加到地图的日期进行排序。一般来说,地图不会记录这样的日期,所以这是不可能的。但是,如果您对原始地图使用LinkedHashMap,它会保留插入顺序,因此这将满足您的要求。

最后为了完整起见,假设您想通过键对具有相等值的条目进行排序:

public static <K extends Comparable<? super K>, V extends Comparable<? super V>> Map<K, V> sortByValue( Map<K, V> map )
{
    List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>( map.entrySet() );
    list.sort(Comparator.comparing(Map.Entry<K, V>::getValue).thenComparing(Map.Entry<K, V>::getKey) );

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

这是 Java 8 的答案。您可以在早期的 Java 版本中通过多几行代码获得相同的效果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-31
    • 2021-05-17
    • 1970-01-01
    • 2016-02-10
    • 2019-02-09
    • 2021-01-02
    • 1970-01-01
    相关资源
    最近更新 更多