如果我们需要一个有序的Map,我们会使用TreeMap进行存储。TreeMap默认是按照key值升序进行排序的,如数字、ASCII。
如果我们需要对TreeMap按值进行排序的话,可以实例化Comparator接口,在TreeMap的构造方法中当作参数传入。这里遇到了问题:当插入TreeMap的两条数据value值一样的时候,后一条数据会覆盖前一条数据。
通过查资料发现,原因是实例化Comparator接口的时候,相当于自己实现了一个比较器,而TreeMap的插入与取出都是会经过比较器的。以如下代码为例:
base就是我们需要按值排序的Map,在ValueComparator的构造方法中传入。然后在下面的compare方法中,value1与value2就是根据o1和o2取到的value值,其中o1与o2都是Map的key值。当o1与o2的value值不一样的时候,会返回1与-1,代表着排序关系。而当他们的value值一样的时候,需要对o1和o2的进行排序关系的判断。当取出数据的时候,过程是一样的,需要根据get方法中的参数对TreeMap中的数据对TreeMap进行遍历判断,如果相等则返回0,并且get方法会返回相等的那个对象,如果不等,就搜索下一节点并进行判断,知道遍历完整个TreeMap。
这里就很明显了,如果两个key值一样的对象插入到TreeMap中时,由于插入的时候进行判断返回的结果为0,后一个插入的对象会覆盖在TreeMap中存储的对象。
如果我们需要对TreeMap按值进行排序的话,可以实例化Comparator接口,在TreeMap的构造方法中当作参数传入。这里遇到了问题:当插入TreeMap的两条数据value值一样的时候,后一条数据会覆盖前一条数据。
通过查资料发现,原因是实例化Comparator接口的时候,相当于自己实现了一个比较器,而TreeMap的插入与取出都是会经过比较器的。以如下代码为例:
- public class ValueComparator implements Comparator<Object>{
- Map<Object, Object> base;
- public ValueComparator(Map<Object, Object> map){
- this.base = map;
- }
- @Override
- public int compare(Object o1, Object o2) {
- Integer value1 = Integer.parseInt(base.get(o1.toString()).toString());
- Integer value2 = Integer.parseInt(base.get(o2.toString()).toString());
- if ((value2 - value1) > 0) {
- return 1;
- }else if (value2 - value1 ==0) {
- return o2.toString().compareTo(o1.toString());
- }else {
- return -1;
- }
- }
- }
public class ValueComparator implements Comparator<Object>{
Map<Object, Object> base;
public ValueComparator(Map<Object, Object> map){
this.base = map;
}
@Override
public int compare(Object o1, Object o2) {
Integer value1 = Integer.parseInt(base.get(o1.toString()).toString());
Integer value2 = Integer.parseInt(base.get(o2.toString()).toString());
if ((value2 - value1) > 0) {
return 1;
}else if (value2 - value1 ==0) {
return o2.toString().compareTo(o1.toString());
}else {
return -1;
}
}
}
base就是我们需要按值排序的Map,在ValueComparator的构造方法中传入。然后在下面的compare方法中,value1与value2就是根据o1和o2取到的value值,其中o1与o2都是Map的key值。当o1与o2的value值不一样的时候,会返回1与-1,代表着排序关系。而当他们的value值一样的时候,需要对o1和o2的进行排序关系的判断。当取出数据的时候,过程是一样的,需要根据get方法中的参数对TreeMap中的数据对TreeMap进行遍历判断,如果相等则返回0,并且get方法会返回相等的那个对象,如果不等,就搜索下一节点并进行判断,知道遍历完整个TreeMap。
这里就很明显了,如果两个key值一样的对象插入到TreeMap中时,由于插入的时候进行判断返回的结果为0,后一个插入的对象会覆盖在TreeMap中存储的对象。
以上转自:http://blog.csdn.net/u012434091/article/details/38276807
自己项目中用的treemap:
//treeMap排序代码
public AppCacheDataManager() {
metaMap = new TreeMap<String,AppMetaData>(newMyComparator());
appList = new Vector<String>();
this.comm= HistoryClient.build();
userInfoMap = new HashMap<String,AmUserInfo>();
}
public static class MyComparator implementsComparator {
public int compare(Objecto1, Object o2) {
String s1 = (String) o1;
String s2 = (String) o2;
String str1 = s1.replace('_','-');
String str2 = s2.replace('_','-');
return str2.compareTo(str1);
// app_user_20161111152008_1928 与app-user-20161111152008-1930去掉前面"app_user_9"个字符, // 和后面"_1928"5个或6个字符之后再比较。前面方法不好使,所以直接把_转为-再排序
}
}