如何对Java HashMap进行排序

时间:2020-01-09 10:35:04  来源:igfitidea点击:

Java中的HashMap根据插入的(键,值)对的键计算哈希,并根据该键存储其元素。因此,HashMap本质上是一个无序的集合,但是当我们想用Java对HashMap进行排序时,我们可能会遇到一种情况。

HashMap的排序既可以按键也可以按值进行,在本文中,我们将介绍基于Java键或者值对HashMap进行排序的方法。

在键上对HashMap排序

如果必须对Java中的键对HashMap进行排序,最简单的选择是将HashMap转换为TreeMap。

TreeMap根据其键的自然顺序或者在创建地图时提供的Comparator进行排序,具体取决于所使用的构造函数。如果要根据其键的自然顺序对HashMap进行排序,则可以使用TreeMap类的以下构造函数。

TreeMap(Map <?扩展K ,?扩展V> m)–构造一个新的树图,该树图包含与给定图相同的映射,并根据其键的自然顺序进行排序。

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class SortMap {
  public static void main(String[] args) {
    // Creating HashMap
    Map<String, String> empMap = new HashMap<String, String>();
    // Storing elements
    empMap.put("E01", "Hyman");
    empMap.put("E02", "Amy");
    empMap.put("E11", "Harvey");
    empMap.put("E45", "Mike");
    System.out.println("** Unsorted Map **");
    for(Map.Entry<String, String> emp : empMap.entrySet()) {
      System.out.println("Key- " + emp.getKey() + 
                  " Value- " + emp.getValue());
    }
       
    TreeMap<String, String> sortedEmpMap = new TreeMap<>(empMap);
    System.out.println("** Map sorted by keys **");
    for(Map.Entry<String, String> emp : sortedEmpMap.entrySet()) {
      System.out.println("Key- " + emp.getKey() + 
             " Value- " + emp.getValue());
    }
  }
}

输出:

** Unsorted Map **
Key- E11 Value- Harvey
Key- E02 Value- Amy
Key- E01 Value- Hyman
Key- E45 Value- Mike
** Map sorted by keys **
Key- E01 Value- Hyman
Key- E02 Value- Amy
Key- E11 Value- Harvey
Key- E45 Value- Mike

按值对HashMap排序

为了对值上的Java HashMap进行排序,我们必须将HashMap转换为Set,然后对该Set进行排序。为了对Set进行排序,我们再次有两个选项将该Set转换为List或者TreeSet。

如果只希望按排序顺序排列Map的值,那么将Map的值转换为TreeSet是最简单的选择。

public class SortMap {
  public static void main(String[] args) {
    // Creating HashMap
    Map<String, String> empMap = new HashMap<String, String>();
    // Storing elements
    empMap.put("E01", "Hyman");
    empMap.put("E02", "Amy");
    empMap.put("E11", "Harvey");
    empMap.put("E45", "Mike");
    System.out.println("** Unsorted Map **");
    for(Map.Entry<String, String> emp : empMap.entrySet()) {
        System.out.println("Key- " + emp.getKey() + " Value- " + emp.getValue());
    }
    // Creating a TreeSet         
    Set<String> empSet = new TreeSet<String>(empMap.values());
    System.out.println("** Sorted Set **");
    for(String emp : empSet) {
      System.out.println(" Value- " + emp);
    }
  }
}

输出:

** Unsorted Map **
Key- E11 Value- Harvey
Key- E02 Value- Amy
Key- E01 Value- Hyman
Key- E45 Value- Mike
** Sorted Set **
 Value- Amy
 Value- Harvey
 Value- Hyman
 Value- Mike

如我们所见,对值进行了排序,唯一的缺点是现在有了Set而不是Map,因为现在只存储了值。

如果希望使用Map作为对Java中的HashMap进行排序的最终结果,则该过程会有些冗长。

  • 创建一个指定比较器进行排序的TreeSet。
  • 通过使用addAll()方法将HashMap的条目集转换为TreeSet。在这一步,我们有一个包含Map.entry元素的排序集。
  • 创建一个LinkedHashMap来存储排序后的值。在这里使用LinkedHashMap是因为它维护插入顺序。
  • 迭代TreeSet并将值放入创建的LinkedHashMap中。
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

public class SortMap {
  public static void main(String[] args) {
    // Creating HashMap
    Map<String, String> empMap = new HashMap<String, String>();
    // Storing elements
    empMap.put("E01", "Hyman");
    empMap.put("E02", "Amy");
    empMap.put("E11", "Harvey");
    empMap.put("E45", "Mike");
    System.out.println("** Unsorted Map **");
    for(Map.Entry<String, String> emp : empMap.entrySet()) {
      System.out.println("Key- " + emp.getKey() + " Value- " + emp.getValue());
    }
    // Creating a treeset with comparator
    Set<Map.Entry<String, String>> empSet = new TreeSet<Map.Entry<String, String>>(new EmpComparator());
    // Adding the entry set to a TreeSet
    empSet.addAll(empMap.entrySet());
    System.out.println("** Sorted Set **");
    for(Map.Entry<String, String> emp : empSet) {
      System.out.println("Key- " + emp.getKey() + " Value- " + emp.getValue());
    }
    // Using LinkedHashMap to maintain insertion order
    Map<String, String> sortedEmpMap = new LinkedHashMap<>();
    // Insert values in LinkedHashMap
    for(Map.Entry<String, String> emp : empSet) {
      sortedEmpMap.put(emp.getKey(), emp.getValue());
    }
    System.out.println("** Map Sorted by Values **");
    for(Map.Entry<String, String> emp : sortedEmpMap.entrySet()) {
      System.out.println("Key- " + emp.getKey() + " Value- " + emp.getValue());
    }
  }
}
// Comparator class
class EmpComparator implements Comparator<Map.Entry<String, String>>{
  @Override
  public int compare(Map.Entry<String, String> entry1, Map.Entry<String, String> entry2) {
    return entry1.getValue().compareTo(entry2.getValue());
  }    
}

输出:

** Unsorted Map **
Key- E11 Value- Harvey
Key- E02 Value- Amy
Key- E01 Value- Hyman
Key- E45 Value- Mike
** Sorted Set **
Key- E02 Value- Amy
Key- E11 Value- Harvey
Key- E01 Value- Hyman
Key- E45 Value- Mike
** Map Sorted by Values **
Key- E02 Value- Amy
Key- E11 Value- Harvey
Key- E01 Value- Hyman
Key- E45 Value- Mike

除了TreeSet,还可以使用ArrayList来存储Map.Entry元素。在这种情况下,我们可以使用Collections.sort(list,new EmpComparator())对值进行排序。