十分钟探讨map与hashmap的排序
来源:互联网 发布:淘宝福利晒图店家 编辑:程序博客网 时间:2024/06/05 19:29
今天遇到一个关于map排序的问题,做个笔记(^__^) 嘻嘻……
既然遇到了,就不如挖它祖坟看一看里面的究竟,说不定找到价值连城的古董或者什么的,也说不准,下面,我们就一起带着铲子和摸金校尉,一起去探个究竟吧^_^
老规矩,先上代码,有代码有真相,如下所示:
/** * * Created by zero on 2016-6-11 * */public class HashMapSort{ public static void main(String[] args) { Map<String, Object> map = new HashMap<String, Object>(); map.put("b", 1 + ""); map.put("cds", 1 + ""); map.put("daac", 23 + ""); map.put("ass", 3 + ""); map.put("daaa", 21 + ""); map.put("f", 2 + ""); map.put("daaz", 25 + ""); map.put("e", 22 + ""); List<Map.Entry<String, Object>> list = new ArrayList<Map.Entry<String, Object>>( map.entrySet()); Collections.sort(list, new Comparator<Map.Entry<String, Object>>() { public int compare(Entry<String, Object> o1, Entry<String, Object> o2) {// // 按key升序排序 return o1.getKey().compareTo(o2.getKey());// // 按key降序排序// return o2.getKey().compareTo(o1.getKey());// // 把value转化成String升序排序// return ((String) o1.getValue()).compareTo((String) o2.getValue());// // 把value转化成String降序排序// return ((String) o2.getValue()).compareTo((String) o1.getValue()); } }); for (Map.Entry<String, Object> mapping : list) { System.out.println(mapping.getKey() + "=" + mapping.getValue()); } }}
我们采用的是key的升序排序,执行后的结果是这个样子的
ass=3b=1cds=1daaa=21daac=23daaz=25e=22f=2
那很多人要说了,我们的产品需要的是降序或者是value排序,那也很简单,只要改return那行代码就好,但是有一点要强调的是,compareTo前后的数据类型要一致,String、Long、Integer等都支持,或者更准确的说,只要实现Comparable接口的都支持,这个接下来会举例分析,现在,我们先看下sort这个函数,在Collections中有两个sort方法,如下所示:
public static <T extends Comparable<? super T>> void sort(List<T> list) { Object[] a = list.toArray(); Arrays.sort(a); ListIterator<T> i = list.listIterator(); for (int j=0; j<a.length; j++) { i.next(); i.set((T)a[j]); } }public static <T> void sort(List<T> list, Comparator<? super T> c) { Object[] a = list.toArray(); Arrays.sort(a, (Comparator)c); ListIterator<T> i = list.listIterator(); for (int j=0; j<a.length; j++) { i.next(); i.set((T)a[j]); } }
第一个sort方法,是根据元素的自然顺序对指定列表按升序进行排序。列表中的所有元素都必须实现 Comparable 接口(根据刚刚的介绍,是不是想到了什么?String、Long、Integer等,当然,也可以自己手写去实现接口)。此外,列表中的所有元素都必须是可相互比较的(也就是说,对于列表中的任何 e1 和 e2 元素,e1.compareTo(e2) 不得抛出 ClassCastException)。
此排序方法具有稳定性:不会因调用 sort 方法而对相等的元素进行重新排序。
指定列表必须是可修改的,但不必是大小可调整的。
该排序算法是一个经过修改的合并排序算法(其中,如果低子列表中的最高元素小于高子列表中的最低元素,则忽略合并)。此算法提供可保证的 n log(n) 性能。 此实现将指定列表转储到一个数组中,并对数组进行排序,在重置数组中相应位置处每个元素的列表上进行迭代。这避免了由于试图原地对链接列表进行排序而产生的 n2 log(n)(PS:此处2为平方,忘记平方怎么打了,O(∩_∩)O~) 性能。
我们着重看下第二个sort方法,参数:
·list - 要排序的列表。
·c - 确定列表顺序的比较器。null 值指示应该使用元素的自然顺序。
抛出:
·ClassCastException - 如果列表中包含不可使用指定比较器相互比较 的元素。
·UnsupportedOperationException - 如果指定列表的列表迭代器不支持 set 操作。
根据指定比较器产生的顺序对指定列表进行排序。此列表内的所有元素都必须可使用指定比较器相互比较(也就是说,对于列表中的任意 e1 和 e2 元素,c.compare(e1, e2) 不得抛出 ClassCastException)。
此排序被保证是稳定的:不会因调用 sort 而对相等的元素进行重新排序。
排序算法是一个经过修改的合并排序算法(其中,如果低子列表中的最高元素小于高子列表中的最低元素,则忽略合并)。此算法提供可保证的 n log(n) 性能。 指定列表必须是可修改的,但不必是可大小调整的。此实现将指定列表转储到一个数组中,并对数组进行排序,在重置数组中相应位置每个元素的列表上进行迭代。这避免了由于试图原地对链接列表进行排序而产生的 n2 log(n) 性能。
下面,我们在通过最初代码将Object转换成String,通过value降序排序,就像上述说所得那样,只要打开return就ok,如下:
public class HashMapSort{ public static void main(String[] args) { Map<String, Object> map = new HashMap<String, Object>(); map.put("b", 1 + ""); map.put("cds", 1 + ""); map.put("daac", 23 + ""); map.put("ass", 3 + ""); map.put("daaa", 21 + ""); map.put("f", 2 + ""); map.put("daaz", 25 + ""); map.put("e", 22 + ""); List<Map.Entry<String, Object>> list = new ArrayList<Map.Entry<String, Object>>( map.entrySet()); Collections.sort(list, new Comparator<Map.Entry<String, Object>>() { public int compare(Entry<String, Object> o1, Entry<String, Object> o2) {// // 按key升序排序// return o1.getKey().compareTo(o2.getKey());// // 按key降序排序// return o2.getKey().compareTo(o1.getKey());// // 把value转化成String升序排序// return ((String) o1.getValue()).compareTo((String) o2.getValue());// // 把value转化成String降序排序 return ((String) o2.getValue()).compareTo((String) o1.getValue()); } }); for (Map.Entry<String, Object> mapping : list) { System.out.println(mapping.getKey() + "=" + mapping.getValue()); } }}
运行结果
ass=3daaz=25daac=23e=22daaa=21f=2b=1cds=1
这个value降序排序是不是有点出乎想象?我们采用的是Object转String,这真的是value降序排序吗?带着这个疑问去打开String源码找到compareTo方法,如下所示:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {..................省略太多代码,只看核心代码.......................public int compareTo(String anotherString) { int len1 = value.length; int len2 = anotherString.value.length; int lim = Math.min(len1, len2); char v1[] = value; char v2[] = anotherString.value; int k = 0; while (k < lim) { char c1 = v1[k]; char c2 = v2[k]; if (c1 != c2) { return c1 - c2; } k++; } return len1 - len2; }}
如果自己打开源码,上面会有一些注释,大致意思是按字典顺序比较两个字符串。该比较基于字符串中各个字符的 Unicode 值。按字典顺序将此 String 对象表示的字符序列与参数字符串所表示的字符序列进行比较。如果按字典顺序此 String 对象位于参数字符串之前,则比较结果为一个负整数。如果按字典顺序此 String 对象位于参数字符串之后,则比较结果为一个正整数。如果这两个字符串相等,则结果为 0;compareTo 只在方法 equals(Object) 返回 true 时才返回 0。
今天的笔记到此为止,一不小心又是凌晨了,这篇只是简单浏览了一遍,没做过多检查,如有错误,欢迎批评指正,好困,睡觉了(~﹃~)~zZ
- 十分钟探讨map与hashmap的排序
- Map 与 HashMap 的区别
- Map与HashMap的关系
- 《Map中HashMap与TreeMap的排序以及四种遍历方式》
- Map的实现类HashMap与IdentityHashMap
- Map与HashMap,Hashtable,HashSet的区别
- Map与HashMap和Set的区别
- Map与HashMap,Hashtable,HashSet的区别
- Map与HashMap,Hashtable,HashSet的区别
- Map与hashMap
- Map-HashMap与TreeMap
- Java中对Map(HashMap,TreeMap,Hashtable等)的排序
- 关于map的数据排序问题(hashmap,treemap)
- java 对map或hashmap排序的两种方法
- Java中对Map(HashMap,TreeMap,Hashtable等)的排序
- map和list的用法:HashMap排序(二)
- stl hashmap与map hashmap与hashtable
- stl hashmap与map hashmap与hashtable
- bzoj4538【HNOI2016】网络
- ES6允许块级作用域的任意嵌套
- AngularJS 风谲云诡的指令
- arm驱动linux异步通知与异步IO
- 各大json的使用
- 十分钟探讨map与hashmap的排序
- MySQL与NULL值有关的问题
- Div+CSS 规则整理 以及注意问题
- 中国未来十年可能因战争而惨不忍睹
- 游程编码与哈弗曼编码结合的压缩解压(c语言)
- 2016 大学老友小聚
- Keil(MDK-ARM)系列教程(二)_工具栏详细说明
- Android-LayoutInflater学习
- 如何开发java语言