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

java Map 按value排序

2015-06-17 10:30 1016 查看
当我们需要统计一个字符串中每个字符的出现次数时,一般的做法是我们会使用一个HashMap<String, Integer>来统计每一个字符的出现次数,进一步的要求,我们需要基于统计次数进行排序,这时就需要针对value来进行排序,如何实现,下面描述两种思路。

无论哪种思路都需要实现一个比较器,比较器我们知道有comparable和comparator两种,一个是extends使用,一个是implements使用,具体两者的比较这里不说了,本文需要使用comparator,至于为什么这里也不解释了。自定义comparator的代码如下:

static class ByValueComparator implements Comparator<String> {
HashMap<String, Integer> base_map;

public ByValueComparator(HashMap<String, Integer> base_map) {
this.base_map = base_map;
}

public int compare(String arg0, String arg1) {
if (!base_map.containsKey(arg0) || !base_map.containsKey(arg1)) {
return 0;
}

if (base_map.get(arg0) < base_map.get(arg1)) {
return 1;
} else if (base_map.get(arg0) == base_map.get(arg1)) {
return 0;
} else {
return -1;
}
}
}
思路1:创建一个TreeMap结构,使用上述比较器作为构造函数参数。具体代码如下

ByValueComparator cmp = new ByValueComparator(m);
TreeMap<String, Integer> sorted_map = new TreeMap<String, Integer>(cmp);
sorted_map.putAll(m);
for (String name : sorted_map.keySet()) {
System.out.printf("%s -> %d\n", name, m.get(name));
}
默认情况下TreeMap是按照key进行比较的,当然前提是Key的类型必须是可比较的不然编译器报错(基本上原始类型的封装类型都是可以比较的,若是自定义类型,择需要实现比较器了)。这里我们构造的时候没有使用默认的情况,而是传人自定义的比较器。那么在执行putAll的时候,就会按照自定义的比较器实现元素的插入操作,实现我们希望的基于Value排序。

但是上述方案实际上有一个问题,就是value的值可能是相同的,这个时候转换为TreeMap相同value的元素就只能保留一个,比如有两个Value都是4,那么TreeMap中则只会有一个Value=4的元素了,具体原因实际是和TreeMap的实现有关系的,因为TreeMap是基于比较来决定元素的位置的,而我们构造的比较器是基于值的比较,当值相同的时候,TreeMap就认为这个是相同的元素,从而导致了上述的结果。

思路2:基于value集合创建一个List,然后将List排序,具体代码如下

// 第二种方法
List<String> keys = new ArrayList<String>(m.keySet());
Collections.sort(keys, cmp);
for(String key : keys) {
System.out.printf("%s -> %d\n", key, m.get(key));
}
这个思路实现按value排序不会有问题,先按照value集合,对value进行排序,然后基于重排序的集合获取value的值和相应的key。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: