集合框架2(HashSet,TreeSet,泛型)
HashSet:
HashSet中如果有两个对象有相同的哈希值,但是对象的内容不同,则在同一地址上顺延,都存在同一地址,HashSet打印只可以使用Iterator,但是打印出来的结果和存储的顺序未必一致
利用HashSet来存储自定义的对象,如果姓名和性别一致,则视为同一元素。
1: import java.util.*;
2:
3: class Person
4: {
5: private String name;
6: private int age;
7: Person(String name,int age)
8: {
9: this.name=name;
10: this.age=age;
11: }
12:
13: public int hashCode()
14: {
15: System.out.println(this.name+"...hashCode");
16: return 60;
17: }
18:
19: public boolean equals(Object obj)
20: {
21: if(!(obj instanceof Person))
22: return false;
23: Person p=(Person)obj;
24: System.out.println(this.name+".....equals..."+p.name);
25: return this.name.equals(p.name)&&this.age==p.age;
26: }
27: }
28:
29: class HashSetDemo
30: {
31: public static void main(String[] args)
32: {
33: HashSet hs=new HashSet();
34: hs.add(new Person("a1",11));
35: hs.add(new Person("a2",12));
36: hs.add(new Person("a3",13));
37:
38: }
39: }
HashSet是如何保证元素的唯一性的呢?
是通过元素的两个方面,hashCode和equals来完成的,如果元素的hashCode值相同,才会判断equals是否为true,如果元素的hashCode值不同,则不会调用equals方法。
对于判断元素是否存在,以及删除等操作,依据的方法就是元素的hashCode和equals方法。。
TreeSet:
当主要条件相同时,判断次要条件。
1: import java.util.*;
2:
3: class Student implements Comparable//该接口强制让学生具备比较性
4: {
5: private String name;
6: private int age;
7:
8: Student(String name,int age)
9: {
10: this.name=name;
11: this.age=age;
12: }
13:
14: public String getName()
15: {
16: return name;
17: }
18: public int getAge()
19: {
20: return age;
21: }
22:
23: //实现Comparable接口
24: public int compareTo(Object obj)
25: {
26: if(!(obj instanceof Student))
27: throw new RuntimeException("不是学生类对象");
28: Student s=(Student)obj;
29:
30: //首先比较年龄,如果年龄相同的话,则比较姓名
31: if(this.age>s.age)
32: return 1;
33: else if(this.age==s.age)
34: {
35: return this.name.compareTo(s.name);
36: }
37: else return -1;
38: }
39: }
40: class TreeSetDemo
41: {
42: public static void main(String[] args)
43: {
44: TreeSet ts=new TreeSet();
45:
46: ts.add(new Student("lisi02",22));
47: ts.add(new Student("lisi007",20));
48: ts.add(new Student("lisi09",19));
49: ts.add(new Student("lisi08",19));
50: ts.add(new Student("lisi11",40));
51: ts.add(new Student("lisi16",30));
52: ts.add(new Student("lisi12",36));
53: ts.add(new Student("lisi10",29));
54: ts.add(new Student("lisi22",90));
55:
56: Iterator it=ts.iterator();
57: while(it.hasNext())
58: {
59: Object obj=it.next();
60: Student s=(Student)obj;
61: System.out.println(s.getName()+"......."+s.getAge());
62: }
63:
64: }
65: }
66:
TreeSet集合的第二种排序方式:
当元素自身不具备比较性时,或者具备的比较性不是所需要的时,这时就需要让集合自身具备比较性。定义一个比较器Comparator,将比较器对象作为参数传递给TreeSet集合的构造函数。如果希望在上述代码的基础上,将TreeSet集合中的对象按照姓名进行排序,当比较器和CompareTo方法均存在时,以比较器为主。
1: class MyCompare implements Comparator
2: {
3: public int compare(Object o1,Object o2)
4: {
5: Student s1=(Student)o1;
6: Student s2=(Student)o2;
7:
8: int num=s1.getName().compareTo(s2.getName());
9: if(num==0)
10: return (s1.getAge()-s2.getAge());
11:
12: return num;
13: }
14:
15: }
泛型:
JDK1.5的新特性。用于解决安全问题。是一个安全机制。
ArrayList<String> al=new ArrayList<String> ( );<>中指定该集合存储的类型为String,这就是泛型。
好处:<1>将运行时期出现的问题,ClassCastException,转移到了编译时期,方便程序员解决问题,让运行时期的问题减少,安全
Itetator<String> it=al.iterator( );
<2>避免了强制转换的麻烦。
格式:通过<>来定义要操作的引用数据类型。当使用集合时,将集合中要存储的数据类型作为参数传递给<>中即可。
例如:class LenComparator implements Comparator<String>
泛型类:当类中操作的引用数据类型不确定时,早起定义Object类,现在定义泛型来完成扩展。泛型定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。public <T> void (T t),定义泛型方法,该定义只在该方法内有效。
静态方法不可以访问类上定义的泛型,如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。public static <T> void method(T t)
泛型定义在接口上:
1: interface Inter<T>
2: {
3: void show(T t);
4: }
5:
6: class InterImpl implements Inter<String>
7: //实现接口时要指定好操作的类型
8:
9: class InterImpl<T> implements Inter<T>
10: {
11: public void show(T t)
12: { }
13:
14: }
15: //实现接口时,不指定操作的类型。
泛型限定:当对象的类型不确定时,可以使用通配符来占位<?>
1:
2: class GenericDemo6
3: {
4: public static void main(String[] args)
5: {
6: ArrayList<String> al=new ArrayList<String>();
7:
8: al.add("abc1");
9: al.add("abc2");
10: al.add("abc3");
11:
12: ArrayList<Integer> al1=new ArrayList<Integer>();
13: al1.add(4);
14: al1.add(7);
15:
16: printColl(al);
17: printColl(al1);
18:
19: }
20:
21: public static void PrintColl(ArrayList<?> al)
22: {
23: Iterator<?> it=al.iterator();
24: while(it.hasNext())
25: {
26: System.out.println(it.next());
27: }
28: }
29: /*
30: public static<T> void printColl(ArrayList<T> al)
31: 如果写成这样,可以在方法内使用该类的引用,如T t=it.next();
32: 如果写成通配符的形式,则不可以使用类型的具体方法
33: */
34: public static void printColl_1(ArrayList<? extends Person> al)
35: {
36: Iterator<? extends Person> it=al.iterator();
37: while(it.hasNext())
38: {
39: System.out.println(it.next());
40: }
41:
42: }
43: /*
44: 泛型的限定:<1>? extends E:可以接收E类型获取E类型的子类型,上限
45: <2>? super E:可以接收E类型或者E类型的父类,下限
46: */
47: }