【问题标题】:Sort a map on key and value根据键和值对地图进行排序
【发布时间】:2011-09-26 16:03:16
【问题描述】:

我想根据键和值对 Map 进行排序。首先是关键,然后是价值。 比如这应该是结果;

1,2 1,3 2,1 2,2

有人对如何有效地实现这一目标提出建议吗?我一直看到人们使用 TreeMap 对键进行排序,但我也需要值。

或者当然欢迎使用任何其他方法对键和值进行排序。

【问题讨论】:

标签: java sorting map


【解决方案1】:

请遵循此代码:- 此代码将首先按键对地图进行排序,然后按值对地图进行排序。 只需编写一个 main 方法并按如下方式调用此方法:-

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class SortMapByKeyAndValue
{
    public static void main(String[] args)
    {
        aMapSortProgramByKeyAndValue();
    }

    private static void aMapSortProgramByKeyAndValue()
    {
        Map<String, Integer> myMap = new HashMap<String, Integer>();
        // putting values in the Map
        myMap.put("Jayant", 80);
        myMap.put("Abhishek", 90);
        myMap.put("Anushka", 80);
        myMap.put("Amit", 75);
        myMap.put("Spandan", 50);
        myMap.put("Hari", 55);
        myMap.put("Keshav", 60);

        System.out.println("Map data without Sort :-");
        for (Entry<String, Integer> myEntryMapData : myMap.entrySet())
        {
            System.out.println("The Map data is Key: " + myEntryMapData.getKey() + " Value: "
                    + myEntryMapData.getValue());
        }

        List<Entry<String, Integer>> myMapDataAsList = new ArrayList<Map.Entry<String, Integer>>();
        myMapDataAsList.addAll(myMap.entrySet());

        System.out.println("Map data Stored in List, The whole List is : " + myMapDataAsList);

        Iterator<Entry<String, Integer>> myListIterator = myMapDataAsList.iterator();
        System.out.println("Map data Stored in List, Print through iterator :-");

        for (; myListIterator.hasNext();)
        {
            Entry<String, Integer> myListData = myListIterator.next();
            System.out.println("The List data is Key: " + myListData.getKey() + " Value: " + myListData.getValue());
        }

        Collections.sort(myMapDataAsList, new Comparator<Entry<String, Integer>>()
        {

            @Override
            public int compare(Entry<String, Integer> dataOne, Entry<String, Integer> dataTwo)
            {
                return dataOne.getKey().compareTo(dataTwo.getKey());
            }

        });

        System.out.println("After Sort by the Key the Map data is : ");
        myListIterator = myMapDataAsList.iterator();
        for (; myListIterator.hasNext();)
        {
            Entry<String, Integer> myListData = myListIterator.next();
            System.out.println("The List data is Key: " + myListData.getKey() + " Value: " + myListData.getValue());
        }

        Collections.sort(myMapDataAsList, new Comparator<Entry<String, Integer>>()
        {

            @Override
            public int compare(Entry<String, Integer> dataOne, Entry<String, Integer> dataTwo)
            {
                return dataOne.getValue().compareTo(dataTwo.getValue());
            }

        });

        System.out.println("After Sort by the vale the Map data is : ");
        myListIterator = myMapDataAsList.iterator();
        for (; myListIterator.hasNext();)
        {
            Entry<String, Integer> myListData = myListIterator.next();
            System.out.println("The List data is Key: " + myListData.getKey() + " Value: " + myListData.getValue());
        }
    }
}

【讨论】:

【解决方案2】:

您要查找的是SortedSetMultimap,它是 Google 的 Guava 库的一部分。他们包含的实现被命名为TreeMultimap:
http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/TreeMultimap.html

如果您不熟悉它,Guava 是一个很棒的库,其中包含许多您有时认为应该在标准 Java 库中的好东西。实际上,我认为 Java 8 将包含来自 Guava 的一些东西(至少在我看来,这似乎是这个项目的漂移:http://openjdk.java.net/jeps/108)。

【讨论】:

    【解决方案3】:
    import java.util.SortedSet;
    import java.util.TreeSet;
    
    public class SortMapOnKeyAndValue {
    
        public static void main(String[] args) {
            SortedSet<KeyValuePair> sortedSet = new TreeSet<KeyValuePair>();
            sortedSet.add(new KeyValuePair(1, 2));
            sortedSet.add(new KeyValuePair(2, 2));
            sortedSet.add(new KeyValuePair(1, 3));
            sortedSet.add(new KeyValuePair(2, 1));
    
            for (KeyValuePair keyValuePair : sortedSet) {
                System.out.println(keyValuePair.key+","+keyValuePair.value);
            }
        }
    }
    class KeyValuePair implements Comparable<KeyValuePair>{
        int key, value;
    
        public KeyValuePair(int key, int value) {
            super();
            this.key = key;
            this.value = value;
        }
    
        public int compareTo(KeyValuePair o) {
            return key==o.key?value-o.value:key-o.key;
        }
    }
    

    【讨论】:

    • Blimmey,太花哨了 :) 为什么我没想到.. :)
    【解决方案4】:

    整体思路是,将Map转换成List,对List进行排序,将排序后的list放回Map。

    地图--->列表--->排序--->地图

    示例

    import java.util.Collections;
    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.LinkedHashMap;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    
    public class SortMyMap{
    
       public static void main(String[] args) {
    
        System.out.println("Unsort Map......");
        Map<String,String> unsortMap = new HashMap<String,String>();
        unsortMap.put("1", "1");
        unsortMap.put("2", "A");
        unsortMap.put("3", "2");
    
        Iterator iterator=unsortMap.entrySet().iterator();
    
            for (Map.Entry entry : unsortMap.entrySet()) {
                System.out.println("Key : " + entry.getKey() 
                    + " Value : " + entry.getValue());
            }
    
            System.out.println("Sorted Map......");
            Map<String,String> sortedMap =  sortByComparator(unsortMap);
    
            for (Map.Entry entry : sortedMap.entrySet()) {
                System.out.println("Key : " + entry.getKey() 
                    + " Value : " + entry.getValue());
            }
       }
    
       private static Map sortByComparator(Map unsortMap) {
    
            List list = new LinkedList(unsortMap.entrySet());
    
            //sort list based on comparator
            Collections.sort(list, new Comparator() {
                 public int compare(Object o1, Object o2) {
                   return ((Comparable) ((Map.Entry) (o1)).getValue())
                   .compareTo(((Map.Entry) (o2)).getValue());
                 }
        });
    
            //put sorted list into map again
        Map sortedMap = new LinkedHashMap();
        for (Iterator it = list.iterator(); it.hasNext();) {
             Map.Entry entry = (Map.Entry)it.next();
             sortedMap.put(entry.getKey(), entry.getValue());
        }
        return sortedMap;
       }    
    }
    

    【讨论】:

      【解决方案5】:

      这是不可能的,因为地图不能包含重复的键。 TreeMap 始终按键值排序(假设键类型为Comparable)。


      但是对于那些任务,我们通常会使用一个值是列表的地图:

      Map<Integer, List<Integer>> map = new TreeMap<Integer, List<Integer>>();
      
      // add some values in random order
      List<Integer> list = new ArrayList<Integer>();
      list.add(2);
      list.add(1);
      map.put(2,list);
      list = new ArrayList<Integer>();
      list.add(2);
      list.add(1);
      map.put(1,list);
      
      // result
      for (Integer key:map.keySet()) {   // map is already sorted
        List<Integer> value = map.get(key);
        Collections.sort(value);         // list of values needs sorting
        for (Integer innerValue:value) {
          System.out.printf("%s : %s%n", key, innerValue);
        }
      }
      

      【讨论】:

        【解决方案6】:

        其他答案表明重复键的问题,但我猜你有想要排序的对,而 Map 位只是一个错误。我能想到的最简洁的解决方案是创建一个自定义 Pair 类,该类实现 Comparator 并比较两个 Pair 的键和值。然后,您可以使用 Collections.sort 对其进行排序。

        【讨论】:

          【解决方案7】:

          听起来你想要某种类型的多地图,例如

          SortedMap<Key, SortedSet<Value>> map = new TreeMap<Key, SortedSet<Value>>();
          
          map.put(1, new TreeSet<Integer>(Arrays.asList(1, 2)));
          map.put(2, new TreeSet<Integer>(Arrays.asList(2, 1)));
          
          System.out.println(map);
          

          打印

          { 1 = {1, 2}, 2 = {1, 2}}
          

          【讨论】:

            【解决方案8】:

            如果你愿意冒险,你可以使用允许你指定 Comparator 的构造函数:http://download.oracle.com/javase/1.5.0/docs/api/java/util/TreeMap.html#TreeMap%28java.util.Comparator%29

            话虽如此,但你想做的事丑得要命,而且是非法的,因为: * 顺序将与equals()不一致,这是SortedSet的必要条件) * 由于 Map 中的值发生变化,顺序可能会发生变化,我不知道它的实现是否允许这样做。

            我认为你需要别的东西。也许你最好创建一个既有键又有值的对象,并正确实现equals()、hashcode()和Comparable,并使用SortedSet。


            编辑:我已经回答了一般问题(对键和值进行排序),而没有查看您的示例。正如其他人所写,地图中不能有重复的键。

            【讨论】:

              【解决方案9】:

              你不能有这样的地图

               1->11
               1->21
              

              键 '1' 很常见,所以 21 将取代 11

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-06-07
                • 2015-11-07
                • 2017-09-29
                • 2014-12-14
                • 2013-10-31
                • 1970-01-01
                • 2013-05-14
                • 1970-01-01
                相关资源
                最近更新 更多