对映射按键和值进行排序

4
我希望能够按照键和值对Map进行排序。首先按键排序,然后按值排序。例如,下面应该是结果:
1,2 1,3 2,1 2,2
有人有建议如何有效地实现这个功能吗?我看到一些人使用TreeMap对键进行排序,但我也需要值。
当然,欢迎采用任何其他基于键和值排序的方法。

最相关的问题似乎包含了很多想法。https://dev59.com/qXVD5IYBdhLWcg3wDG_m - Charles Goodwin
你是指某种“multimap”吗?如果是的话,它不在Java规范中。 - bezmax
9个回答

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

哇,这真是太高级了 :) 为什么我没想到呢.. :) - ferdyh

3

1

听起来你想要一个多映射类型的东西,例如:

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

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

0

这是不可能的,因为一个映射表不能包含重复的键。一个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);
  }
}

0

总体思路是将Map转换为List,对List进行排序,然后将排序后的List放回到Map中。

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

0
请按照以下代码进行操作: 此代码将首先按键排序,然后按值排序。 只需编写一个主方法并按以下方式调用此方法:
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());
        }
    }
}

1
你正在比较值,我猜那不是他想要的。 - Amessihel
是的,你说得对...我的帖子是要按键或值排序... :) - Spandan
我已经发布了另一个问题来获取我的答案:- https://stackoverflow.com/questions/54909215/sort-a-map-by-key-or-value-in-java/54909242#54909242 - Spandan

0

如果你愿意冒险,你可以使用允许你指定比较器的构造函数: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。


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


-1

你不能拥有这样的映射

 1->11
 1->21

键'1'是通用的,因此21将替换11


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接