treemap.docx

上传人:b****7 文档编号:9008042 上传时间:2023-02-02 格式:DOCX 页数:14 大小:18.53KB
下载 相关 举报
treemap.docx_第1页
第1页 / 共14页
treemap.docx_第2页
第2页 / 共14页
treemap.docx_第3页
第3页 / 共14页
treemap.docx_第4页
第4页 / 共14页
treemap.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

treemap.docx

《treemap.docx》由会员分享,可在线阅读,更多相关《treemap.docx(14页珍藏版)》请在冰豆网上搜索。

treemap.docx

treemap

treemap

我们知道HashMap的存储位置是按照key这个对象的hashCode来存放的,而TreeMap则是不是按照hashCode来存放,他是按照实现的Comparable接口的compareTo这个方法来存储的,

只要compareTo的返回结果为0就表示两个对象相等,那么就存不进去两个对象,后put的就把前面的覆盖掉,甚至我们都不用重写equasls和hashCode方法,而

只需要实现Comparable接口来重写comparareTo方法就行了,但是我们不能保证在应用中不会用到HashMap,所以保持良好的习惯,当我们定义了一个对象之后习惯性的

重写equals和hashCode方法。

本文比较详细的解释了TreeMap、Comparable、Comparator这三者的关联。

  测试Comparable接口:

  第一次比较:

定义一个User类,实现Comparable接口,按照年龄排序,我们让equals为true,而hashCode也始终相等。

publicclassUserimplementsComparable{

privateStringid;

privateStringname;

privateIntegerage;

publicUser(){

}

publicUser(Stringid,Stringname,Integerage){

super();

this.id=id;

this.name=name;

this.age=age;

}

publicStringgetId(){

returnid;

}

publicvoidsetId(Stringid){

this.id=id;

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicIntegergetAge(){

returnage;

}

publicvoidsetAge(Integerage){

this.age=age;

}

@Override

publicStringtoString(){

return"User[name="+name+",age="+age+"]";

}

@Override

publicbooleanequals(Objectobj){

returntrue;

}

@Override

publicinthashCode(){

return0;

}

publicintcompareTo(Usero){

returnthis.age>o.getAge()?

1:

this.age==o.getAge()?

0:

-1;

}

}

  测试代码:

publicclassTestUser{

publicstaticvoidmain(String[]args){

MapuserHashMap=newHashMap();

Useruser1=newUser("1","Jay",30);

Useruser2=newUser("2","Jolin",21);

Useruser3=newUser("3","JackCheng",22);

Useruser4=newUser("4","BruceLee",22);

userHashMap.put(user1,100);

userHashMap.put(user2,200);

userHashMap.put(user3,300);

userHashMap.put(user4,400);

System.out.println(userHashMap);

MapuserTreeMap=newTreeMap();

userTreeMap.put(user1,100);

userTreeMap.put(user2,200);

userTreeMap.put(user3,300);

userTreeMap.put(user4,400);

System.out.println(userTreeMap);

}

}

结果

{User[name=Jay,age=30]=400}

{User[name=Jolin,age=21]=200,User[name=JackCheng,age=22]=400,User[name=Jay,age=30]=100}

1

2

3

  结论:

对于HashMap而言,只要key的equals相等就表示两个元素相等,HashMap就存不进去;而TreeMap是不管equals和hashCode的,只要compareTo相等就表示两个元素相同,就存不进去。

  2.第二次比较:

现在我们按照id来重写hashCode和equals方法,如下:

@Override

publicinthashCode(){

finalintprime=31;

intresult=1;

result=prime*result+((id==null)?

0:

id.hashCode());

returnresult;

}

@Override

publicbooleanequals(Objectobj){

if(this==obj)

returntrue;

if(obj==null)

returnfalse;

if(getClass()!

=obj.getClass())

returnfalse;

Userother=(User)obj;

if(id==null){

if(other.id!

=null)

returnfalse;

}elseif(!

id.equals(other.id))

returnfalse;

returntrue;

}

测试代码不变,还是上面的测试代码,结果:

{User[name=Jolin,age=21]=200,User[name=Jay,age=30]=100,User[name=BruceLee,age=22]=400,User[name=JackCheng,age=22]=300}

{User[name=Jolin,age=21]=200,User[name=JackCheng,age=22]=400,User[name=Jay,age=30]=100}

1

2

说明:

HashMap只要equals不等那就表示不等,而对于TreeMap如果compareTo相等,那么2个元素就相等,并且排序是按照compareTo方法定义的排序规则。

接下来再在测试代码里面添加List测试:

ListuserList=newArrayList();

userList.add(user1);

userList.add(user2);

userList.add(user3);

userList.add(user4);

System.out.println(userList);

Collections.sort(userList);

System.out.println(userList);

结果:

{User[name=Jolin,age=21]=200,User[name=Jay,age=30]=100,User[name=BruceLee,age=22]=400,User[name=JackCheng,age=22]=300}

{User[name=Jolin,age=21]=200,User[name=JackCheng,age=22]=400,User[name=Jay,age=30]=100}

[User[name=Jay,age=30],User[name=Jolin,age=21],User[name=JackCheng,age=22],User[name=BruceLee,age=22]]

[User[name=Jolin,age=21],User[name=JackCheng,age=22],User[name=BruceLee,age=22],User[name=Jay,age=30]]

当调用sort方法之后List里面的元素就按照age排序了。

对于Comparator,一种叫做策略模式的设计模式,我们在User中实现Comparable接口,重写里面的方法,可以实现对User按age排序,这个排序算法是

存在于User内部的,换句话说User和排序算法是相互依存的,User只能用compareTo这个算法,而compareTo算法也只能为User服务,那么如果我们其他

地方也有同样的需求,就只能再实现一次Comparable,来为另外一个对象服务,这就有点重复的感觉,而且代码没有得到复用,样子对象和算法混在一

起耦合性很强,于是希望把算法和模型分离出来,让算法单独存在,不同的对象可以使用同一个算法,并且二者是分离的,没有混为一体。

当然可以分

开那必然还是可以放在一起的。

用一句比较专业点的话来讲就是策略模式有两个特点:

1.封装变化。

2.变成中使用接口而不实现接口。

如果我再说得直白一点,策略模式就是一种面向接口编程的思想。

这点在多线程里面也有所体现,就是为什么我们在开启新线程的时候要newThread(Runnable接口),

参数传接口而不推荐去继承Thread,虽然也可以继承,这也是体现面向对象的封装特性,将run的算法和线程分离,可以实现run所在类的复用,虽然一般都不会去复用,

当然这里还有一点就是Java只能单继承,如果继承了Thread就不能在继承其他的类。

此时我们的User是按照age排序,那如果想按照名字排序呢,那就没办法了,

但是如果将算法分离出来,需要用名字排序我们就传用名字排序的算法进去,需要用age排序就传age排序算法进去。

环境持有接口引用,通过set方法将接口实现

传入到环境,在环境中来调用接口方法,这完完全全是面向接口的特点。

下面的第一个例子就是存放在一起的,因为TreeMap的构造方法其中就有一个是待Comparator

接口参数的构造方法,该参数只要实现了Comparator接口就行,如下:

publicTreeMap(Comparator

superK>comparator){

parator=comparator;

}

举例:

有一个Person类,实现了Comparator接口,并且按照岁数排序:

publicclassPersonimplementsComparator{

privateStringid;

privateStringname;

privateIntegerage;

publicPerson(){

}

publicPerson(Stringid,Stringname,Integerage){

this.id=id;

this.name=name;

this.age=age;

}

publicStringgetId(){

returnid;

}

publicvoidsetId(Stringid){

this.id=id;

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicIntegergetAge(){

returnage;

}

publicvoidsetAge(Integerage){

this.age=age;

}

@Override

publicStringtoString(){

return"Person[name="+name+",age="+age+"]";

}

@Override

publicinthashCode(){

finalintprime=31;

intresult=1;

result=prime*result+((id==null)?

0:

id.hashCode());

returnresult;

}

@Override

publicbooleanequals(Objectobj){

if(this==obj)

returntrue;

if(obj==null)

returnfalse;

if(getClass()!

=obj.getClass())

returnfalse;

Personother=(Person)obj;

if(id==null){

if(other.id!

=null)

returnfalse;

}elseif(!

id.equals(other.id))

returnfalse;

returntrue;

}

publicintcompare(Persono1,Persono2){

returno1.getAge()>o2.getAge()?

1:

o1.getAge()==o2.getAge()?

0:

-1;

}

}

测试:

publicclassTestPerson{

publicstaticvoidmain(String[]args){

MappersonHashMap=newHashMap();

Personperson1=newPerson("1","Jay",30);

Personperson2=newPerson("2","Jolin",21);

Personperson3=newPerson("3","JackCheng",22);

Personperson4=newPerson("4","BruceLee",22);

personHashMap.put(person1,100);

personHashMap.put(person2,200);

personHashMap.put(person3,300);

personHashMap.put(person4,400);

System.out.println(personHashMap);

MappersonTreeMap=newTreeMap(newPerson());

personTreeMap.put(person1,100);

personTreeMap.put(person2,200);

personTreeMap.put(person3,300);

personTreeMap.put(person4,400);

System.out.println(personTreeMap);

}

}

结果:

{Person[name=Jolin,age=21]=200,Person[name=Jay,age=30]=100,Person[name=BruceLee,age=22]=400,Person[name=JackCheng,age=22]=300}

{Person[name=Jolin,age=21]=200,Person[name=JackCheng,age=22]=400,Person[name=Jay,age=30]=100}

1

2

依然是compara方法相等的元素表示相同,只能存放一个进去,并且是按照age排序的。

在List中的结果:

publicclassTestPerson{

publicstaticvoidmain(String[]args){

MappersonHashMap=newHashMap();

Personperson1=newPerson("1","Jay",30);

Personperson2=newPerson("2","Jolin",21);

Personperson3=newPerson("3","JackCheng",22);

Personperson4=newPerson("4","BruceLee",22);

personHashMap.put(person1,100);

personHashMap.put(person2,200);

personHashMap.put(person3,300);

personHashMap.put(person4,400);

System.out.println(personHashMap);

MappersonTreeMap=newTreeMap(newPerson());

personTreeMap.put(person1,100);

personTreeMap.put(person2,200);

personTreeMap.put(person3,300);

personTreeMap.put(person4,400);

System.out.println(personTreeMap);

ListpersonList=newArrayList();

personList.add(person1);

personList.add(person2);

personList.add(person3);

personList.add(person4);

System.out.println(personList);

Collections.sort(personList,newPerson());

System.out.println(personList);

}

}

结果:

{Person[name=Jolin,age=21]=200,Person[name=Jay,age=30]=100,Person[name=BruceLee,age=22]=400,Person[name=JackCheng,age=22]=300}

{Person[name=Jolin,age=21]=200,Person[name=JackCheng,age=22]=400,Person[name=Jay,age=30]=100}

[Person[name=Jay,age=30],Person[name=Jolin,age=21],Person[name=JackCheng,age=22],Person[name=BruceLee,age=22]]

[Person[name=Jolin,age=21],Person[name=JackCheng,age=22],Person[name=BruceLee,age=22],Person[name=Jay,age=30]]

调用sort方法前没排序,而调用之后按照age排序了。

其实将算法和模型分离也非常类似,只需要将实现Comparator接口的类单独拿出去就ok了。

现在定义Person类,不实现Comparator接口,而将SortPerson类来

实现该接口,其实就是用SortPerson类代替之前TreeMap中的参数,之前的参数是实现了Comparator接口的Person对象。

Person类:

publicclassPerson{

privateStringid;

privateStringname;

privateIntegerage;

publicPerson(){

}

publicPerson(Stringid,Stringname,Integerage){

this.id=id;

this.name=name;

this.age=age;

}

publicStringgetId(){

returnid;

}

publicvoidsetId(Stringid){

this.id=id;

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicIntegergetAge(){

returnage;

}

publicvoidsetAge(Integerage){

this.age=age;

}

@Override

publicStringtoString(){

return"Person[name="+name+",age="+age+"]";

}

@Override

publicinthashCode(){

finalintprime=31;

intresult=1;

result=prime*result+((id==null)?

0:

id.hashCode());

returnresult;

}

@Override

publicbooleanequals(Objectobj){

if(this==obj)

returntrue;

if(ob

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1