反向HashMap

时间:2016-01-31 20:32:36

标签: java hashmap reverse sorted

我有HashMap看起来像:

HashMap<Player, Integer> playerHashMap = new HashMap<>();

玩家是包含姓名,号码,年龄等的对象。

现在我已经对它进行了分类,它就像这样:

key    , value
-----------------
Player1, 1
Player2, 2
Player3, 4
Player4, 6

但是我希望按值反转这个地图,如下所示:

key    , value
-----------------
Player4, 6
Player3, 4
Player2, 2
Player1, 1

有什么想法吗?

排序方法(按值排序)如下所示:

private static HashMap<Player, Integer> sortByValues(HashMap<Player, Integer> map) { 
           List list = new LinkedList(map.entrySet());

           Collections.sort(list, new Comparator<Object>() {
                public int compare(Object o1, Object o2) {
                   return ((Comparable) ((Map.Entry) (o1)).getValue())
                      .compareTo(((Map.Entry) (o2)).getValue());
                }
           });

           HashMap<Player, Integer> sortedHashMap = new LinkedHashMap<Player, Integer>();
           for (Iterator<?> it = list.iterator(); it.hasNext();) {
                Map.Entry<Player, Integer> entry = (Map.Entry<Player, Integer>) it.next();
                  sortedHashMap.put(entry.getKey(), entry.getValue());
           } 
           return sortedHashMap;
      }

5 个答案:

答案 0 :(得分:2)

您可以使用java.util.TreeMap并传递比较器,以您想要的方式对它们进行排序。

但是我仍然想知道为什么你有玩家作为钥匙和整数作为价值? 如果仅使用Integer进行排序,则可能需要交换Key和值以获得更好的标准使用Maps的方法。 此外,如果您不需要使用散列技术访问对象(即如果您的集合在散列会提高性能的情况下不会很大),请考虑使用简单的List。

答案 1 :(得分:1)

事实是HashMap并没有保证任何特定的迭代顺序。所以你只是幸运了#39;您的列表以任何方式排序。要解决您的问题,您必须将表行排序为一个实体,以便value链接到相应的player。为此,您可以直接使用Map.Entry,并将它们放到集合中,但您需要一个自定义比较器。在您的示例中,最好使用通常的ArrayList作为任务,并使用Collections.sort()对其进行排序。要颠倒顺序,否定从比较器返回的结果:

class Player {}

public static void main(String[] args) {
    HashMap<Player, Integer> all = new HashMap<>();
    List<Map.Entry<Player, Integer>> sorted = sortByValues(all);
    for (Map.Entry<Player, Integer> e : sorted) {
        System.out.println("Player: " + e.getKey());
        System.out.println("Value: " + e.getValue());
    }
}

private static List<Map.Entry<Player, Integer>> sortByValues(HashMap<Player, Integer> map) {
    List<Map.Entry<Player, Integer>> list = new ArrayList<>(map.entrySet());

    Collections.sort(list, new Comparator<Map.Entry<Player, Integer>>() {
        public int compare(Map.Entry<Player, Integer> e1, Map.Entry<Player, Integer> e2) {
            //use minus to reverse the order
            return -e1.getValue().compareTo(e2.getValue());
        }
    });

    return list;
}

答案 2 :(得分:1)

你是怎么排序的? (基本)HashMap不定义元素之间的顺序。 我用这个:

    public static <K extends Comparable<K>,V> List<Entry<K,V>> sortByKeys(Map<K,V> map, final Comparator<K> cmp)
{
    List<Entry<K, V>> ret = new ArrayList<>();
    for(Entry<K,V> kv : map.entrySet())
        ret.add(kv);


    Collections.sort(ret,((Comparator) new Comparator<Entry<K,?>>()
    {
        @Override
        public int compare(Entry<K, ?> o1, Entry<K, ?> o2)
        {
            return cmp.compare(o1.getKey(), o2.getKey());
        }
    }));

    return ret;
}

您可以指定比较器来订购退回的入库清单。

=====

编辑: 使用关注顺序的Map实现是个好主意。 您可以简单地修改代码以指定排序,只需修改标题和这一行:

-private static HashMap<Player, Integer> sortByValues(HashMap<Player, Integer> map) {
+private static HashMap<Player, Integer> sortByValues(HashMap<Player, Integer> map, final boolean reverse) {

并在街区:

-return ((Comparable) ((Map.Entry) (o1)).getValue())
+return (reverse?-1:1)*((Comparable) ((Map.Entry) (o1)).getValue())

答案 3 :(得分:1)

我不确定您为什么要返回单独的地图。您已经拥有了List,您只需按存储条目的值进行排序即可 也不要限制自己使用特定类型的地图,如HashMap。你可能只获得了一些东西,但是你很难将你的实现改为其他类型的Map。

所以你的代码看起来像:

private static List<Map.Entry<Player, Integer>> entriesSoltedByValue(
        Map<Player, Integer> map) {
    List<Map.Entry<Player, Integer>> list = new ArrayList<>(map.entrySet());

    list.sort(Comparator.comparing(Map.Entry<Player, Integer>::getValue).reversed());

    return list;
}

或使用流:

private static List<Map.Entry<Player, Integer>> entriesSoltedByValue(
        Map<Player, Integer> map) {
    return map.entrySet()
            .stream()
            .sorted(Comparator
                    .comparing(Map.Entry<Player, Integer>::getValue)
                    .reversed())
            .collect(Collectors.toList());
}

答案 4 :(得分:1)

简而言之,您无法将订单设置为HashMap。如果您希望使用与HashMap相同的功能,但需要使用TreeMap

Map<String, Integer> orderedMap = new TreeMap(Collections.reverseOrder());
orderedMap.putAll(playerHashMap);

HashMapTreeMap中为O(log(n))提供O(1)插入和搜索,因为它在内部用红黑树实现。