泛型-概述
如果在创建集合的时候,不写泛型会怎么样?
(图1
)
(图2
)
(图3
)
泛型概述
泛型:是 JDK5
中引入的特性,它提供了编译时类型安全检测机制
泛型的好处:
把运行时期的问题提前到了编译期间
避免了强制类型转换
Set-概述
集合类体系结构
(图4
)
Set-基本使用
Set集合概述和特点
Set
集合的特点
可以去除重复
存取顺序 不一致
没有带索引的方法,所以不能使用普通 for
循环遍历,也不能通过索引来获取/删除 set
集合里的元素
Set集合练习
存储字符串并遍历 (所有单列集合都可以使用迭代器进行遍历,所以 set
集合也可以使用)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MySet1 {
public static void main ( string [] args ) {
Set < String > set = new TreeSet ();
set . add ( "aaa" );
set . add ( "aaa" );
set . add ( "bbb" );
set . add ( "ccc" );
//for(int i = 0; i < set.size(); i++){
// //Set集合是没有索引的,所以不能使用通过索引获取元素的方法
//}
Iterator < string > it = set . iterator ();
while ( it . hasNext ()){
String s = it . next ();
System . out . println ( s ); //aaa bbb ccc
}
//---------------------------------------------------
for ( String s : set ){
System . out . println ( s ); //aaa bbb ccc
}
}
}
存储和取出的顺序不一致
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MySet1 {
public static void main ( string [] args ) {
Set < String > set = new TreeSet ();
set . add ( "ccc" );
set . add ( "aaa" );
set . add ( "aaa" );
set . add ( "bbb" );
Iterator < string > it = set . iterator ();
while ( it . hasNext ()){
String s = it . next ();
System . out . println ( s ); //aaa bbb ccc
}
//---------------------------------------------------
for ( String s : set ){
System . out . println ( s ); //aaa bbb ccc
}
}
}
TreeSet-基本使用
TreeSet集合概述和特点
TreeSet
:底层是红黑树结构,所以要求元素必须排序
TreeSet
集合特点
不包含重复元素的集合
没有带索引的方法
可以将元素按照规则进行排序 (TreeSet
虽然 不能保证存和取的顺序 ,但是可以 对内部的元素进行排序 )
TreeSet
集合练习
存储 Integer
类型的整数,并遍历
存储学生对象,并遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Treeset集合来存储Integer类型
*/
public class MyTreeSet1 {
public static void main ( string [] args ) {
TreeSet < Integer > ts = new TreeSet <> ();
ts . add ( 5 );
ts . add ( 3 );
ts . add ( 4 );
ts . add ( 1 );
ts . add ( 2 );
System . out . println ( ts ); //[1, 2, 3, 4, 5]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Treeset集合来存储Student类型
*/
public class MyTreeset2 {
public static void main ( String [] args ) {
TreeSet < Student > ts = new TreeSet <> ();
Student s1 = new Student ( "小花" , 27 );
Student s2 = new Student ( "小花花" , 28 );
Student s3 = new Student ( "小小花" , 28 );
ts . add ( s1 );
ts . add ( s2 );
ts . add ( s3 );
System . out . println ( ts );
//Exception in thread "main"java.lang.ClassCastException:class com.itheima.mytreeset.Student cannot be cast to class java.lan
//报错的原因:没有指定排序的规则,是按照身高排,还是按照年龄排...,没有制定规则
}
}
想要使用 TreeSet,需要制定排序规则
TreeSet-自然排序
自然排序Comparable的使用
使用 空参构造 创建 TreeSet
集合
自定义的 Student
类实现 Comparable 接口
重写里面的 compareTo 方法
public interface Comparable<T>
该接口对实现它的每个类的对象强加一个整体排序。这个排序被称为类的自然排序,类的 compareTo
方法被称为其自然比较方法。
简单来说,一个类实现了 Comparable
接口,那么就可以根据里面 compareTo
方法的返回值,对元素进行排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class Student implements comparable < Student > { //此处的泛型要和集合里边存储的数据类型保持一致
private String name ;
private int age ;
public student () {
}
public Student ( String name , int age ) {
this . name = name ;
this . age = age ;
}
//set/get...
@Override
public int compareTo ( Student o ) {
//按照对象的年龄进行排序
int result = this . age - o . age ;
return result ;
}
}
/**
* Treeset集合来存储Student类型
*/
public class MyTreeset2 {
public static void main ( String [] args ) {
TreeSet < Student > ts = new TreeSet <> ();
Student s1 = new Student ( "小花" , 28 );
Student s2 = new Student ( "小花花" , 27 );
Student s3 = new Student ( "小小花" , 29 );
ts . add ( s1 );
ts . add ( s2 );
ts . add ( s3 );
//[Student{name='小花花',age=27), Student{name='小花',age=28}, Student{name='小小花',age=29}]
System . out . println ( ts );
}
}
自然排序简单原理图 (找中间的比较)
如果返回值为负数,表示当前存入的元素是较小值,存左边
如果返回值为 0,表示当前存入的元素跟集合中元素重复了,不存
如果返回值为正数,表示当前存入的元素是较大值,存右边
(图5
)
将创建的三个对象存入到我们创建的容器 TreeSet
集合中
第一个是 小花,28
,容器中没有内容,他直接就存进去了,第二个要存的是 小花花,27
(图6
)
This
:表示现在正在存的对象,也就是 小花花,27
O
:表示已经存到集合中的元素,也就是 小花,28
第三个是 小小花,29
,将正在存的元素与集合中的元素一个一个进行比较
(图7
)
(图8
)
(图9
)
自然排序-练习
案例:按照年龄排序
需求:改写刚刚的学生案例
要求:按照年龄从小到大排,如果年龄一样,则按照姓名首字母排序
如果年龄和姓名都一样,认为是同一个学生对象,不存入
为什么要先按年龄,再按姓名排序呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class Student implements comparable < Student > { //此处的泛型要和集合里边存储的数据类型保持一致
private String name ;
private int age ;
public student () {
}
public Student ( String name , int age ) {
this . name = name ;
this . age = age ;
}
//set/get...
@Override
public int compareTo ( Student o ){
//按照对象的年龄进行排序
int result = this . age - o . age ;
return result ;
}
}
/**
* Treeset集合来存储Student类型
*/
public class MyTreeset2 {
public static void main ( String [] args ) {
TreeSet < Student > ts = new TreeSet <> ();
Student s1 = new Student ( "小花" , 28 );
Student s2 = new Student ( "小花花" , 27 );
Student s3 = new Student ( "小小花" , 29 );
Student s4 = new Student ( "小黑" , 28 );
ts . add ( s1 );
ts . add ( s2 );
ts . add ( s3 );
ts . add ( s4 );
//[Student{name='小花花Lage=27), Student{name='小花',age=28}, Student{name='小小花',age=29}]
System . out . println ( ts );
}
}
我们发现 小黑,28
没有存到集合中,这是因为排序规则是按照年龄排序的,小黑的年龄 28
集合中已经有了,于是在添加的时候,就会认为 小花,28
和 小黑,28
是同一个对象,所以 TreeSet
就把第四个对象扔了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class Student implements comparable < Student > { //此处的泛型要和集合里边存储的数据类型保持一致
private String name ;
private int age ;
public student () {
}
public Student ( String name , int age ) {
this . name = name ;
this . age = age ;
}
//set/get...
@Override
public int compareTo ( Student o ) {
//按照对象的年龄进行排序
//主要判断条件
int result = this . age - o . age ;
//次要判断条件
result = result == 0 ? this . name . compareTo ( o . getName ()) : result ;
return result ;
}
}
/**
* Treeset集合来存储Student类型
*/
public class MyTreeset2 {
public static void main ( String [] args ) {
TreeSet < Student > ts = new TreeSet <> ();
Student s1 = new Student ( "zhangsan" , 28 );
Student s2 = new Student ( "lisi" , 27 );
Student s3 = new Student ( "wangwu" , 29 );
Student s4 = new Student ( "zhaoliu" , 28 );
ts . add ( s1 );
ts . add ( s2 );
ts . add ( s3 );
ts . add ( s4 );
System . out . println ( ts );
}
}
姓名是中文的,中文无法按照首字母排序,需要将姓名换成英文的
this.name
是一个字符串,this.name.compareTo()
用的是字符串 String
里的 compareTo
方法
int compareTo(String anotherString)
按字典顺序比较两个字符串
对字符串中的 compareTo
方法进行演示
1
2
3
4
5
6
7
8
public static void main ( String [] args ) {
String s1 = "aaa" ;
String s2 = "ab" ;
System . out . println ( s1 . compareTo ( s2 )); //-1
//首先比较第一个字母,如果第一个字母是一样的,那么继续比较后面的字母
//当不一样的时候,就拿着a对应的码表值97,减去b的码表值98
//认为a是比b要小的
}
TreeSet-比较器排序
比较器排序Comparator的使用
TreeSet
的 带参 构造方法使用的是 比较器排序 对元素进行排序的 (如果要使用比较器排序,在创建 TreeSet
的时候,就不能使用空参,空参是自然排序 )
比较器排序,就是 让集合构造方法接收Comparator的实现类对象 ,重写 compare(To1,To2)
方法
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
练习:
需求:用比较器排序实现下面的需求
要求:自定义 Teacher
老师类,属性为姓名和年龄
请按照年龄排序,如果年龄一样,则按照姓名进行排序,姓名都使用英文字母表示
构造方法
Constructor
描述
TreeSet()
构造一个新的、空的树组,根据其元素的自然排序进行排序。
TreeSet(Collection<? extends E> c)
构造一个包含指定集合中的元素的新树集,根据其元素的自然排序进行排序。
TreeSet(Comparator<? super E> comparator)
构造一个新的、空的树集,根据指定的比较器进行排序。
TreeSet(Sortedset s)
构造一个包含相同元素的新树,并使用与指定排序集相同的顺序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class MyTreeset4 {
public static void main ( String [] args ) {
Treeset < Teacher > ts = new Treeset <> ( new Comparator < Teacher > () { //泛型要和集合里存储的元素类型保持一致
@Override
public int compare ( Teacher o1 , Teacher o2 ){ //匿名内部类
//o1表示现在要存入的那个元素
//o2表示已经存入到集合中的元素
//主要条件
int result = o1 . getAge () - o2 . getAge ();
//次要条件
result = result == 0 ? o1 . getName (). compareTo ( o2 . getName ()) : result ;
return result ;
}
});
Teacher t1 = new Teacher ( "zhangsan" , 23 );
Teacher t2 = new Teacher ( "lisi" , 22 );
Teacher t3 = new Teacher ( "wangwu" , 24 );
ts . add ( t1 );
ts . add ( t2 );
ts . add ( t3 );
}
}
o1
代表当前要存入的元素,o2
代表集合中的元素,比较的时候先找集合中处于中间位置的元素比较,如果比中间的位置元素小,就继续与左边的元素比较,反之则与右边的元素比较