关于HashMap排序的一点浅见

我们在对hashmap进行排序的时候存在一定的误解,首先在这更正下~

我在遇到这个问题的时候也上网查了相关的资料,发现大家在进行hashmap进行排序的时候存在一定的了解误区。



有很多人认为把hashmap遍历一下,然后对其中的key和value进行排序,然后打印出来~



大家想一想,这样的hashmap排序根本就不是对hashmap进行排序~最多也只能称为hashmap遍历,hashmap的遍历问题很简单,网上也有很多相关的资料,下面我给出一个例程:

1. public static void itHashMap(Map<Object, Object> m) {
2. Set set = m.entrySet();
3. Iterator it = set.iterator();
4. while(it.hasNext()) {
5. Map.Entry<Object, Object> me = (Map.Entry<Object, Object>)it.next();
6. System.out.println("key:" + me.getKey() + "----value" + me.getValue());
7. }
8. }



这个方法可以将hashmap遍历,并打印出相应的key和value!



其实,单纯的hashmap是无法实现排序的,我这里的排序是指,我们将键值对按照一定的顺序put进hashmap里,然后在进行取键值对的操作的时候,在按照put进去的顺序把键值对取出来。



下面我来浅显的解释下为什么不能排序.

1. HashMap<String, Date> hm = new HashMap<String, Date>();
2. hm.put("1", new Date(8,10,1));
3. hm.put("3", new Date(8,10,3));
4. hm.put("2", new Date(8,10,2));
5. hm.put("5", new Date(8,10,5));
6. hm.put("9", new Date(8,10,9));
7. hm.put("8", new Date(8,10,8));
8. hm.put("6", new Date(8,10,6));
9. hm.put("7", new Date(8,10,7));

我在hashmap里按照以上的顺序放入9个键值对,然后我遍历hashmap打印出上面hm里的键值对:

key:3----value:Tue Nov 03 00:00:00 CST 1908
key:5----value:Thu Nov 05 00:00:00 CST 1908
key:7----value:Sat Nov 07 00:00:00 CST 1908
key:2----value:Mon Nov 02 00:00:00 CST 1908
key:9----value:Mon Nov 09 00:00:00 CST 1908
key:8----value:Sun Nov 08 00:00:00 CST 1908
key:6----value:Fri Nov 06 00:00:00 CST 1908
key:1----value:Sun Nov 01 00:00:00 CST 1908

我们从上面的结果可以看出,取出来的顺序并我们想要的顺序!

hashmap在put的时候是根据key的hashcode进行hash然后放入对应的地方!通过Debug可以看到HashMap的存放位置,网上有很多人说是随即存放,随即取,其实不然,放的时候是根据hashcode经过 hash算法进行存放的,而我们取的时候也是想过key来取value。所以你取出来拍完序,在放入HashMap的时候哦,它又把顺序打乱了~~(这里说的打乱也不是完全没有规律可循的,主要是你根据你的key来放的)!



所以我们要实现HashMap排序的时候就要借用别的集合来完成这个功能!



基本的思路是这样的,首先遍历HashMap取出相应的键值对,然后根据key或者是value进行排序,然后放入一个有序的集合当中,这样就实现了排序!



java在JDK1.4以后提供了LinkedHashMap来帮我们实现了有序的HashMap!



LinkedHashMap取键值对的时,是按照你放入的顺序来取的!



具体的排序算法有很多种~也可以自己写个冒泡排序取排列~~



再排完序以后,我们要找到key对应的vluae或是value对应的key!找key对应的vluea的时候很简单,网上有很多资料,我这里就不说了~~关键说说找value对应的key的时候,有的朋友就不知道该怎么做了~~



下面我提供两种思路



一种是我们可以把value放入一个数组,key也放入一个数组,这样在排序的时候按照value排序的时候,我们把key的位置也交换一次,这样就保证了键值对的完整性,见例程:

1. private static void sortHashMap(HashMap<String, Date> hm) {
2.
3. List<Date> dateListSorted = new ArrayList<Date> ();
4.
5. int size = hm.size();
6. Date[] dates = new Date[size];
7. Set set = hm.keySet();
8. Iterator iteratorSet = set.iterator();
9. int k = 0;
10. while(iteratorSet.hasNext()) {
11. String keyStr = (String)iteratorSet.next();
12. System.out.println("key from set----" + keyStr);
13. if(keyStr!=null && !(keyStr.length()<1)) {
14. dates[k] = hm.get(keyStr);
15. k++;
16. }
17. System.out.println("value from hashmap----" + hm.get(keyStr));
18. }
19. iteratorList.next());
20. int sizeList = dates.length;
21. Object[] keyObj = set.toArray();
22. for(int i=0;i<sizeList;i++) {//冒泡排序
23. for(int j=i;j<sizeList;j++) {
24. if(dates[j].after(dates[i])) {
25. Date temp = dates[i];//交换value
26. dates[i] = dates[j];
27. dates[j] = temp;
28. Object objectTemp = keyObj[i];//交换key
29. keyObj[i] = keyObj[j];
30. keyObj[j] = objectTemp;
31. }
32.
33. }
34. }
35. for(int i=0;i<keyObj.length;i++) {
36. System.out.println("key from array sorted----" + keyObj[i]);
37. }
38. for(int i=0;i<dates.length;i++) {
39. System.out.println("value from list sorted----" + dates[i]);
40. }
41. LinkedHashMap lhm = new LinkedHashMap();
42. for(int i=0;i<keyObj.length;i++) {//把经过排序的键值对放入Linked中
43. lhm.put(keyObj[i], dates[i]);
44. }
45. /*
46. *遍历Linkedhashmap打印出结果
47. */
48. Set set1 = lhm.entrySet();
49. Iterator it = set1.iterator();
50. while(it.hasNext()) {
51. Map.Entry me = (Map.Entry)it.next();
52. System.out.println("key:" + me.getKey() + "----value" + me.getValue());
53. }
54. }

这种方法比较直观,可是效率比较低,而且对内存也很浪费,你想想,在这个过程中我们new了两个长度是hm.size()长度的数组,用于存放key和value,排序也是我们自己写的冒泡排序法~~



下面我介绍第二种方法:



第二种方法的思路是这样的,我们用hm.value()放回hm的vuale集合,再把它转换成一个数组,然后调用jdk给我们提供的Arrays.sort()方法去帮我们排序,这样效率会比自己写的冒泡排序法效率高的多!



在调用sort方法的时候我们需要写一个比较器,比较器的代码如下:





1. package com.mgoann.test1;
2.
3. import java.util.Comparator;
4. import java.util.Date;
5.
6. public final class DateComp implements Comparator {
7.
8. public int compare(Object o1, Object o2) {
9. Date date1 = (Date)o1;
10. Date date2 = (Date)o2;
11. return date2.compareTo(date1);
12. }
13.
14. }
15.

剩下的就是更具value去找相应的key的问题了~~这里我用了一个for循环和Iterator去查找hm里的key,找到以后我们就放到LinkedHashMap里~,详见例程:

1. package com.mgoann.test1;
2.
3. import java.util.Arrays;
4. import java.util.Collection;
5. import java.util.Comparator;
6. import java.util.Date;
7. import java.util.HashMap;
8. import java.util.Iterator;
9. import java.util.LinkedHashMap;
10. import java.util.Map;
11. import java.util.Set;
12.
13. public class Sort {
14.
15. /**
16. * @param args
17. */
18. public static void main(String[] args) {
19. HashMap<String, Date> hm = new HashMap<String, Date>();
20. LinkedHashMap<String, Date> linkedHM = new LinkedHashMap<String, Date>();
21. hm.put("1", new Date(8,10,1));
22. hm.put("3", new Date(8,10,3));
23. hm.put("2", new Date(8,10,2));
24. hm.put("5", new Date(8,10,5));
25. hm.put("9", new Date(8,10,9));
26. hm.put("8", new Date(8,10,8));
27. hm.put("6", new Date(8,10,6));
28. hm.put("7", new Date(8,10,7));
29. itHashMap(hm);
30. linkedHM = sortHashMap(hm);
31. itHashMap(linkedHM);
32. }
33.
34. private static LinkedHashMap sortHashMap(HashMap<String, Date> hm) {
35.
36. LinkedHashMap<String, Date> linkedHM = new LinkedHashMap<String, Date>();
37. final Comparator DATE_COMP = new DateComp();
38.
39. int index = 0;
40.
41. Collection<Date> DateColl = hm.values();
42. Object[] dates = DateColl.toArray();
43. Arrays.sort(dates, DATE_COMP);
44. System.out.println("dates after sorted");
45. printElements(dates);
46. Set set = hm.entrySet();
47. for(int j=0;j<dates.length;j++) {
48. Iterator it = set.iterator();
49. while(it.hasNext()) {
50. Map.Entry<String, Date> me = (Map.Entry<String, Date>)it.next();
51. if(dates[j].equals(me.getValue())) {
52. linkedHM.put(me.getKey(), me.getValue());
53. }
54. }
55. }
56. return linkedHM;
57. }
58.
59. public static void printElements(Collection c) {
60. Iterator it = c.iterator();
61. while(it.hasNext()) {
62. System.out.println(it.next());
63. }
64. }
65.
66. public static void printElements(Object[] dates) {
67. for(int i=0;i<dates.length;i++) {
68. System.out.println(dates[i]);
69. }
70. }
71.
72. public static void itHashMap(Map<String, Date> m) {
73. Set set = m.entrySet();
74. Iterator it = set.iterator();
75. while(it.hasNext()) {
76. Map.Entry<String, Date> me = (Map.Entry<String, Date>)it.next();
77. System.out.println("key:" + me.getKey() + "----value:" + me.getValue());
78. }
79. }
80. }

这样我们就实现了HashMap的排序问题!



程序运行结果如下:

key:3----value:Tue Nov 03 00:00:00 CST 1908
key:5----value:Thu Nov 05 00:00:00 CST 1908
key:7----value:Sat Nov 07 00:00:00 CST 1908
key:2----value:Mon Nov 02 00:00:00 CST 1908
key:9----value:Mon Nov 09 00:00:00 CST 1908
key:8----value:Sun Nov 08 00:00:00 CST 1908
key:6----value:Fri Nov 06 00:00:00 CST 1908
key:1----value:Sun Nov 01 00:00:00 CST 1908
dates after sorted
Mon Nov 09 00:00:00 CST 1908
Sun Nov 08 00:00:00 CST 1908
Sat Nov 07 00:00:00 CST 1908
Fri Nov 06 00:00:00 CST 1908
Thu Nov 05 00:00:00 CST 1908
Tue Nov 03 00:00:00 CST 1908
Mon Nov 02 00:00:00 CST 1908
Sun Nov 01 00:00:00 CST 1908
key:9----value:Mon Nov 09 00:00:00 CST 1908
key:8----value:Sun Nov 08 00:00:00 CST 1908
key:7----value:Sat Nov 07 00:00:00 CST 1908
key:6----value:Fri Nov 06 00:00:00 CST 1908
key:5----value:Thu Nov 05 00:00:00 CST 1908
key:3----value:Tue Nov 03 00:00:00 CST 1908
key:2----value:Mon Nov 02 00:00:00 CST 1908
key:1----value:Sun Nov 01 00:00:00 CST 1908
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值