目录
一、异常
1.try…catch
①Throwable类
②多catch并行处理
2.throw和throws关键字的使用
3.finally代码块
4.Runtime异常
编译异常 :
运行异常 :
常见的运行异常:
5.自定义异常
二、集合框架
1.集合框架由来
2.集合框架的继承体系
①Collection (集合) 接口 单列集合
②Map (映射键值对) 接口 双列集合
③Iterator迭代器接口
④泛型 Generic
⑤for(:)循环
3.Collection接口
①定义
②Collection接口的常用方法
4.Iterator接口
①定义
②Iterator接口的抽象方法
②获取迭代器接口实现类
④迭代器的实现原理
⑤并发修改异常
⑥集合存储自定义对象并迭代
5.List接口
①特点
②List接口自己的方法 (带有索引)
③List集合的特有迭代器
6.List接口的实现类的数据结构
数组 :
链表
三、集合
1.ArrayList
①特点
②源码解析
2.linkedList
①linkedList集合的特点
②linkedList集合特有方法
③源码解析
3.Set集合
①Set接口实现类HashSet类
③对象的哈希值
④String类的哈希值
⑤哈希值的相关问题
⑥哈希表的数据结构
⑦哈希表存储对象的过程
4.红黑树(Red-Black-Tree)
二叉树,本质就是链表
自然平衡二叉树
红黑树
①TreeSet集合使用
②TreeSet存储自定义对象
5.linkedHashSet
6.Collections工具类
一、异常
1.try…catch
例
public static void main(String[] args) {
int[] arr = {1};
//try catch异常处理
try {
int i = getNum(arr);
System.out.println("i = " + i);
}catch (Exception ex){
System.out.println("异常被处理掉");
}
System.out.println(111);
}
public static int getNum(int[] arr){
return arr[1] + 10;
}
①Throwable类
public static void main(String[] args){
int[] arr = {1};
//try catch异常处理
try{
int i = getNum(arr);
System.out.println("i=" + i);
}catch (Exception ex){
//Throwable类的异常信息的方法
String message = ex.getMessage();//message=1
System.out.println("message=" + message);
String str = ex.toString();//str = java.lang.ArrayIndexOutOfBoundsException: 1
System.out.println("str=" + str);
ex.printStackTrace();
}
System.out.println(111);
}
public static int getNum(int[] arr){
return arr[1] + 10;
}
②多catch并行处理
异常处理的代码中,try可以跟随多个catch
好处:不同的异常,可以区别对待,分开处理
注意:如果catch中的异常类没有关系,先写后写没有区别;catch中的异常类有继承关系,父类写在最下面
2.throw和throws关键字的使用
throw关键字 : 只能写在方法内部, 关键字的后面跟随对象的创建
throws关键字 : 只能写在方法的定义上,关键字后面跟随异常类名
例
public static void main(String[] args) {
try {
int area = getArea(-10);
System.out.println(area);
} catch (Exception e) {
e.printStackTrace();
}
}
public static int getArea(int length) throws Exception{
if (length <= 0)
//数据错误,导致后面的计算不能进行
//内部出现问题
throw new Exception("边长不存在");
return length * length;
}
3.finally代码块
finally代码块跟随try ... catch使用,也有跟随try使用,finally代码块里面的程序,无论是否出现异常,都会执行,必须执行,结束JVM了,finally不执行
作用:主要用于释放资源
public static void main(String[] args) {
try {
int[] arr = {1};
System.out.println(arr[0]);
}catch (Exception ex){
ex.printStackTrace();
}finally {
//后期用于资源的释放
System.out.println("这里的代码,必须执行");
}
}
4.Runtime异常
异常的父类是Exception,Exception类的子类RuntimeException,凡是RuntimeException和他的所有子类,都称为运行异常,非子类的称为编译异常Exception异常
编译异常 :
方法出现编译异常,调用者必须处理,否则编译失败.处理方式可以是try catch或者是throws都可以
运行异常 :
方法出现运行异常,方法的定义上,不需要throws声明,调用者也不需要处理这个异常
常见的运行异常:
NullPointerException空指针
IndexOutOfBoundsException越界异常
ClassCastException类型强制
IllegalArgumentException无效的参数异常
5.自定义异常
自定义异常,入伙,继承Exception或者RuntimeException
只有Exception和他的子类,才具有可抛出性
自定义的类中,构造方法,super调用父类构造方法,传递异常信息
例
自定义的异常类:
成绩负数的异常
自定义异常信息 : 继承父类 RuntimeException 带有String类型的构造方法 (String 异常信息)
public class ScoreException extends RuntimeException{
public ScoreException(String s){
super(s);
}
}
public static void main(String[] args) {
// int[] arr = {1};
//System.out.println(arr[2]);
int avg = getAvg(-100,2);
System.out.println("avg = " + avg);
}
public static int getAvg(int math,int chinese){
//判断成绩的数值
if ( math < 0 || chinese < 0)
//手动抛出,自己定义的异常
throw new ScoreException("成绩不存在");
return (math + chinese) / 2;
}
二、集合框架
1.集合框架由来
①集合本质上是存储对象的容器
②数组也能存储对象,数组弊端就是定长
③解决数组的问题,开发出来集合框架,集合框架无需考虑长度
④集合和数组的区别与共同点
集合,数组都是容器,都可以存储数据
集合只存储引用数据类型,不存储基本数据类型
数组可以存储基本类型,也可以存储引用类型
数组定长,集合容器变成
数据多了存数组,对象多了存集合
2.集合框架的继承体系
①Collection (集合) 接口 单列集合
List (列表) 接口
ArrayList (数组列表) 实现类
linkedList (链表) 实现类
Vector(数组列表) 实现类,过时了
Set (集) 接口
HashSet(哈希表) 实现类
linkedHashSet(链表哈希表) 实现类,继承HashSet
TreeSet(红黑树) 实现类
②Map (映射键值对) 接口 双列集合
- HashMap(哈希表) 实现类
- linkedHashMap(链表哈希表) 实现类,继承HashMap
- TreeMap(红黑树) 实现类
- Hashtable(哈希表) 实现类,过时
- Properties(哈希表)实现类, 继承Hashtable
- ConCurrentHashMap (哈希表) 线程相关
③Iterator迭代器接口
④泛型 Generic
- 写法
- 泛型类,泛型方法,泛型接口,泛型限定,泛型通配符
⑤for(:)循环
3.Collection接口
①定义
①定义
是所有单列集合的顶级接口,任何单列集合都是他的子接口,或者是实现类, 该接口中定义的方法,是所有单列集合的共性方法
Collection
②Collection接口的常用方法
| 方法的定义 | 方法作用 |
|---|---|
| boolean add(E) | 元素添加到集合 |
| void clear() | 清空集合容器中的元素 |
| boolean contains(E) | 判断元素是否在集合中 |
| boolean isEmpty() | 判断集合的长度是不是0,是0返回true |
| int size() | 返回集合的长度,集合中元素的个数 |
| boolean remove(E) | 移除集合中指定的元素,移除成功返回true |
| T[] toArray(T[] a) | 集合转成数组 |
4.Iterator接口 ①定义
迭代器接口 Iterator , 为集合进行遍历的.。迭代器技术是所有Collection集合的通用遍历形式
②Iterator接口的抽象方法
②获取迭代器接口实现类
迭代器就是为了遍历集合而产生.。
集合的顶层接口Collection中定义了方法: iterator() ,返回值是Iterator接口类型, 返回的是Iterator接口实现类的对象
Collection接口中的方法摘要 :public Iterator iterator() ; 返回迭代器接口实现类的对象
使用的对象ArrayList,实现接口Collection,重写方法iterator();
public static void main(String[] args) {
//迭代器遍历集合
//接口多态创建集合容器对象,存储的数据类型是字符串
Collection coll = new ArrayList<>();
//集合对象的方法add添加元素
coll.add("hello");
coll.add("world");
coll.add("java");
coll.add("money");
coll.add("wife");
//1 遍历 集合对象,调用方法iterator() 获取迭代器接口的实现类对象
Iterator it = coll.iterator();
//2 迭代器对象的方法,判断集合是否有下元素
//boolean b = it.hasNext();
//System.out.println(b);
//3 迭代器对象的方法,取出元素
//String str = it.next();
//System.out.println(str);
//条件,集合中有下一个元素就可以
while ( it.hasNext() ){
String str = it.next();
System.out.println(str);
}
}
④迭代器的实现原理
每个集合容器,内部结构不同,但是迭代器都可以进行统一的遍历实现
结论:迭代器是隐藏在集合的内部的, 提供公共的访问方式, Iterator接口
⑤并发修改异常
异常的产生原因 : 在迭代器遍历集合的过程中,使用了集合的功能,改变了集合的长度造成
例
public static void main(String[] args) {
//迭代器遍历集合
//接口多态创建集合容器对象,存储的数据类型是字符串
Collection coll = new ArrayList<>();
//集合对象的方法add添加元素
coll.add("hello");
coll.add("world");
coll.add("java");
coll.add("money");
coll.add("wife");
//迭代器遍历集合
Iterator it = coll.iterator();
while ( it.hasNext() ){
String str = it.next();
//判断,遍历到的集合元素是不是java
if (str.equals("java")){
//添加元素 出现并发修改异常
coll.add("add");
}
System.out.println(str);
}
}
⑥集合存储自定义对象并迭代
public static void main(String[] args) {
//创建集合,存储自定义的对象
Collection coll = new ArrayList<>();
//集合的方法add存储Person对象
coll.add( new Person("张三",21) );
coll.add( new Person("李四",22) );
coll.add( new Person("王五",23) );
//迭代器遍历集合
Iterator iterator = coll.iterator();
while (iterator.hasNext()){
Person person = iterator.next();
System.out.println(person);
System.out.println(person.getName());
}
}
public class Person {
private String name;
private int age;
public Person(){}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
5.List接口
①特点
①特点
这个接口的集合都具有索引
这个接口中的元素允许重复
这个接口中的元素是有序的
元素不会排序 ,有序指的是 ,元素存储和取出的顺序是一致的
②List接口自己的方法 (带有索引)
add(int index ,E e)
指定的索引位置,添加元素
public static void listAdd(){
List list = new ArrayList<>();
list.add("a") ;//集合的尾部添加
list.add("b");
list.add("c");
list.add("d");
list.add("e");
System.out.println(list);
//指定的索引上,添加元素 ,3索引添加元素
list.add(3,"QQ");
System.out.println(list);
}
get(int index)
返回指定索引上的元素
public static void listGet(){
List list = new ArrayList<>();
list.add("a") ;//集合的尾部添加
list.add("b");
list.add("c");
list.add("d");
list.add("e");
//List接口方法get取出元素
//String s = list.get(3);
//System.out.println(s);
for(int i = 0 ; i < list.size() ; i++){
System.out.println(list.get(i));
}
}
set(int index,E e)
修改指定索引上的元素,返回被修改之前的元素
remove(int index)
移除指定索引上的元素, 返回被移除之前的元素
public static void listSetRemove(){
List list = new ArrayList<>();
list.add("a") ;//集合的尾部添加
list.add("b");
list.add("c");
list.add("d");
list.add("e");
System.out.println(list);
//修改指定索引上的元素,3索引
String str = list.set(3,"https://www.baidu.com");
System.out.println(list);
System.out.println(str);
//删除指定索引上的元素,删除3索引
str = list.remove(3);
System.out.println(list);
System.out.println(str);
}
③List集合的特有迭代器
List接口中的方法 listIterator() 返回迭代器,迭代器的接口是ListIterator,集合的专用迭代器.
ListIterator迭代器接口的方法
boolean hasNext()
E next()
boolean hasPrevious() 判断集合中是否有上一个元素,反向遍历
E previous() 取出集合的上一个元素
6.List接口的实现类的数据结构
数组 :
有索引,数组中元素的地址是连续,查询速度快
数组的长度为固定,新数组创建,数组元素的复制,增删的效率慢
链表
链表没有索引,采用对象之间内存地址记录的方式存储
查询元素,必须通过第一个节点依次查询,查询性能慢
增删元素,不会改变原有链表的结构,速度比较快
三、集合
1.ArrayList
①特点
ArrayList类实现接口List,ArrayList具备了List接口的特性:有序,重复,索引
ArrayList集合底层的实现原理是数组,大小可变
数组的特点 : 查询速度快,增删慢
数组的默认长度是10个,每次的扩容是原来长度的1.5倍
ArrayList是线程不安全的集合,运行速度快
②源码解析
ArrayList类成员变量
private static final int DEFAULT_CAPACITY = 10; //默认容量
private static final Object[] EMPTY_ELEMENTDATA = {};//空数组
transient Object[] elementData; //ArrayList集合中的核心数组
private int size; //记录数组中存储个数
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //数组扩容的最大值
ArrayList集合类的构造方法
无参数构造方法
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //数组没有长度
有参数的构造方法
public ArrayList(int 10) {
if (initialCapacity > 0) {
//创建了10个长度的数组
this.elementData = new Object[10];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
ArrayList集合类的方法add()
new ArrayList<>().add("abc"); //集合中添加元素
public boolean add("abc") {
//检查容量 (1)
ensureCapacityInternal(size + 1);
//abc存储到数组中,存储数组0索引,size计数器++
elementData[size++] = "abc";//数组扩容为10
return true;
}
//检查集合中数组的容量, 参数是1
private void ensureCapacityInternal(int minCapacity = 1) {
//calculateCapacity 计算容量,方法的参是数组 , 1
// ensureExplicitCapacity (10) 扩容的
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//计算容量方法, 返回10
private static int calculateCapacity(Object[] elementData, int minCapacity = 1) {
//存储元素的数组 == 默认的空的数组 构造方法中有赋值
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//返回最大值 max(10,1)
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
//扩容
private void ensureExplicitCapacity(int minCapacity = 10) {
modCount++;
// 10 - 数组的长度0 > 0
if (minCapacity - elementData.length > 0)
//grow方法(10) 数组增长的
grow(minCapacity);
}
//增长的方法,参数是(10)
private void grow(int minCapacity = 10) {
//变量oldCapacity保存,原有数组的长度 = 0
int oldCapacity = elementData.length; // 0
//新的容量 = 老 + (老的 / 2)
int newCapacity = oldCapacity + (oldCapacity >> 1);// 0
// 0 - 10 < 0 新容量-计算出的容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity; //新容量 = 10
//判断是否超过最大容量
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//数组的赋值,原始数组,和新的容量
elementData = Arrays.copyOf(elementData, newCapacity);
}
2.linkedList
①linkedList集合的特点
linkedList类实现接口List,linkedList具备了List接口的特性:有序,重复,索引
linkedList底层实现原理是链表,双向链表
linkedList增删速度快
linkedList查询慢
linkedList是线程不安全的集合,运行速度快
②linkedList集合特有方法
集合是链表实现,可以单独操作链表的开头元素和结尾元素
void addFirst(E e) 元素插入到链表开头
void addLast(E e) 元素插入到链表结尾
E getFirst() 获取链表开头的元素
E getLast() 获取链表结尾的元素
E removeFirst() 移除链表开头的元素
E removeLast() 移除链表结尾的元素
void push(E e)元素推入堆栈中
E pop()元素从堆栈中弹出
③源码解析
linkedList集合的成员变量
transient int size = 0; //集合中存储元素个数计数器
transient Node
first; //第一个元素是谁 transient Node
last; //最后一个元素是谁
linkedList集合的成员内部类Node (节点)
private static class Node{ E item; //我们存储的元素 Node next; // 下一个节点对象 Node prev; // 上一个节点对象 //构造方法,创建对象,传递上一个,下一个,存储的元素 Node(Node prev, E element, Node next) { this.item = element; this.next = next; this.prev = prev; } }
linkedList集合的方法add()添加元素
void linkLast(E "abc") {
//声明新的节点对象 = last
final Node l = last; // l = null l "abc"节点
//创建新的节点对象,三个参数, 最后一个对象,"abc", 上一个对象null
final Node newNode = new Node<>(l, e, null);
//新节点赋值给最后一个节点
last = newNode;
if (l == null)
//新存储的几点赋值给第一个节点
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
3.Set集合
Set集合,是接口Set,继承Collection接口,Set集合不存储重复元素
Set接口下的所有实现类,都会具有这个特性
Set接口的方法,和父接口Collection中的方法完全一样
①Set接口实现类HashSet类
HashSet集合类的特点
实现Set接口,底层调用的是HashMap集合
HashSet的底层实现原理是哈希表
HashSet不保证迭代顺序,元素存储和取出的顺序不一定
线程不安全,运行速度快
③对象的哈希值
每个类继承Object类,Object类定义方法 :
public native int hashCode(); // C++语言编写,不开源
方法使用没有区别 : 方法返回int类型的值,就称为哈希值
④String类的哈希值
字符串类重写方法hashCode(),自定义了哈希值,哈希值的计算方法是 :
h = 31 * 上一次的计算结果 + 字符数组中元素的ASCII码值
*31 的目的,减少相同哈希值的计算
⑤哈希值的相关问题
两个对象的哈希值相同,不要求equals一定返回true. 两个对象的equals返回true,两个对象的哈希值必须一致
⑥哈希表的数据结构
数组 + 链表的组合体
class Node{
E element; //存储的元素
Node next; //下一个元素
}
main(){
Node[] node = new Node[5];
}
哈希表的底层数组长度默认是16个,扩容为原来长度的2倍
加载因子默认是0.75F,数组中存储元素的个数达到长度的75%,扩容
⑦哈希表存储对象的过程
4.红黑树(Red-Black-Tree)
二叉树,本质就是链表
查询速度快
每个一个节点,只有两个子节点,左和右
树长偏了
自然平衡二叉树
二叉树的基础上,改进,保证树是平衡的
红黑树
每个节点有颜色,要么红,要么是黑
根节点必须是黑色
叶子节点必须是黑色
变量表示颜色,true黑色,false红色
①TreeSet集合使用
TreeSet集合,底层是红黑树结构,依赖于TreeMap的实现
可以对存储到红黑树的元素进行元素的自然顺序排序
②TreeSet存储自定义对象
public static void treeSetStudent(){
Set set = new TreeSet();
set.add(new Student("a",10));
set.add(new Student("b",20));
System.out.println("set = " + set);
}
程序出现了异常,类型的转换异常 ClassCastException
异常原因,Student类不能进行类型的转换,有接口没有实现java.lang.Comparable.
类实现接口Comparable,这个类就具有了自然顺序
Student类具有自然顺序
实现接口Comparable,重写方法compareTo
public int compareTo(Student student){
return this.age - student.age;
}
程序出现了异常,类型的转换异常 ClassCastException
异常原因,Student类不能进行类型的转换,有接口没有实现java.lang.Comparable.
类实现接口Comparable,这个类就具有了自然顺序
Student类具有自然顺序
实现接口Comparable,重写方法compareTo
自定义比较器java.util.Comparator接口
public class MyCom implements Comparator{ @Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } } Set set = new TreeSet ( new MyCom());
5.linkedHashSet
底层的数据结构是哈希表,继承HashSet
linkedHashSet数据是双向链表, 有序的集合,存储和取出的顺序一样
public static void main(String[] args) {
Set set = new linkedHashSet<>();
set.add("b");
set.add("e");
set.add("c");
set.add("a");
set.add("d");
System.out.println("set = " + set);
}
6.Collections工具类
java.util.Collection 集合的顶级接口
java.util.Collections 操作集合的工具类
工具类的方法全部静态方法,类名直接调用
主要是操作Collection系列的单列集合,少部分功能可以操作Map集合
例
public class CollectionsTest {
public static void main(String[] args) {
sort2();
}
//集合元素的排序,逆序
public static void sort2(){
List list = new ArrayList();
list.add(1);
list.add(15);
list.add(5);
list.add(20);
list.add(9);
list.add(25);
System.out.println("list = " + list);
//Collections.reverseOrder() 逆转自然顺序
Collections.sort(list,Collections.reverseOrder());
System.out.println("list = " + list);
}
//集合元素的排序
public static void sort(){
List list = new ArrayList();
list.add(1);
list.add(15);
list.add(5);
list.add(20);
list.add(9);
list.add(25);
System.out.println("list = " + list);
Collections.sort(list);
System.out.println("list = " + list);
}
//集合元素的随机交换位置
public static void shuffle(){
List list = new ArrayList();
list.add(1);
list.add(15);
list.add(5);
list.add(20);
list.add(9);
list.add(25);
System.out.println("list = " + list);
Collections.shuffle(list);
System.out.println("list = " + list);
}
//集合的二分查找
public static void binarySearch(){
List list = new ArrayList();
list.add(1);
list.add(5);
list.add(9);
list.add(15);
list.add(20);
list.add(25);
int index = Collections.binarySearch(list, 15);
System.out.println(index);
}
}



