您的位置:首页 > 产品设计 > UI/UE

map key value的排序问题

2016-04-10 05:02 519 查看
  一、简单描述

Map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,HashTable以及LinkedHashMap等。

        TreeMap:能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的
Comparator 进行排序,具体取决于使用的构造方法。

        HashMap的值是没有顺序的,它是按照key的HashCode来实现的,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null(多条会覆盖);允许多条记录的值为
Null。非同步的。

        Map.Entry返回Collections视图。

        注:map简单的UML



二、排序的具体实现
(1)较简单的排序方式(直接根据key值进行比较),按key值排序

Map<String, String> map = new TreeMap<String, String>(new
Comparator<String>() {
public int compare(String obj1, String obj2) {
return obj1.compareTo(obj2);
}
});
map.put("b", "1111");
map.put("d", "2222");
map.put("c", "3333");
map.put("a", "4444");

for (Entry entry : map.entrySet()) {
System.err.println(entry.getKey() + "========" + entry.getValue());
}


TreeMap 接收的comparator的接口默认是key值的排序,源代码如下:

/**
* Constructs a new, empty tree map, ordered according to the given
* comparator.  All keys inserted into the map must be <em>mutually
* comparable</em> by the given comparator: {@code comparator.compare(k1,
* k2)} must not throw a {@code ClassCastException} for any keys
* {@code k1} and {@code k2} in the map.  If the user attempts to put
* a key into the map that violates this constraint, the {@code put(Object
* key, Object value)} call will throw a
* {@code ClassCastException}.
*
* @param comparator the comparator that will be used to order this map.
*        If {@code null}, the {@linkplain Comparable natural
*        ordering} of the keys will be used.
*/
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}



(2) 根据Map.Entry进行排序,即可实现key值的排序,也可以实现value值的排序

Map<String, String> map = new HashMap();
map.put("1", "b");
map.put("2", "a");
map.put("4", "e");
map.put("5", "c");
map.put("3", "d");
Set<Map.Entry<String, String>> keyEntries = new TreeSet<Map.Entry<String, String>>(
(Comparator<Map.Entry<String, String>>) (c1, c2) -> c1.getKey().compareTo(c2.getKey()));
keyEntries.addAll(map.entrySet());
for (Entry<String, String> entry : keyEntries) {
System.err.println(entry.getKey() + "----" + entry.getValue());
}

Set<Map.Entry<String, String>> valueEntries = new TreeSet<Map.Entry<String, String>>(
(Comparator<Map.Entry<String, String>>) (c1, c2) -> c1.getValue().compareTo(c2.getValue()));
valueEntries.addAll(map.entrySet());
for (Entry<String, String> entry : valueEntries) {
System.err.println(entry.getKey() + "----" + entry.getValue());
}


注:java8 在Map接口中的Entry接口中实现了根据key、value排序的接口,源代码如下:

public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getKey().compareTo(c2.getKey());
}
public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getValue().compareTo(c2.getValue());
}


(3)当要比较的key或者value 是一个对象的时候,你可以定义一个comparator进行排序,java8 在Map接口中的Entry接口有两个接收comparator的方法,源码如下:

public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
}
public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
}
}
例子:

Map<String, Person> personMap = new HashMap<String, Person>();
personMap.put("a", new Person(1, "aaa"));
personMap.put("acd", new Person(4, "acd"));
personMap.put("abc", new Person(3, "abc"));
personMap.put("eda", new Person(2, "eda"));
Set<Map.Entry<String, Person>> valueEntries = new TreeSet(Map.Entry.comparingByValue(new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.id - p2.id;
}
}));
// Set<Map.Entry<String, Person>> valueEntries = new
// TreeSet<Map.Entry<String, Person>>(
// new Comparator<Map.Entry<String, Person>>() {
//
// @Override
// public int compare(Entry<String, Person> o1, Entry<String, Person>
// o2) {
// Person p1 = o1.getValue();
// Person p2 = o2.getValue();
// return p1.id - p2.id;
// }
// });
valueEntries.addAll(personMap.entrySet());
for (Entry<String, Person> entry : valueEntries) {
System.err.println(entry.getKey() + "----" + entry.getValue().id);
}




结束语:这是学习源代码时个人的见解,如有不对的地方,请指正,不尽感激
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  map的键值排序