第七章 泛型与集合.docx
- 文档编号:26615018
- 上传时间:2023-06-20
- 格式:DOCX
- 页数:25
- 大小:25.81KB
第七章 泛型与集合.docx
《第七章 泛型与集合.docx》由会员分享,可在线阅读,更多相关《第七章 泛型与集合.docx(25页珍藏版)》请在冰豆网上搜索。
第七章泛型与集合
第七章泛型与集合
7.1重写hashCode()和equals()方法
考试目标6.2区分hashCode()和equals()方法的正确设计和错误设计,并解释==和equals()方法的不同。
toString()方法
刚没有重写toString方法时,显示该对象哈希码的无符号十六进制表示。
如:
TestObject@a47e0.如果重写了该方法,则会显示该对象有意义的输出。
例如System.out.println(Obj)的时候,就会出去toString方法中定义的行为。
SCJP考试拥有的Object类方法:
booleanequals(Objectobj)
voidfinalize()
inthashCode()
finalvoidnotify()
finalvoidnotifyAll()
finalvoidwait()
StringtoString()
7.1.1重写equals()方法
使用==来判断两个引用变量是否引用了同一个对象。
使用equals()来判断两个对象在意义上是否等价。
不重写equals()意味着什么?
Object类的equals()方法只适用==运算符进行比较。
这样比较片面。
即只有当两个引用都引用了同一个对象,才被认为是相等的。
如果不重写equals(),则不同的对象不能认为是等价的。
如果不重写equals(),则对象将不会是有用的哈希键。
总之,如果不重写,则equals()只使用==运算符进行比较。
Java代码
publicclassTestEquals{
publicstaticvoidmain(String[]args){
TestEqualst1=newTestEquals();
TestEqualst2=newTestEquals();
System.out.println(t1.toString());
System.out.println(t2.toString());
System.out.println(t1==t2);
System.out.println(t1.equals(t2));
}
}
//result:
//testGenerics.TestEquals@35ce36
//testGenerics.TestEquals@757aef
//false
//false
实现equals()方法
Java代码
publicclassTestEquals2{
privateintid;
publicintgetId(){
returnid;
}
publicvoidsetId(intid){
this.id=id;
}
publicbooleanequals(Objecto){
if((oinstanceofTestEquals2)&&(this.id==((TestEquals2)o).getId())){
returntrue;
}else{
returnfalse;
}
}
publicstaticvoidmain(String[]args){
TestEquals2t1=newTestEquals2();
t1.setId
(1);
TestEquals2t2=newTestEquals2();
t2.setId
(1);
TestEquals2t3=newTestEquals2();
t3.setId
(2);
System.out.println(t1.toString());
System.out.println(t2.toString());
System.out.println(t1==t2);
System.out.println(t1.equals(t2));
System.out.println(t1.equals(t3));
}
}
//result:
//testGenerics.TestEquals2@35ce36
//testGenerics.TestEquals2@757aef
//false
//true
//false
一定要注意,重写equals(),hashcode(),toString()方法时,要注意变元类型,而且他们都是Public的。
publicbooleanequals(Boob),这个是对equals的重载,不是重写,因为变元不是Object。
equals()契约
自反的对于任何引用值x,x.equals(x)都应该返回true。
对称的对于任何引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才返回true。
传递的对于任何引用值x,y,z,如果x.equals(y)返回true时,并且y.equals(z)返回true。
一致的对于任何引用值x和y,如果在该对象上的相等性比较中所使用的信息没有做修改,则对x.equals(y)的多次调用要一致地返回true或者false。
对于变元为null的都应返回false
7.1.2重写hashCode()方法
理解哈希码
一个类的许多对象,根据同一算法生成的值分类(分桶),当查找时,先由hashCode()算出值,确定在哪个哈希桶里。
不同的对象可能有相同的哈希值;重写过equals方法的相同对象,应该有一样的哈希值。
实现hashCode()方法
说白了就是怎样的hashCode算法,都返回一个默认值,比如1932,这样的做法是“合法的”,但是并不合适。
这就相当于把所有的对象都放在了一个桶中,并没有达到分类、管理对象的目的。
“适当的”方法是将如id等,能代表对象唯一性等的属性加入到hashCode的算法中,尽可能的将各个桶平衡。
hashCode()契约
在Java应用程序的同一个执行期间,如果没有修改对象的equals()比较内使用的任何信息,则无论什么时候在相同的对象上多次调用hashCode()方法时,它必须一致地返回同一个整数。
对于应用程序的一次执行合同一个应用程序的另一次执行,这个证书不需要保持一致。
如果equals()方法两个对象是相等的,则在这两个对象的任意一个上调用hashCode()方法,必须产生相同的整数结果。
如果根据equals()方法两个对象是不相等的,则在这两个对象的任意一个上调用hashCode()方法,并不要求产生不同的整数结果。
然而程序员应该知道,为不相等的对象产生不同的整数结果可能提高哈希表的性能。
transient变量容易和equals(),hashcode()混淆.所以transient变量最好不要用来用作哈希码或者进行相等性的比较。
7.2集合
考试目标6.1给定一个设计场景,判断应该使用哪些集合类和/或接口来恰当地实现该设计,包括使用Comparable接口。
7.2.1用集合做什么
将对象添加到集合。
从集合中删除对象。
找出一个对象(或一组对象)是否位于集合内。
从集合中检索对象(不删除它)。
迭代遍历集合,逐个查看每个元素(对象)。
集合框架的重点接口和类
collection表示概念上的集合。
Collection表示java.util.Collection接口,Set、List和Queue扩展自它。
Map并不扩展自它。
Collections表示java.util.Collections类,它拥有大量的静态实用工具方法,用于集合。
集合的4种基本形式:
List事物列表(实现List的类)
Set具有唯一性的事物(实现Set的类)
Map具有唯一ID的事物(实现Map的类)
Queue按照被处理的顺序排列的事物
ordered(有序的,有秩序的,有先来后到的)
表示该集合能够按照特定的顺序(而不是随机的顺序)迭代遍历这个集合。
sorted(已排序,有顺序的,有顺序规则的)
表示集合中的顺序是根据某个或某些规则确定的。
除了自然排序外,还可以定义Comparable接口制定的自然顺序,以及另一个接口comparator定义其他的不同排序顺序
sorted顺序于以下因素无关:
对象何时被添加到集合中;对象最后一次被访问的时间,对象被添加到的“位置”
7.2.2List接口
List关心的是索引。
ArrayList
可以将它理解成一个可增长的数组。
它不是同步的。
它提供快速迭代和快速随机访问的能力。
Vector
它就是个同步的ArrayList,线程安全。
LinkedList
迭代比ArrayList慢,但适合用来快速插入和删除。
在Java5中,其实现了Queue接口,这样就支持常见的队列方法:
peek(),poll(),offer().
7.2.3Set接口
Set关心唯一性,它不允许重复
HashSet
HashSet是一种unsorted、unordered的Set。
它使用被插入对象的哈希码,因此,hashCode()实现越有效,将得到的访问性能就越好。
、
速度访问,保证没有重复,不提供任何顺序。
LinkedHashSet
是HashSet的ordered版本,按照插入顺序迭代
当使用hashset或者linkedhashset时,添加到他们的对象必须重写hashcode()方法。
否则,将允许多个在意义上相等的对象添加到不允许重复的集合中去
TreeSet
是sorted的,按照元素的自然顺序进行升序排列。
或者构造一个带构造函数的TreeSet,它让你通过使用Comparable或Comparator为集合提供自己的规则。
通过add()方法加入的元素必须事先实现comparable接口才可以进行,不然会抛出异常,如果两个元素使用comparable比较相等的话,则两个元素再用Size()方法计算的时候算一个
7.2.4Map接口
Map关心唯一的标识符
HashMap
最快速地更新键/值对。
允许一个null键和多个null值。
Hashtable
HashMap的同步版本,不允许null键或null值。
LinkedHashMap
迭代更快,按照插入顺序或者最后访问的顺序迭代。
允许一个null键和多个null值。
TreeMap
一种排序映射。
是sorted的
7.2.5Queue接口
PriortyQueue
按照元素的优先级排序的“待执行任务”的列表。
优先进优先出
类MapSetListorderedsorted
HashMapx否否
Hashtablex否否
TreeMapxsorted按照自然顺序或自定义比较规则
LinkedHashMapx按照插入顺序或最后的访问顺序否
HashSetx否否
TreeSetxsorted按照自然顺序或自定义比较规则
LinkedHashSetx按照插入顺序否
ArrayListx按照索引否
Vectorx按照索引否
LinkedListx按照索引否
PriorityQueuesorted按照“要执行的任务”的顺序
7.3使用集合框架
7.3.1ArrayList基础
与数组相比,ArrayList建立时不用指定长度,可以动态增长,提供更加强大的插入和查找机制。
7.3.2用集合进行自动装箱
Java5中,可以将集合中的基本类型自动装箱为包装类型。
7.3.3排序集合与数组
排序集合
Java代码
importjava.util.ArrayList;
importjava.util.Collections;
publicclassTestSort1{
publicstaticvoidmain(String[]args){
ArrayList
stuff.add("Denver");
stuff.add("Boulder");
stuff.add("Vail");
stuff.add("Aspen");
stuff.add("Telluride");
System.out.println("unsorted"+stuff);
Collections.sort(stuff);//自然排序
System.out.println("sorted"+stuff);
}
}
Java代码
unsorted[Denver,Boulder,Vail,Aspen,Telluride]
sorted[Aspen,Boulder,Denver,Telluride,Vail]
Comparable接口
Comparable接口由Collections.sort()方法和java.util.Arrays.sort()方法用来分别排序List和对象数组。
要实现java.lang.Comparable,类必须实现一种方法compareTo()。
下面是compareTo()的调用:
intx=thisOpareTo(anotherObj);
该方法返回如下int结果:
负数,如果thisObj 零,如果thisObj==anotherObj 正数,如果thisObj>anotherObj 总之,实现compareTo()就是制定对象排序的标准。 当重写equals()时,必须带有一个类型为Object的变元,但当重写compareTo(),应该带有的变元类型是正在排序的类型 用Comparator排序 Collections.sort()还有一个重载: publicstatic Comparator superT>c) Comparable接口和Comparator接口的比较 java.lang.Comparablejava.util.Comparator intobjOpareTo(objTwo)intcompare(objOne,objTwo) 返回: 负数,如果objOne 零,如果objOne==objTwo 正数,如果objOne>objTwo相同 必须修改想排序其实例的类构建一个类,它不同于想排序其实例的类,但是该类要实现comparator 只可以创建一个排序序列可以创建多个排序序列 在API中经常由如下方式实现: String、包装器类、Date、Calendar 意味着要实现成排序第三方类的实例 comparable必须修改想排序其实例的类,也就是将该类要实现comparable<>接口,实现compareTo()方法,就像String实现了该接口,所以直接直接按照Collections.sort()方法排序String对象的list.不过此时只有compareTo()这一种排序方法。 classDVDInfoimplementsComparable{ //othercodes publicintcompareTo(Objecto){ DVDInfod=(DVDInfo)o; returnpareTo(d.getTitle()); } } 使用泛型之后,就是 classDVDInfoimplementsComparable //othercodes publicintcompareTo(DVDInfod){ returnpareTo(d.getTitle()); } } 如果采用Compatator,那么要创建一个新的类用于比较,如下: classGenreSortimplementscomparator publicintcompare()//实现该方法 } 然后,在排序时,可以collections.sort(dvdlist,gs),而comparable是直接用collections.sort(dvdlist),但是dvdlist实现了comparable的compareTo(). 用Arrays类排序 Arrays.sort(arrayToSort) Arrays.sort(arrayToSort,Comparator) Collections和Arrays的sort()方法都是静态方法,也就是它们修改正在排序的对象,而不是返回不同的排序对象 查找数组与集合 staticintbinarySearch(Object[]ar,Objectkey) 方法返回两种结果,如果在数组ar中查到了key,则返回key的索引值;否则返回插入点。 插入点与索引值: 插入点: -1-2-3-4-5-(n+1)-(n+2) 数组: ar[0]ar[1]ar[2]ar[3]...............ar[n] 索引值: 0123n Java代码 packagetestGenerics; importjava.util.Arrays; importjava.util.Comparator; publicclassSearchObjArray{ publicstaticvoidmain(String[]args){ String[]sa={"one","two","three","four"}; Arrays.sort(sa);//#1 for(Strings: sa){ System.out.print(s+""); } System.out.println("\none="+Arrays.binarySearch(sa,"one"));//#2 System.out.println("nowreversesort"); ReSortComparatorrs=newReSortComparator();//#3 Arrays.sort(sa,rs); for(Strings: sa){ System.out.print(s+""); } System.out.println("\none="+Arrays.binarySearch(sa,"one"));//#4 System.out.println("one="+Arrays.binarySearch(sa,"one",rs));//#5 } staticclassReSortComparatorimplementsComparator publicintcompare(Stringa,Stringb){ returnpareTo(a);//#7 } } } //result: //fouronethreetwo //one=1 //nowreversesort //twothreeonefour //one=-1 //one=2 /* *#1: 按字母顺序(自然顺序)排序sa数组。 *#2: 查找元素“one”的位置,该位置为1. *#3: 创建一个Comparator实例。 下一行使用comparator重新排序数组。 *#4: 尝试查找数组。 我们没有将用于排序数组的Comparator传递给binarySearch()方法, *因此,获得一个不正确的(不明确的)答案。 因为此时数组使用comparator进行了排序,所以在查找时也要将comparator作为参数传过去。 *#5: 再次查找,将Comparator传递给binarySearch()。 这次获得了正确答案2. *#6: 定义Comparator,这里让它称为一个内部类是可行的。 *#7: 通过在调用compareTo()中变元的交换使用,得到反向的排序。 */ 被查找的数组/集合必须在能够查找之前进行排序,无论是自然排序还是使用comparator排序。 如果查找的集合/数组以自然顺利排序,则查找时候要按照自然顺序进行查找,在使用方法的时候不用传入comparator变元。 如果查找的数组/集合使用comparator进行排序,那么必须使用相同的comparator作为参数传入至binarySearch()方法进行查找,不传入的话不会出错,但只会返回-1。 成功的查找返回所查找元素的int索引值,不成功的返回一个int索引值,表示插入点。 如果实际插入点是N,实际返回的插入点是(-(N)-1).例如,如果查找的插入点位于元素2,则返回的实际插入点将是-3. 在数组和List之间进行转换: Arrays.asList() List.toArray() 使用List 可以通过Iterator迭代器来遍历List,Iterator的两个方法: booleanhasNext() Objectnext() 要尽量使用泛型,例如遍历List 使用Set 当使用实现Set的类时,希望集合中不存在重复集合。 HashSet非常快,add()相同的元素会返回false。 TreeSet是经过排序的,因此add()中的元素也必须是可以比较的。 否则就是ClassCastException。 使用Map 当使用实现map的类时,用作该映射的键的一部分的任何类都必须重写hashCode()和equals()方法。 当用作键的对象的值发生变化时,考虑两阶段检索可能是有用的: 首先使用hashcode()方法找到正确的桶,然后使用equals()方法找到桶中的对象。 枚举是重写了equals()和hashCode(). 7.3.4导航(查找)TreeSet与TreeMap TreeSet和TreeMap实现了Java6的新接口java.util.NavigableSet和java.util.NavigableMap 现在
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第七章 泛型与集合 第七 集合