Java - 泛型、常见数据结构、集合(一)
一、泛型
-
介绍
泛型(Generic)是JDK5之后新增语法,可以在类、接口或方法中预支地使用未知的类型。
-
加上泛型可以保证集合中只有一种类型的数据,这样好处理,而且也可以在编译时期即可提示错误信息,不然有问题要等到运行的时候才报错,避免了类型强转的麻烦。
-
泛型主要应用于方法的参数与返回值类型;接收的实际类型是什么,到时候泛型就会转换成实际类型,就很灵活,多变。
-
泛型可以使API在设计的过程中,使类或接口中不明确的数据类型,交给使用阶段来确定,从而简化API的开发。
-
定义含有泛型的类
- 定义含有泛型的方法
- 定义含有泛型的接口
-
泛型通配符入门
<1> 概述
泛型的使用不存在继承关系,不可以给已指定泛型的变量接收有其他泛型类型的对象,也就是在定义泛型的时候要保持定义语句的前后一致,或者后面不写。
例如: ArrayList list = new ArrayList() //错误格式,泛型不存在继承关系
<2> 泛型通配符用问号 ? 表示。用于限制泛型数据类型的定义区间。单独使用表示任意类型,与不写的效果相同。
<3> ArrayList不加泛型默认其实也是object,但是如果你把它显式地写出来了,那就要遵循泛型之间不能继承的规则,也就是不能接收一个已确定的泛型对象, 左图显式书写了导致加不了其他对象,右图都可以加。
-
泛型受限 - >=子类 或者 <=父类,目的是限制范围
在方法中不能添加新的对象,因为区间只确定了一边,另一边一直可以变,编译器不能够确定,如果把子类new 成了父类也不太合适,所以方法一般只用于对传进来的集合做一些处理。
- 泛型通配符应用场景
package com.itheima.demo03_泛型通配符.p02泛型受限;
import java.util.ArrayList;
public class Test1 {
public static ArrayList<Fu> list = new ArrayList<>();
public static ArrayList<Zi> list2 = new ArrayList<>();
public static ArrayList<Sun> list3 = new ArrayList<>();
public static Fu f = new Fu();
public static Zi z = new Zi();
public static Sun s = new Sun();
public static void main(String[] args) {
ArrayList<Fu> list = new ArrayList<>();
ArrayList<Zi> list2 = new ArrayList<>();
ArrayList<Sun> list3 = new ArrayList<>();
show(list);
show(list2);
//show(list3);
//show2(list);
show2(list2);
show2(list3);
show3(list);
show3(list2);
show3(list3);
}
//这里因为限制了参数至少得是Zi类以及以上类型(也就是Zi的父类),所以我在用这样的实参去添加对象的时候,只能加比我低的
//最低类型时Zi类,将来传入的集合泛型最低一定是Zi类,所以Zi类的子类类型一定可以被操作
private static void show(ArrayList<? super Zi> list) {
//list.add(f);
list.add(z);//可以
list.add(s);//可以
}
//这里因为限制了参数的范围是Zi类及以下,所以我在用实参的时候,我不知道传过来的到底有多低,所以一个都不敢加,因为只能加比我低的
//最低类型不确定,将来传入的集合泛型不一定是子类,所以不能保证子类的子类一定能添加。
private static void show2(ArrayList<? extends Zi> list) {
//list.add(f);
//list.add(z);
//list.add(s);
}
public static void show3(ArrayList list) {
list.add(new Zi());
}
}
class Fu {
}
class Sun extends Zi {
}
class Zi extends Fu {
}
二、数据结构
-
概述
-
数据结构 :其实就是存储数据和表示数据的方式,有助于帮助我们选择更合适的集合,因为不同的集合存储数据用的是不同的数据结构,优缺点各不同
-
常见的数据结构:堆栈、队列、数组、链表和红黑树。
-
-
栈结构
-
队列结构
-
数组结构
-
链表结构
-
树结构 - "高度"要分左高度和右高度,判断节点是否平衡就是对比节点的左右高度
<1> 二叉树 - 如果树中的:每个节点的子节点的个数不超过2,那么该树就是一个二叉树。
<2> 二叉查找树
-
满足二叉树条件,且左子树节点的值均小于等于根节点,右子树上节点值均大于等于根节点,这有助于查询,一次就可以排除一半的数据。
-
存在问题:瘸子现象 - 如果是有点像链子的这种树,没啥分支,那其实查起来就没区别了,也是一个个去找,很慢。
<3> 平衡二叉(查找)树
-
左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树
-
避免出现"瘸子"的现象,减少树的高度,提高了搜索效率
-
平衡二叉(查找)树是如何保持平衡的
• 当有新的节点要插入时,检查是否因插入后而破坏了树的平衡,如果是,则需要做旋转去改变树的结构。
• 右旋:左子的右子断连旧父,连旧父父,左子升新父。见《平衡二叉树右旋》
• 左旋:右子的左子断连旧父,连旧父父,右子升新父。见《平衡二叉树左旋》、《左旋示例图》
<4> 红黑树 - 黑红相间,保证每条路径中的黑节点个数相同来保持平衡
-
三、集合
-
概述
-
集合中的单列集合 - Collection
元素存取有序还是无序,指的是存进去是数据顺序是 a,b,c ,取出来的数据的顺序是否也是a,b,c
-
从通用到特殊
- 介绍Collection类以及他所有的子类都通用的方法,用ArrayList 做示范而已,其实其他的也支持这些方法。
- 介绍List 自己特有的一些方法
- 介绍LinkedList 自己特有的方法
-
单列集合通用方法
toArray()方法,是转换成数组的方法,可以指定转换后的数组长度,一般是原集合的元素个数。
-
-
遍历集合要借助迭代器 - 方式1
- 迭代器在迭代的时候如果用集合来添加元素,会报并发异常的错误,因为此时迭代器会一直记住对比原有长度,变了不行,如果要添加那也是要用迭代器来添加。
-
遍历集合 - 方式2 - 增强 for
-
四、List
-
概述
-
List集合通用方法
-
LinkedList