Java对HashMap按key排序和按value排序

HashMap的值是没有顺序的,它是按照key的HashCode来实现的。对于这个无序的HashMap我们要怎么来实现排序呢?(TreeMap类似)

一、按key进行排序

对Key进行排序大致步骤如下:

(1)为了提供一个对Key排序普遍适用的方法,我们使用泛型,并且由于要对K进行排序,所以我们需要限定K所代表的类实现了Comparable接口

(2)首先需要得到HashMap中的包含映射关系的视图(entrySet)

(3)将entrySet转换为List,然后重写比较器对list中的entry进行排序即可。这里可以使用List.sort(comparator),也可以使用Collections.sort(list,comparator)

(4)如果需要返回一个有序的Map,可以把排序后的按照排序后的List将entry中的元素添加到LinkedHashMap中返回即可。

代码实现
public class MapSorter {

    //Map按key进行升序排序
    public static <K extends Comparable<? super K>,V> Map<K,V> sortMapByKeyAscend(Map<K,V> map){
        ArrayList<Map.Entry<K,V>> entries=new ArrayList<>(map.entrySet());
        entries.sort((o1,o2)-> (o1.getKey().compareTo(o2.getKey())));
        Map<K,V> sortedMap=new LinkedHashMap<>();
        for(Map.Entry<K,V> entry:entries){
            sortedMap.put(entry.getKey(),entry.getValue());
        }
        return sortedMap;
    }

    //Map按key进行降序排序
    public static <K extends Comparable<? super K>,V> Map<K,V>  sortMapByKeyDescend(Map<K,V> map){
        ArrayList<Map.Entry<K,V>> entries=new ArrayList<>(map.entrySet());
        entries.sort((o1,o2)-> -(o1.getKey().compareTo(o2.getKey())));
        Map<K,V> sortedMap=new LinkedHashMap<>();
        for(Map.Entry<K,V> entry:entries){
            sortedMap.put(entry.getKey(),entry.getValue());
        }
        return sortedMap;
    }
}    

测试:

public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Jack", 52);
        map.put("Mary", 75);
        map.put("Zoom", 48);
        map.put("Huang", 55);
        map.put("Wang", 76);
        System.out.println("对key升序排序:");
        Map<String, Integer> sortedKeyAscendMap = MapSorter.sortMapByKeyAscend2(map);
        sortedKeyAscendMap.forEach((k,v)->{
            System.out.print(k+":"+v+" ");
        });
        System.out.println("\n对key降序排序:");
        Map<String, Integer> sortedKeyDescendMap = MapSorter.sortMapByKeyDescend2(map);
        sortedKeyDescendMap.forEach((k,v)->{
            System.out.print(k+":"+v+" ");
        });
    }                                                                              

执行main方法,得到如下输出:

Java源码中对Map的key排序的支持

其实在Java的Map接口的源码中已经提供了对Key和Map进行排序的方法:

  • comparingByKey
  • comparingByValue
  • comparingByKey(Comparator<? super K> cmp)
  • comparingByValue(Comparator<? super V> cmp)

这几个方法都只是返回一个对应的Comparator,我们拿到这个Comparator就可以对Map进行排序操作了。下面是一个简单使用示例:

public class MapSorter {

    //Map按key进行升序排序
    public static <K extends Comparable<? super K>,V> Map<K,V> sortMapByKeyAscend(Map<K,V> map){
        ArrayList<Map.Entry<K,V>> entries=new ArrayList<>(map.entrySet());
        //就是这里省略了自定义Comparator,其余的都一样
        Comparator<Map.Entry<K,V>> keyComparator=Map.Entry.comparingByKey();
        entries.sort(keyComparator);
        Map<K,V> sortedMap=new LinkedHashMap<>();
        for(Map.Entry<K,V> entry:entries){
            sortedMap.put(entry.getKey(),entry.getValue());
        }
        return sortedMap;
    }

    //Map按key进行降序排序
    public static <K extends Comparable<? super K>,V> Map<K,V>  sortMapByKeyDescend(Map<K,V> map){
        ArrayList<Map.Entry<K,V>> entries=new ArrayList<>(map.entrySet());
        Comparator<Map.Entry<K, V>> keyComparator = Map.Entry.comparingByKey(
             (o1,o2)->-(o1.compareTo(o2)));
        entries.sort(keyComparator);
        Map<K,V> sortedMap=new LinkedHashMap<>();
        for(Map.Entry<K,V> entry:entries){
            sortedMap.put(entry.getKey(),entry.getValue());
        }
        return sortedMap;
    }
} 

二、按value进行排序

弄明白了对key的排序之后,对value的排序也就水到渠成了,不同的是现在我们需要限定V所代表的类实现了Comparable接口,下面是简单实现:

public class MapSorter {

    //Map按value进行升序排序
    public static <K,V extends Comparable<? super V>> Map<K,V> sortMapByValueAscend(Map<K,V> map){
        ArrayList<Map.Entry<K,V>> entries = new ArrayList<>(map.entrySet());
        entries.sort((o1, o2) -> o1.getValue().compareTo(o2.getValue()));
        Map<K,V> sortedMap=new LinkedHashMap<>();
        for(Map.Entry<K,V> entry:entries){
            sortedMap.put(entry.getKey(),entry.getValue());
        }
        return sortedMap;
    }

    //Map按value进行降序排序
    public static <K,V extends Comparable<? super V>> Map<K,V> sortMapByValueDescend(Map<K,V> map){
        ArrayList<Map.Entry<K,V>> entries = new ArrayList<>(map.entrySet());
        entries.sort((o1, o2) -> -(o1.getValue().compareTo(o2.getValue())));
        Map<K,V> sortedMap=new LinkedHashMap<>();
        for(Map.Entry<K,V> entry:entries){
            sortedMap.put(entry.getKey(),entry.getValue());
        }
        return sortedMap;
    }

}

测试

public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Jack", 52);
        map.put("Mary", 75);
        map.put("Zoom", 48);
        map.put("Huang", 55);
        map.put("Wang", 76);
        System.out.println("对value升序排序:");
        Map<String, Integer> sortedValueAscendMap = MapSorter.sortMapByValueAscend(map);
        sortedValueAscendMap.forEach((k,v)->{
            System.out.print(k+":"+v+" ");
        });
        System.out.println("\n对value降序排序:");
        Map<String, Integer> sortedValueDescendMap = MapSorter.sortMapByValueDescend(map);
        sortedValueDescendMap.forEach((k,v)->{
            System.out.print(k+":"+v+" ");
        });
 }

运行main方法,输出如下结果:

同理,对Map的value排序也可以直接使用Map接口中提供的几个方法,这里不再尝试,有兴趣的小伙伴可以自行尝试。这里有必要在强调的是,我的例子中的Map的key和value的类型是String、Integer这些Java内部提供的类,这些类都是实现了Comparable接口的,所以程序中可以正常使用,但是如果你的Key或value是一个自定义的类型,比如Student,Person等,如果要对这些类型排序的话,必须实现Comparable接口,不然就会出错。

参考

留言区

还能输入500个字符