一.集合复习
- 1.集合
1.集合
Collection(单列集合)
List(有序,可重复)
ArrayList
底层数据结构是数组,查询快,增删慢
线程不安全,效率高
Vector
底层数据结构是数组,查询快,增删慢
线程安全,效率低
LinkedList
底层数据结构是链表,查询慢,增删快
线程不安全,效率高
Set(无序,唯一)
HashSet
底层数据结构是哈希表。
哈希表依赖两个方法:hashCode()和equals()
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终:
自动生成hashCode()和equals()即可
LinkedHashSet
底层数据结构由链表和哈希表组成。
由链表保证元素有序。
由哈希表保证元素唯一。
TreeSet
底层数据结构是红黑树。(是一种自平衡的二叉树)
如何保证元素唯一性呢?
根据比较的返回值是否是0来决定
如何保证元素的排序呢?
两种方式
自然排序(元素具备比较性)
让元素所属的类实现Comparable接口
比较器排序(集合具备比较性)
让集合接收一个Comparator的实现类对象
Map(双列集合)
A:Map集合的数据结构仅仅针对键有效,与值无关。
B:存储的是键值对形式的元素,键唯一,值可重复。
HashMap
底层数据结构是哈希表。线程不安全,效率高
哈希表依赖两个方法:hashCode()和equals()
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终:
自动生成hashCode()和equals()即可
LinkedHashMap
底层数据结构由链表和哈希表组成。
由链表保证元素有序。
由哈希表保证元素唯一。
Hashtable
底层数据结构是哈希表。线程安全,效率低
哈希表依赖两个方法:hashCode()和equals()
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终:
自动生成hashCode()和equals()即可
TreeMap
底层数据结构是红黑树。(是一种自平衡的二叉树)
如何保证元素唯一性呢?
根据比较的返回值是否是0来决定
如何保证元素的排序呢?
两种方式
自然排序(元素具备比较性)
让元素所属的类实现Comparable接口
比较器排序(集合具备比较性)
让集合接收一个Comparator的实现类对象
2:到底使用那种集合
看需求。
是否是键值对象形式:
是:Map
键是否需要排序:
是:TreeMap
否:HashMap
不知道,就使用HashMap。
否:Collection
元素是否唯一:
是:Set
元素是否需要排序:
是:TreeSet
否:HashSet
不知道,就使用HashSet
否:List
要安全吗:
是:Vector(其实现在也不用它,后面讲解了多线程以后,再回顾用谁)
否:ArrayList或者LinkedList
增删多:LinkedList
查询多:ArrayList
不知道,就使用ArrayList
不知道,就使用ArrayList
3:集合的常见方法及遍历方式
Collection:
add()
remove()
contains()
iterator()
size()
遍历:
增强for
迭代器
|--List
get()
遍历:
普通for
|--Set
Map:
put()
remove()
containskey(),containsValue()
keySet()
get()
value()
entrySet()
size()
遍历:
根据键找值
根据键值对对象分别找键和值
至少需要达到:
讲解过的任意一个集合,要求存储什么,就能够存储什么。
并且,还要能够遍历出来。
4:ArrayList,LinkedList,HashSet,HashMap(掌握)
存储字符串和自定义对象数据并遍历
5:集合的嵌套遍历(理解)
二.异常处理
1.概述
- 开发过程中比如 客户输入数据的格式,读取文件是否存在等问题是不能靠代码避免的;
- 异常:java中,将程序执行中发生的不正常情况被称为“异常”。(语法错误和逻辑错误不是异常)
-
两类:
Error:java虚拟机无法解决的严重问题。比如栈溢出StackOverflowError,堆溢出OutOfMemory
** Exception**:编程或偶然的外在因素导致的一般性问题,可以用针对性代码处理
2.异常分类
- 捕获错误最理想的是编译期间,但有的错误只在运行时出现。比如除数为0,数据下标越界。
- 分为:编译时异常javac.exe和运行时异常java.exe
-
java.lang.Throwable
-
常见的异常:
运行时异常
@Test
public void test1(){
int[] arr = new int[3];
System.out.println(arr[3]);
//数组索引越界
//java.lang.ArrayIndexOutOfBoundsExcept//ion: 3
String str = "abc";
str = null;
System.out.println(str.charAt(0));
// java.lang.NullPointerException
Object obj = new Date();
String str = (String)obj;
// java.lang.ClassCastException
String str = "123";
str = "abc";
int num = Integer.parseInt(str);
// java.lang.NumberFormatException
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();//输入 asfl
System.out.println(i);
//java.util.InputMismatchException
int a =10;
int b= 0;
int c = a/b;
// java.lang.ArithmeticException
编译时异常:
File file = new File("Hello.txt");
FileInputStream fis = new FileInputStream(file);
//java.io.FileNotFoundException
int data = fis.read();//java.io.IOException
while(data != -1){
System.out.println((char)data);
data = fis.read();
}
fis.close();
3.异常处理机制
- 两类:try-catch-finally和throws+异常类型
- 引入:写程序时候,通常在可能出现错误的地方加上检测代码,比如除法要检测分母为0,用if else分支会导致代码冗长,因此引入异常处理机制
- Java异常处理:将异常处理的程序代码集中在一起与正常的程序代码分开,便于维护。
- 抓抛模型:
过程一:抛,程序在正常执行过程中,一旦出现异常,就会在异常代码生成除生成一个对应异常类的对象,将该对象抛出;一旦抛出对象后,在其后的代码就不再执行;
过程二:抓,异常处理方式:1.try catch finally,和throws。
3.1第一类:try-catch-finally:
- 结构
try{
//可能出现异常的代码
}catch(异常类型1 变量名1){
//处理异常的方式1
}catch(异常类型2 变量名2){
//处理异常的方式2
}catch(异常类型3 变量名3){
//处理异常的方式3
}//.....
finally{
//一定会执行的代码
}
- 实践
1.finally可选的
2.使用try将可能出现异常的代码包装,一旦出现异常,就生成一个对应异常类的对应,根据类型到catch抓取。
3.一旦匹配到某个catch,就进去进行异常处理,一旦处理完毕,就不执行后面的catch了,
catch中类型如果没有子父类关系,则声明顺序无所谓
但如果有的话,要求子类一定声明在父类上面,否则报错
4.执行finally,完毕后继续执行以后的代码。
5.常用处理异常方式:String getMessage();和printStackTrace()
6.try结构声明的变量,出了try就不能调用
7.对于编译时的异常:try结构可以处理编译异常,编译时就不再报错,把编译时运行延迟到运行时了
String str = "123";
str = "abc";
try {
int num = Integer.parseInt(str);
System.out.println("hello----1");
// java.lang.NumberFormatException
}catch (NumberFormatException e){
System.out.println("出现数值转换异常");
System.out.println(e.getMessage());
e.printStackTrace();
}catch (Exception e){
System.out.println("出现数异常");
}
finally{
System.out.println("hello----2");
}
// 出现数值转换异常
// hello----2
//运行时异常
try{
File file = new File("Hello.txt");
FileInputStream fis = new FileInputStream(file);
//java.io.FileNotFoundException
int data = fis.read();//java.io.IOException
while(data != -1){
System.out.println((char)data);
data = fis.read();
}
fis.close();
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
- finally使用
1.finally可选
2.finally声明的是一定会被执行的代码,即使catch中出现异常,try中有return语句等,也仍然执行。
3.像数据库连接、输入输出流等资源,JVM不能自动回收,要求自己手动的资源释放。此时资源释放,就放在finally中。
imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
4.try catch结构可以嵌套
3.2编译时异常和运行时异常处理的不同处理方式
- 实际开发时候运行时异常和加了处理printStackTrace后一样。
- 但编译异常有用,可以通过编译阶段,把报错延迟到运行时;
3.3throws方式
-
throws + 异常类型
抛到上一级了
- 一旦出现异常,生成一个异常类对象,此对象满足throws后类型时候,就会抛出,后面的代码不再执行!
- 体会:try-catch-finally:真正将异常处理了。throws方式只是把异常抛给了方法调用者。
3.4重写方法异常抛出原则
-
子类重写的方法抛出的异常类型不大于父类被重写方法抛出的异常类型(就是该异常属于父类异常的子类)
这样在调用的时候,try catch可以罩得住。
3.5如何选择哪种异常处理方式
- 如果父类中被重写方法没throws处理异常,则子类重写方法也不能用throws,意味者子类只能用try方式
- 嵌套调用的几个方法建议throws处理,而最顶层的方法用try