前言
我们知道,HashMap不会对键进行排序,而TreeMap会对键进行排序,当然这两者还有很多其他的区别,本文为了保持主题一致,只考虑排序的影响因素,当然本文实际上没有经过其他参考资料验证,也是在自己使用HashMap与TreeMap时所产生的疑惑,并且记录下来,比如当两者的key为integer时,两者都会对键进行排序,而对字符串、自定义类型却会体现不同。而网上探讨角度过于深奥,也许原因会与深层的机制有关,本人也不是很了解就不献丑了,在此仅演示一下两者的实例。
当然若有错误欢迎批评指正。
键为整形(Integer)
HashMap自动排序的情况
当hashmap的键的最大值与第二大的键相差小于16时(不包括16),hashmap会自动排序
package Lab7;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
// Treemap会对键进行排序,而HashMap不会
public class Lab7_3 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
HashMap<Integer, String>mp=new HashMap<Integer,String>();
mp.put(11, "bna");
mp.put(2, "apple");
mp.put(1, "banana");
mp.put(3, "chel");
mp.put(5, "d");
mp.put(4, "e");
mp.put(7, "f");
mp.put(6, "g");
mp.put(8, "h");
mp.put(10, "l");
mp.put(9, "o");
System.out.println(mp);
Set<Integer>set=mp.keySet();
Iterator<Integer>it=set.iterator();
for (Integer i : mp.keySet()) {
System.out.println("key: "+i+" value:"+mp.get(i));
}
TreeMap<Integer, String>MP=new TreeMap<Integer,String>();
MP.put(11, "bna");
MP.put(2, "apple");
MP.put(1, "banana");
MP.put(3, "chel");
MP.put(5, "d");
MP.put(4, "e");
MP.put(7, "f");
MP.put(6, "g");
MP.put(8, "h");
MP.put(10, "l");
MP.put(9, "o");
System.out.println(MP);
for (Integer i : MP.keySet()) {
System.out.println("key: "+i+" value:"+MP.get(i));
}
}
输出
{1=banana, 2=apple, 3=chel, 4=e, 5=d, 6=g, 7=f, 8=h, 9=o, 10=l, 11=bna}
key: 1 value:banana
key: 2 value:apple
key: 3 value:chel
key: 4 value:e
key: 5 value:d
key: 6 value:g
key: 7 value:f
key: 8 value:h
key: 9 value:o
key: 10 value:l
key: 11 value:bna
{1=banana, 2=apple, 3=chel, 4=e, 5=d, 6=g, 7=f, 8=h, 9=o, 10=l, 11=bna}
key: 1 value:banana
key: 2 value:apple
key: 3 value:chel
key: 4 value:e
key: 5 value:d
key: 6 value:g
key: 7 value:f
key: 8 value:h
key: 9 value:o
key: 10 value:l
key: 11 value:bna
可以看到,对于键为整形的映射关系,HashMap与TreeMap都会进行排序,这一点是众多教材都没有指出来的特殊情况,这一点也是我在实践中遇到的问题。
HashMap不会自动排序的情况
当hashmap键的最大值与第二大的键大于等于16时,hashmap不对该键进行排序,而其他小于16的键仍然会自动排序
package Lab6;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
// Treemap会对键进行排序,而HashMap不会
public class Lab6_1 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
HashMap<Integer, String>mp=new HashMap<Integer,String>();
mp.put(11, "bna");
mp.put(2, "apple");
mp.put(1, "banana");
mp.put(3, "chel");
mp.put(16, "ld");
mp.put(5, "d");
mp.put(4, "e");
mp.put(15, "we");
mp.put(17, "f");
mp.put(6, "g");
mp.put(32, "os");
mp.put(8, "h");
mp.put(10, "l");
mp.put(9, "o");
mp.put(12, "ll");
mp.put(13, "oo");
mp.put(14, "lsd");
System.out.println(mp);
Set<Integer>set=mp.keySet();
Iterator<Integer>it=set.iterator();
for (Integer i : mp.keySet()) {
System.out.println("key: "+i+" value:"+mp.get(i));
}
TreeMap<Integer, String>MP=new TreeMap<Integer,String>();
MP.put(11, "bna");
MP.put(2, "apple");
MP.put(1, "banana");
MP.put(3, "chel");
MP.put(16, "ld");
MP.put(5, "d");
MP.put(4, "e");
MP.put(15, "we");
MP.put(17, "f");
MP.put(6, "g");
MP.put(32, "os");
MP.put(8, "h");
MP.put(10, "l");
MP.put(9, "o");
MP.put(12, "ll");
MP.put(13, "oo");
MP.put(14, "lsd");
System.out.println(MP);
for (Integer i : MP.keySet()) {
System.out.println("key: "+i+" value:"+MP.get(i));
}
}
}
输出:
{32=os, 1=banana, 2=apple, 3=chel, 4=e, 5=d, 6=g, 8=h, 9=o, 10=l, 11=bna, 12=ll, 13=oo, 14=lsd, 15=we, 16=ld, 17=f}
key: 32 value:os
key: 1 value:banana
key: 2 value:apple
key: 3 value:chel
key: 4 value:e
key: 5 value:d
key: 6 value:g
key: 8 value:h
key: 9 value:o
key: 10 value:l
key: 11 value:bna
key: 12 value:ll
key: 13 value:oo
key: 14 value:lsd
key: 15 value:we
key: 16 value:ld
key: 17 value:f
{1=banana, 2=apple, 3=chel, 4=e, 5=d, 6=g, 8=h, 9=o, 10=l, 11=bna, 12=ll, 13=oo, 14=lsd, 15=we, 16=ld, 17=f, 32=os}
key: 1 value:banana
key: 2 value:apple
key: 3 value:chel
key: 4 value:e
key: 5 value:d
key: 6 value:g
key: 8 value:h
key: 9 value:o
key: 10 value:l
key: 11 value:bna
key: 12 value:ll
key: 13 value:oo
key: 14 value:lsd
key: 15 value:we
key: 16 value:ld
key: 17 value:f
key: 32 value:os
键为字符串
package Lab7;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
// Treemap会对键进行排序,而HashMap不会
public class Lab7_3 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
HashMap<String, String>mp=new HashMap<>();
mp.put("11", "bna");
mp.put("2", "apple");
mp.put("1", "banana");
mp.put("3", "chel");
mp.put("5", "d");
mp.put("4", "e");
mp.put("7", "f");
mp.put("6", "g");
mp.put("8", "h");
mp.put("10", "l");
mp.put("9", "o");
System.out.println(mp);
Set<String>set=mp.keySet();
Iterator<String>it=set.iterator();
for (String i : mp.keySet()) {
System.out.println("key: "+i+" value:"+mp.get(i));
}
TreeMap<String, String>MP=new TreeMap<String,String>();
MP.put("11", "bna");
MP.put("2", "apple");
MP.put("1", "banana");
MP.put("3", "chel");
MP.put("5", "d");
MP.put("4", "e");
MP.put("7", "f");
MP.put("6", "g");
MP.put("8", "h");
MP.put("10", "l");
MP.put("9", "o");
System.out.println(MP);
for (String i : MP.keySet()) {
System.out.println("key: "+i+" value:"+MP.get(i));
}
}
输出
{11=bna, 1=banana, 2=apple, 3=chel, 4=e, 5=d, 6=g, 7=f, 8=h, 9=o, 10=l}
key: 11 value:bna
key: 1 value:banana
key: 2 value:apple
key: 3 value:chel
key: 4 value:e
key: 5 value:d
key: 6 value:g
key: 7 value:f
key: 8 value:h
key: 9 value:o
key: 10 value:l
{1=banana, 10=l, 11=bna, 2=apple, 3=chel, 4=e, 5=d, 6=g, 7=f, 8=h, 9=o}
key: 1 value:banana
key: 10 value:l
key: 11 value:bna
key: 2 value:apple
key: 3 value:chel
key: 4 value:e
key: 5 value:d
key: 6 value:g
key: 7 value:f
key: 8 value:h
key: 9 value:o
可以看到,HashMap没有进行排序,而TreeMap会对字符串的首字符进行排序,如"1",“10”,“11"首字符都为"1”,根据ASCII码都小于"2"
为了更好的说明,下面的例子将键改为字母进行比较:
package Lab7;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
// Treemap会对键进行排序,而HashMap不会
public class Lab7_3 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
HashMap<String, String>mp=new HashMap<>();
mp.put("a", "bna");
mp.put("b", "apple");
mp.put("e", "banana");
mp.put("r3", "chel");
mp.put("t5", "d");
mp.put("s4", "e");
mp.put("fd7", "f");
mp.put("jf6", "g");
mp.put("l8", "h");
mp.put("o10", "l");
mp.put("p9", "o");
System.out.println(mp);
Set<String>set=mp.keySet();
Iterator<String>it=set.iterator();
for (String i : mp.keySet()) {
System.out.println("key: "+i+" value:"+mp.get(i));
}
TreeMap<String, String>MP=new TreeMap<String,String>();
MP.put("a", "bna");
MP.put("b", "apple");
MP.put("e", "banana");
MP.put("r3", "chel");
MP.put("t5", "d");
MP.put("s4", "e");
MP.put("fd7", "f");
MP.put("jf6", "g");
MP.put("l8", "h");
MP.put("o10", "l");
MP.put("p9", "o");
System.out.println(MP);
for (String i : MP.keySet()) {
System.out.println("key: "+i+" value:"+MP.get(i));
}
}
输出
{a=bna, r3=chel, t5=d, s4=e, b=apple, e=banana, fd7=f, p9=o, jf6=g, l8=h, o10=l}
key: a value:bna
key: r3 value:chel
key: t5 value:d
key: s4 value:e
key: b value:apple
key: e value:banana
key: fd7 value:f
key: p9 value:o
key: jf6 value:g
key: l8 value:h
key: o10 value:l
{a=bna, b=apple, e=banana, fd7=f, jf6=g, l8=h, o10=l, p9=o, r3=chel, s4=e, t5=d}
key: a value:bna
key: b value:apple
key: e value:banana
key: fd7 value:f
key: jf6 value:g
key: l8 value:h
key: o10 value:l
key: p9 value:o
key: r3 value:chel
key: s4 value:e
key: t5 value:d
可以看到,对于键为字符串的映射关系,TreeMap会对其进行ASCII码的比较进行排序,而HashMap则不会。
键为自定义类型
注意代码中对自定义类型重载了比较运算符,并重载了输出
package Lab7;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
// Treemap会对键进行排序,而HashMap不会
public class Lab7_3 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
HashMap<student, Integer>lovesHashMap=new HashMap<>();
lovesHashMap.put(new student("李白", 1), 2);
lovesHashMap.put(new student("王安石", 2), 3);
lovesHashMap.put(new student("格斯", 3), 4);
lovesHashMap.put(new student("嘎哈", 4), 5);
lovesHashMap.put(new student("李白1", 5), 6);
lovesHashMap.put(new student("李白2", 6), 7);
lovesHashMap.put(new student("李白3", 7), 8);
lovesHashMap.put(new student("李白4", 8), 9);
lovesHashMap.put(new student("李白5", 9), 10);
for (student stu : lovesHashMap.keySet()) {
System.out.println(stu);
}
System.out.println();
TreeMap<student, Integer>lmp=new TreeMap<>();
lmp.put(new student("李白", 1), 2);
lmp.put(new student("王安石", 2), 3);
lmp.put(new student("格斯", 3), 4);
lmp.put(new student("嘎哈", 4), 5);
lmp.put(new student("李白1", 5), 6);
lmp.put(new student("李白2", 6), 7);
lmp.put(new student("李白3", 7), 8);
lmp.put(new student("李白4", 8), 9);
lmp.put(new student("李白5", 9), 10);
for (student stu : lmp.keySet()) {
System.out.println(stu);
}
}
}
class student implements Comparable<student>{
public student(String nameString,int id) {
// TODO 自动生成的构造函数存根
this.nameString=nameString;
this.id=id;
}
private String nameString;
private int id;
@Override
public int compareTo(student arg0) {
// TODO 自动生成的方法存根
if(this.id>arg0.id)return 1;
else if(this.id<arg0.id)return -1;
return 0;
}
@Override
public String toString() {
// TODO 自动生成的方法存根
return "名字:"+nameString+" 学号为:"+id;
}
}
输出
名字:李白 学号为:1
名字:嘎哈 学号为:4
名字:李白1 学号为:5
名字:格斯 学号为:3
名字:李白4 学号为:8
名字:李白3 学号为:7
名字:王安石 学号为:2
名字:李白5 学号为:9
名字:李白2 学号为:6
名字:李白 学号为:1
名字:王安石 学号为:2
名字:格斯 学号为:3
名字:嘎哈 学号为:4
名字:李白1 学号为:5
名字:李白2 学号为:6
名字:李白3 学号为:7
名字:李白4 学号为:8
名字:李白5 学号为:9
可以看到TreeMap的键进行了排序,而HashMap的并没有
总结
- 对于键为integer,HashMap与TreeMap都会进行排序
- 对于键为String,自定义类型,TreeMap会对键进行排序,而HashMap则不会