按值的字母顺序对HashMap进行排序

11

我有一个 HashMap<Object, Student>,其中 Object 是学生的 ID,而 Student 是来自 Student 类的对象。

我该如何通过学生的姓名 student->getName() 对 HashMap 进行重新排序?


这取决于作业“想”让你做什么。由于没有“排序”,也许它希望你按特定顺序显示/导出HashMap中的学生...无论如何,作业总是善变的。 - user166390
1
这是重复的问题,类似的问题已经在stackoverflow上被问过了,例如:https://dev59.com/dkrSa4cB1Zd3GeqPZcsM 和 http://stackoverflow.com/questions/2839003/sorting-in-hash-maps-in-java。 - BalusC
3
这一定是Java十大问题之一。 - Steve Kuo
HashMap不提供对自身进行排序的方法。因此,唯一的选择是获取所需的视图并对其进行排序。但请注意,从视图中删除也会从HashMap本身中删除。 - Volodymyr Levytskyi
5个回答

18
HashMaps本质上是无序的,不能进行排序。
相反,您可以使用SortedMap实现,例如TreeMap
然而,即使是有序映射也只能按其键进行排序。
如果要按值排序,则需要将它们复制到已排序列表中。

5

虽然无法对HashMap进行排序,但是可以通过一些方法达到同样的效果。我使用在Javarevisited博客上发布的优秀代码,按照Integer的降序值来排序我的HashMap <String, Integer>对象。相同的原理适用于HashMap<String,String>对象。

/*
 * Java method to sort Map in Java by value e.g. HashMap or Hashtable
 * throw NullPointerException if Map contains null values
 * It also sort values even if they are duplicates
 */
public static <K extends Comparable,V extends Comparable> Map<K,V> sortByValues(Map<K,V> map){
    List<Map.Entry<K,V>> entries = new LinkedList<Map.Entry<K,V>>(map.entrySet());

    Collections.sort(entries, new Comparator<Map.Entry<K,V>>() {

        @Override
        public int compare(Entry<K, V> o1, Entry<K, V> o2) {
            return o1.getValue().compareTo(o2.getValue());
            // to compare alphabetically case insensitive return this instead
            // o1.getValue().toString().compareToIgnoreCase(o2.getValue().toString()); 
        }
    });

    //LinkedHashMap will keep the keys in the order they are inserted
    //which is currently sorted on natural ordering
    Map<K,V> sortedMap = new LinkedHashMap<K,V>();

    for(Map.Entry<K,V> entry: entries){
        sortedMap.put(entry.getKey(), entry.getValue());
    }

    return sortedMap;
}

调用此方法,我使用:

Map<String, Integer> sorted = sortByValues(myOriginalHashMapObject);

了解更多信息:http://javarevisited.blogspot.com/2012/12/how-to-sort-hashmap-java-by-key-and-value.html#ixzz2akXStsGj

本文介绍如何在Java中通过键和值对HashMap进行排序。


2

地图无法按值排序。但您可以这样做:

Collection<Student> students = map.values();

Collection.sort(new ArrayList<Student>(students)), new Comparator<Student>() {
    public int compare(Student s1, Student s2) {
        return s1.getName().compareTo(s2.getName());
    }
});

假设您需要遍历这些值。(否则,为什么您会希望以这种方式排序呢?)祝好运。

TreeMaps是有序的。说一般情况下的地图无法排序并不完全准确。我知道原帖中说要使用HashMap,但你说的是Map,而不是HashMap。 - user439793
1
按键排序。我说的是按值排序,不是按键排序。 - Todd

0

HashMap 无法按其值进行排序。Map 是为基于键的常数时间查找而设计的,因此按值排序不是必要的。如果您需要按名称排序,建议使用 SortedSet 并创建一个按名称排序的比较器。

class StudentComparator implements Comparator<Student> {
    int compare(Student s1, Student s2) {
       return s1.getName().compareTo(s2.getName());
    }
}

如果您需要同时进行常数时间查找和按值排序的集合,那么您可能需要维护一个映射和一个集合。

是的,我假设学生总是有一个名字。 - Jeff Storey
1
而且学生本身不为空。 - SLaks

0

我肯定会使用一个新的类来存储键和对象。

然后,您可以将Map的每个元素以此类的形式放入ArrayList中,最后使用比较器对ArrayList进行排序,然后简单地构建一个新的Map。 代码将如下所示:

Map<Object, Student> valueMap = new LinkedHashMap<String, String>();
List<Student> pairValueList = new ArrayList<PairValue>();

PairValue p;
for (Map.Entry<Object, Student> entry : map.entrySet()) {
  Object key = entry.getKey();
  Student value = entry.getValue();        
  p = new PairValue(key, value);
  pairValueList.add(p);
 }

Collections.sort(pairValueList, new Comparator<PairValue>() {
  @Override
  public int compare(PairValue c1, PairValue c2) {
    return c1.getLabel().compareTo(c2.getLabel());
  }
});

for (PairValue pv : pairValueList) {
  valueMap.put(pv.getValue(), pv.getStudent());
}

PairValue类

    class PairValue {    

  private Object value;    
  private Student student;

  public PairValue(Object value, String student) {
    this.value = value;
    this.student= student;
  }

  public String getValue() {
    return value;
  }

  public String getStudent() {
    return student;
  }    
}

这是我解决过类似问题的方式。请注意,返回的 map 实现需要是一个 LinkedHashMap。


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