001-集合框架p1
集合框架
异常
Java的异常体系
-
例子:
-
运行时异常:
- 索引越界异常
- 除数为0
- 调取一个空值的长度
-
编译时异常:
-
提醒程序员时间格式可能有误
可以在方法中抛出异常,然后在调用时用try-catch 处理异常
一个代码抛出多个异常可以都抛出,也可以抛出一个Exception,来直接抛出方法内所有异常
-
-
异常的作用?
-
用来定位程序bug的关键信息,如项目日志文件之类的
-
可以作为方法内部的一种特殊返回值,以便通知上层调用者方法的执行问题
-
需要有返回值的方法如果有异常可以返回一个异常作为特殊返回值
-
例如除以0的问题
这里如果抛出Exception需要再方法上也抛出
-
自定义异常
-
Java无法为世界上全部问题都定义异常,如果企业自己的某种问题想通过异常来表示,以便用异常来管理该问题,那就需要自己来定义异常类了
-
分类:
-
自定义编译时异常示例:
-
自定义运行时异常示例:
- 不需要自己抛异常,会自动抛
-
-
现在的设计思想逐渐摒弃编译时异常,因为动不动就报错要处理。
异常的处理方案
-
方案1(推荐):底层异常层层往上抛出,最外层捕获异常,记录下异常信息,并相应适合观众观看的信息进行提示。
-
方法2:最外层捕获异常后,尝试重新修复
泛型
-
定义类、接口、方法时,同时声明了一个或多个类型变量(如
<E>
)成为泛型类、泛型接口、泛型方法,它们统称为泛型
-
作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动检查的能力,这样可以避免强制类型转换,及其可能出现的异常
-
泛型的本质:把具体的数据类型作为参数传给类型变量
泛型类
- 语法:
-
注意:类型变量建议用大写英文字母,常用的有:E、T、K、V
-
示例
-
jdk7开始支持不写new后面尖括号的类型
-
tip:批量修改变量名:shift+F6
泛型接口
-
语法
-
注意:类型变量建议用大写英文字母,常用的有:E、T、K、V
-
示例:
泛型方法、通配符、上下限
泛型方法
-
语法
】
- 自己定义的才是泛型方法,使用别处定义的泛型的方法不是泛型方法
通配符
- 就是“
?
”,可以在“使用泛型”的时候代表一切类型;E T K V是在定义泛型的时候使用,而问号是在定义时使用
上下限
-
为了防止什么类都能传入,所以设置了上下限
-
示例:
泛型支持的类型
- 泛型不支持基本数据类型,只支持对象的类型(引用数据类型)
- 原因:泛型的擦除:
- 泛型工作在编译阶段,等编译后泛型就没用了,所以泛型会在编译后被擦除。所有类型在编译后会变成Object。
- 如果支持基本数据类型,那就无法判断到底用基本数据类型还是Object了
- 原因:泛型的擦除:
包装类
-
包装类就是把基本数据类型的数据包装成对象的类型
-
解决了泛型不支持基本数据类型的问
除了int和char特殊,其他都是首字母大写
-
包装成对象的方法
- 后面时用value而老方法被淘汰而使用valueOf
- 原因:valueOf有很多缓存好的对象,很多常见的数据都已经被new好了,这样拿对象时拿到的是同一个对象,而不用重新new新的对象。比如Integer已经有-127-128的对象了
- 后面时用value而老方法被淘汰而使用valueOf
-
自动装箱和自动拆箱
-
示例:
- 可以看到和上面方法时一样的结果
-
示例2:
- 可以把int传给Integer自动装箱
- 也可以用int接Integer来自动拆箱
-
-
包装类具备的其他功能
-
示例:
-
集合框架
-
集合是一种容器,用来装数据的,类似于数组,但集合的大小可变,开发中也非常常用
-
分类
-
常见方法:
- add方法添加数据
- get(索引)。set系列没有索引,用不了这个方法
collection的常用功能
-
为什么先学collection的常用方法?
- Collection是单列集合的祖宗,它规定的方法(功能)是全部单列集合都会继承的。
-
常用功能:
Collection的遍历方式
-
方式一:
-
迭代器遍历
-
注意:hasNext是看当前位置有没有数据,而不是下一个
-
迭代器创建时默认指的是第一个数据的位置
-
用.next越界时会有异常NoSuchElementException
-
-
方式二:
-
增强for循环(for-each遍历)
-
-
方式三:
-
Lambda表达式
-
需要用Collection的如下方法来完成
-
原理:
源码中用this,即用点调用forEach的主调,然后用了个增强for
-
-
-
三种遍历方式的区别:
-
前置:认识并发修改异常问题
-
遍历集合的同时又存在增删集合元素的行为时可能出现业务异常,这种现象被称之为并发修改异常问题
-
比如删除包含相同字段的内容,如果只用for循环i++遍历、且相邻两个都是要删除内容的话,删掉第一个时,第二个会往前补过来,然而这时候i++了,导致第二个被跳过
-
解决办法:
- 删除的同时i--
- 对于支持索引的集合,倒着遍历并删除
- 使用迭代器解决
-
-
用迭代器遍历也会出现这个问题,但是用迭代器自带的remove方法就会做退步操作从而避免这个问题
-
增强for和lambda都无法解决这个问题
-
List集合
List集合的特有方法
-
List集合的特有方法
-
List集合四种遍历方式
- for循环(有索引)
- 迭代器
- 增强for
- lambda表达式
ArrayList和LinkedList的区别
-
List系列集合的特点:有序、可重复、有索引
- ArrayList:有序、可重复、有索引
- LinkedList:有序、可重复、有索引
-
不同点:底层采用的数据结构不同,应用场景不同,存储、组织数据的方式不同
-
ArrayList底层是基于数组存储数据的
- 查询速度快(根据索引查询数据块)
- 增删数据效率低:可能需要把后面很多的数据进行前移或扩容
- ArrayList起初是空的,在第一次添加数据时才通过扩容有容量
- 当数据量需要扩容时,每次扩容为1.5倍
-
LinkedList底层是基于双链表存储数据的
-
链表的数据是一个个肚里节点组成的,节点在内存中都是不连续的,每个节点包含当前值和下一个值的地址,双链表包含上一个和下一个值
-
查询慢,无论查询哪个数据都要从头开始找
-
链表增删相对于数组快
-
双链表提高了查询的速度,但是内存变的更大,每个节点都要额外存上一个节点
-
对于首尾元素增删极快,LinkedList新增了很多守卫操作的特有方法
-
应用场景:可以设计队列,只在收尾增删数据;也可以设计栈
-
-