泛型
什么是泛型
参数化类型,就是指在定义泛型的时候,像在定义形参一样,在使用泛型的时候,需要传递数据类型
泛型的定义格式
泛型的作用
- 避免了强制类型转换
- 限制了集合中元素的数据类型
泛型的基本使用
//创建集合容器
ArrayList<String> al = new ArrayList<String>();
//添加元素
al.add("aaa");
al.add("bbb");
al.add("ccc");
Iterator<String> it = al.iterator();
while(it.hasNext()) {
String s = it.next();
System.out.println(s);
}
泛型的注意事项
1.泛型里面不能写基本数据类型
2.前面的<>和后面的<>里的数据类型要匹配
3.在jdk新特性,后面<>可以省略不写了
ArrayList<String> al = new ArrayList<String>();
ArrayList<String> al = new ArrayList<>(); //菱形泛型
ArrayList<String> al = new ArrayList();
自定义泛型
自定义泛型类
class Zi<T> {
public void print(T t) {
System.out.println(t);
}
}
自定义泛型方法
class Zi {
public <T> void print(T t) {
System.out.println(t);
}
}
自定义泛型接口
interface Fu<T> {
public abstract void print(T t);
}
class Zi<T> implements Fu<T> {
public void print(T t) {
System.out.println(t);
}
}
泛型通配符
?
List<?> al1 = new ArrayList<String>();
List<?> al2 = new ArrayList<Integer>();
List<?> al3 = new ArrayList<Pig>();
ArrayList<Integer> al1 = new ArrayList<Integer>();
al1.add(111);
al1.add(222);
ListTools.print(al1);
class ListTools {
public static void print(List<?> list) {//List<?> list = al1 = new ArrayList<Integer>
System.out.println(list);
}
}
? extends E
List<? extends Number> list1 = new ArrayList<String>();//编译报错
List<? extends Number> list2 = new ArrayList<Number>();
List<? extends Number> list3 = new ArrayList<Object>();//编译报错 泛型的上限
List<? extends Number> list4 = new ArrayList<Integer>();
List<? extends Number> list5 = new ArrayList<Float>();
? super E
List<? super Number> list1 = new ArrayList<String>();//编译报错
List<? super Number> list2 = new ArrayList<Object>();
List<? super Number> list3 = new ArrayList<Number>();
List<? super Number> list4 = new ArrayList<Integer>();//编译报错 泛型的下限
List<? super Number> list5 = new ArrayList<Float>();//编译报错
泛型擦除
编译时存在,编译后就不存在了
Set接口
Set集合的特点?
1.不保证顺序(存入的顺序和取出的顺序是不一样的)
2.元素唯一
3.无索引
常见的成员方法?
和Collection中的方法是一样
Set集合的遍历?
方式一:转数组
方式二:迭代器
方式三:增强for
3.TreeSet实现类
TreeSet集合的特点?
1.不保证顺序(存入的顺序和取出的顺序是不一样的)
2.元素唯一
3.无索引
4.可以排序的(由小到大)
TreeSet的数据结构?
树型结构中红黑树
常见的成员方法?
和Set中的方法是一样
TreeSet集合的遍历?
方式一:转数组
方式二:迭代器
方式三:增强for
TreeSet集合存储字符串类型的数据?
//创建集合容器
TreeSet
//添加元素
ts.add(“bbb”);
ts.add(“ccc”);
ts.add(“aaa”);
System.out.println(ts);
按照字典顺序进行由小到大排序
TreeSet集合存储Integer类型的数据?
//创建集合容器
TreeSet
//添加元素
ts.add(222);
ts.add(555);
ts.add(111);
ts.add(444);
ts.add(333);
System.out.println(ts);
按照数字的大小由小到大进行排序
TreeSet集合存储自定义类的类型的数据?
//创建集合容器
TreeSet
//添加元素
ts.add(new Pig(“tom”, 18));
ts.add(new Pig(“jerry”, 19));
ts.add(new Pig(“tony”, 20));
System.out.println(ts);//运行报错:类型转换异常
如果我们想要使用TreeSet来存储自定义对象的话,要满足两个条件之一才可以正常运行
条件一:自然排序Comparable
如何实现自然排序?
1.自定义类,实现Comparable接口
2.重写抽象方法compareTo()
3.在compareTo()方法中写比较规
返回值为0:集合中的元素只有一个
返回值为正数:集合中的元素是正序
返回值为负数:集合中的元素是倒数
练习:
需求:按照对象的年龄进行由小到大的顺序来排序,如果年龄相同,去重?
public int compareTo(Cat o) {
int i = this.age - o.age;
return i;
}
需求:按照对象的年龄进行由大到小的顺序来排序,如果年龄相同,去重?
public int compareTo(Cat o) {
//int i = this.age - o.age;
int i = o.age - this.age;
return i;
}
需求:按照对象的年龄由大到小进行排序,如果年龄相同,再根据姓名字典顺序比较,如果
姓名也相同,就去重?
public int compareTo(Person o) {
//先比较年龄:大到小
int i = o.age - this.age;
//比较姓名
return i == 0 ? this.name.compareTo(o.name) : i;
}
条件二:比较器Comparator
如何实现比较器?
1.自定义类
2.创建TreeSet集合对象,在构造方法中传递Comparator的对象
3.重写compare()方法
4.在compare()中写比较规则
返回值为0:集合中的元素只有一个
返回值为正数:集合中的元素是正序
返回值为负数:集合中的元素是倒数
练习:
需求:按照对象的年龄进行由小到大的顺序来排序,如果年龄相同,去重?
TreeSet
@Override
public int compare(Cat o1, Cat o2) {
int i = o1.getAge() - o2.getAge();
return i;
}
});
需求:按照对象的年龄进行由大到小的顺序来排序,如果年龄相同,去重?
TreeSet
@Override
public int compare(Cat o1, Cat o2) {
int i = o2.getAge() - o1.getAge();
return i;
}
});
需求:按照对象的年龄由大到小进行排序,如果年龄相同,再根据姓名字典顺序比较,如果
姓名也相同,就去重?
TreeSet
@Override
public int compare(Person o1, Person o2) {
//先比较年龄,由大到小
int i = o2.getAge() - o1.getAge();
//比较姓名:字典顺序
return i == 0 ? o1.getName().compareTo(o2.getName()) : i;
}
});
4.数据结构
栈
队列
数组
链表
树结构:
普通二叉树:
特点:
二叉树是由节点组成的
有且只有一个根节点
每个节点下面最多只能有两个子节点
二叉查找树:
特点:
二叉树是由节点组成的
有且只有一个根节点
每个节点下面最多只能有两个子节点
小的放在左边,大的放在右边,也就是说一个节点的左子树的数据肯定比它小,右子树数据肯定都比它大
平衡二叉树:
特点:
二叉树是由节点组成的
有且只有一个根节点
每个节点下面最多只能有两个子节点
小的放在左边,大的放在右边,也就是说一个节点的左子树的数据肯定比它小,右子树数据肯定都比它大
任何节点的左子树和右子树的高度差不能超过1
如果没有达到平衡,该怎么办呢?
左旋或者右旋来让树变得平衡
红黑树:
特点:
红黑树中的节点要么是黑色的,要么是红色
根节点一定是黑色的
如果一个节点是红色的,那它的两个子节点一定是黑色的,也就是说不能有连续两个红色的节点连在一起
如果一个节点没有子节点了,那它会默认指向的是名为Nil的节点,可以视为Nil节点为叶子节点,叶子节点
一定是黑色的
任何一个节点到其叶子节点的这条件简单路径上黑色节点的个数是一样多的
注意:
1.默认添加的节点颜色为红色
2.如果出现连续两个红色节点的话:
父亲节点是红色,看叔叔节点是红色还是黑色
a.如果叔叔节点是红色,父亲节点由红变黑,叔叔节点由红变黑,爷爷节点由黑边红,如果爷爷
是根节点,再由红变黑
b.如果叔叔节点是黑色,父亲节点由红变黑,爷爷节点由黑变红,然后进行旋转