异常&集合

1 异常

在这里插入图片描述

抛出异常格式:
选中要生成try catch的代码——右键——surround With——try /catch Block

public class Test{
		try{   
		}
		catch(Exception e//异常类型){
		//捕获到异常后怎么处理它
		}
		catch(Exception e//异常类型){
		}
		catch(Exception e//异常类型){
		}
		finally{
		//无论程序是否异常,都会执行的代码段
		}
}
  • 注意:
    1.一个try可以对应一个或者多个catch
    2.如果try中有一个语句发生异常,则这句语句后的其他语句将不执行
    3.异常也有父类子类,如果要写多个catchcatch中异常的顺序,需要先写子类(小类型)的异常,再写父类
    4.catch(异常 | 异常 | 异常),这里要注意的是,异常是需要是**同级(兄弟关系)**的异常,否则报错
    5.Java允许
try{
}
catch(Exception e){
}
try{
}
finally{
}

1.1 常见异常

  • 数组下标越界异常ArrayIndexOutOfBoundsException:4
public class TestTryCatch{
	//throws Exception 向上抛出异常(谁调用就抛给谁)最后是JVM
	public static void main(String[] args) throws Exception{
		try{   //抓
		int[] array = {1,2,3};
		System.out.println(array[4]);
		}
		catch(Exception e){     //捕获
			e.printStackTrace();//打印栈轨迹
			//System.out.println("系统异常,请联系管理员");
			//System.out.println("数组下标越界");
			//坑爹的:什么都不做
		}
		System.out.println("gpgo");
		//finally无论有没有错误,都会执行
		//finally{
		//	System.out.println("finally");
		//}
	}
}

在这里插入图片描述

  • 空指针异常NullPointerException
//创建一个字符串空引用
String str = null;
//此时又想调用“str”的属性或者方法
System.out.println(str.length());

在这里插入图片描述

  • 输入类型转换异常InputMismatchException
		Scanner a = new Scanner(System.in);
		int b = a.nextInt();
		System.out.println(b);

在这里插入图片描述

  • 数学异常ArithmeticException
		 Scanner a = new Scanner(System.in);
		 System.out.println(a.nextInt()/0);

在这里插入图片描述

  • 类型转换异常ClassCastException
public class Example {
	 public void ti(String str) {
		 System.out.println(str.length());
	 }
	 public static void main(String[] args) {
		 Object str = new String();
		 Example e = (Example)str;
		 
	 }
}

在这里插入图片描述

1.2 错误Throwable分类

分为:

  • 异常Exception:程序运行时发生的不正常事件,异常能够被程序处理,保证程序运行下去;例如除数为0

  • 错误Erro:程序运行期出现,通过异常处理无法解决;例如内层溢出,需要修改代码才能解决相关错误
    此外,Throwable是Exception和Error标准父类子类

  • 异常Exception中——栈溢出异常StackOverflowError

main(null);

在这里插入图片描述

  • 异常Exception中——堆溢出异常OutOfMemoryError heap堆
int [] array = new int[1024*1024*1024];

在这里插入图片描述

1.2.1 Exception分类

Exception分为运行时异常和非运行时异常。
在这里插入图片描述

  • 其中RuntimeException的子类是运行时异常(也叫非检测异常),其他都是非运行时异常(检测异常)

1.3 throw和throws

在这里插入图片描述

1.3.1 throw
  • throw 手动引发一个异常——异常对象,也就是创建了一个异常对象,用throw交给异常处理机制去处理
  • 与编码过程遇到一些特殊业务逻辑有关
  • 更直接、更明显的异常处理——制造异常
  • 抛出异常的方式:
throw new RuntimeException();

catch(Exception e){
	throw e;
}
public class ExampleException{
	
	public static void main(String[] args) {
		t("10");
	}
	public static void t(String s) {
		if (s.length()<10) {
			throw new RuntimeException("长度不能小于10");
		}
	}
}

在这里插入图片描述

1.3.2 throws
  • 一直向上抛出,谁调用这个就抛给谁,最后给JVM
  • 让调用者进行异常的处理
    *在这里插入图片描述
public class ExampleException{
	//throws Exception 向上抛出,谁调用就谁异常处理
	public void setName(String name) throws Exception{
		if (name.length()<=5) {
			//这是异常,手动引发一个异常
			//Exception 包含了runtime和非runtime
			throw new Exception();
		}
	}
	//throws Exception -> JVM
	public static void main(String[] args) throws Exception {
		ExampleException EE = new ExampleException();
		EE.setName("isi");
	}
}

在这里插入图片描述

1.3.3 自定义异常(异常不够用则新定义)

步骤:

1.继承Exception或者Exception下的某个子类
2.构造方法中加入合适的参数、必要的构造方法的重载
3.合适场景中,使用throw new 自定义异常类()
public class ExampleException extends RuntimeException {
	public ExampleException() {
		 super();
	 }
	public ExampleException(String str) {
		 super(str);
	 }
	
	public static void main(String[] args) {
		throw new ExampleException("长度不能小于10");
	}
}

1.4 return

  • 类似break用法——结束后续代码执行,终止方法
  • 和break不同的是,分支上可以有多个return,但是以最后一个为准

情况1

public class TestReturn {
	public void t1(int n) {
		System.out.println("t1-----------1");
		if (n > 1) {
			//n = 10 条件成立
			//结束了方法后续的执行
			return;
		}System.out.println("t2-----------2");
	}
	public static void main(String[] args) {
		new TestReturn().t1(10);
	}
}

在这里插入图片描述
情况2

public class TestReturn {
	public int t1(int n) {
		try {
			System.out.println("执行了try");
			return 0;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("执行了catch");
			return 1;
		}finally {
			System.out.println("执行了finally");
			
			//finally block does not complete normally
			//因为可能有两次return,但是不影响程序执行
			return 2;
		}
	}
	public static void main(String[] args) {
		int n = new TestReturn().t1(10);
		System.out.println(n);
	}
}

在这里插入图片描述
情况3

		int a = 10;
		try {
			System.out.println(1/0);
			System.out.println("执行了try");
			return ++a;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("执行了catch");
			return ++a;
		}finally {
			System.out.println("执行了finally");
			
			//finally block does not complete normally
			//因为可能有两次return,但是不影响程序执行
			return ++a;
		}

在这里插入图片描述
情况4

		int a = 10;
		try {
			System.out.println(1/1);
			System.out.println("执行了try");
			return ++a;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("执行了catch");
			return ++a;
		}finally {
			System.out.println("执行了finally");
			
			//finally block does not complete normally
			//因为可能有两次return,但是不影响程序执行
			return ++a;
		}

在这里插入图片描述
情况5

		int a = 10;
		try {
			System.out.println("执行了try");
			return 1;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("执行了catch");
			return 2;
		}finally {
			System.out.println("执行了finally");
			
			//finally block does not complete normally
			//因为可能有两次return,但是不影响程序执行
			return 3;
		}

在这里插入图片描述

1.5 断言

关键字:assert

  • 默认情况下是没有开启断言的功能的

  • 开启断言 -ea
    在这里插入图片描述

  • 调试程序中使用,只是程序调试的方式

assert<布尔表达式>
assert<布尔表达式><错误信息>
  • 当布尔表达式的值是true时,忽略assert
  • 当布尔表达式的值是false时,发生AssertionError错误,程序中断,如果用第二种形式同时显示错误信息
public class TestAssert {
	public void t1() {
		int n1 = 2;
		int n2 = 2;
		System.out.println("t1 --1:" + n1);
//		assert n1 != 1;   
//t1 --1:2
//t1 --2:2
		assert n1 == 1:"我是你们最爱的断言提示";
		System.out.println("t1 --2:" + n2);
	}
	public static void main(String[] args) {
		TestAssert ta = new TestAssert();
		ta.t1();
	}
}

在这里插入图片描述

2 集合

使用方法:看无参有参构造,再实例化调用
Collection
在这里插入图片描述

list接口 ——awt包下
List组件向用户显示文本项的滚动列表。 可以设置列表,以便用户可以选择一个项目或多个项目。
——java.util下
有序集合(也称为序列 )。 该界面的用户可以精确控制列表中每个元素的插入位置。 用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。

  • 泛型:
    没有写泛型——for(Object book : list)
    写了泛型——for(Book book : list) 不需要再进行类型转换,取出来就是Book类型
//接口的引用					指向实现类对象
接口<任意类型1> 引用名 = new 接口<任意类型2>();
//ArrayList<String> alist = new ArrayList<String>();
//任意类型1需要和任意类型2保持一致

在这里插入图片描述

2.1 ArrayList

ArrayList注意点:

  1. 长度可变,类型可以固定,也可以Object;提供了大量的算法实现。如ArrayList
  2. ArrayList是一个用数组实现的列表
  3. ArrayList底层是Object类型的数组
  4. 元素可以重复,可以为null,如果是两个重复的数据,remove会删除前面那个
  5. 可以精确定位,也就是通过get(index)索引来定位

ArrayList优点:

  1. ArrayList底层以数组实现(随机访问模式)(实现了RandomAccess接口,所以get很快)
  2. ArrayList顺序添加一个元素只是往数组添加了一个元素而已,非常方便
  3. 可以自动扩容,默认每次扩容变成原来的1.5倍,默认情况下,容量为10

ArrayList缺点:

  1. 插入删除元素的效率不高
  2. 根据元素下标查找元素需要遍历整个元素数组,效率不高
  3. 线程不安全

练习:
控制台输入五个人的姓名,存在集合里面,再输出出来

public class TestArrayList {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("请输入五个人的名字");
		Scanner s = new Scanner(System.in);	

		//实例化ArrayList对象
		ArrayList<String> alist = new ArrayList<String>();
		for (int i = 0; i < 5; i++) {
			String name = s.next();
			alist.add(name);
		}s.close();
		
		System.out.println("**********结果foreach循环:************");
		for (String string : alist) {
			System.out.print(string + " ");
		}System.out.println();
		
		System.out.println("**********结果for循环:***************");
		for (int i = 0; i < alist.size(); i++) {
			System.out.print(alist.get(i) + " ");
		}
		//在下面结果栏没有显示出来
		System.out.println("**********结果用Jdk foreach直接输出集合:***************");
		//JDK1.8后才有!
		list.forEach(System.out::println);
	}
}

在这里插入图片描述

  • List接口为Collection子接口,List所代表的是有序可重复、有索引的Collection,add() get() remove()
  • list.size();获取大小 list.get()获取 list.add()添加数值 list.remove()删除数据
    在这里插入图片描述

扩展:如何观察得到扩容的过程?
扩容得到原来的1.5倍
在这里插入图片描述

练习:
定义一个Student类,id和name,实例化3个学生对象,将3个学生对象添加到集合中,再使用for或者foreach遍历出来

import java.util.ArrayList;

public class Student {
	//属性私有化
	private String name;
	private int id;
	//无参构造
	public Student() {
		super();
	}
	//有参构造
	public Student(String name, int id) {
		super();
		this.name = name;
		this.id = id;
	}
	//提供公共getter和setter方法
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	//提供toString方法
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "姓名:" + name + "\t" +"学号:" + id;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//实例化三个对象并给值
		Student s1 = new Student("小明",12);
		Student s2 = new Student("小春",15);
		Student s3 = new Student("小刀",13);
		
		//实例化ArrayList对象
		ArrayList<Student> list = new ArrayList<Student>();
		
		//添加list到ArrayList中
		list.add(s1);
		list.add(s2);
		list.add(s3);
		
		//for循环
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		//foreach
		for (Object object : list) {
			System.out.println(object);
		}
		//直接输出集合
		System.out.println(list);
		//JDK1.8
		list.forEach(System.out::println);
	}
}

2.1 linkedlist

  • 特别的是,相较于ArrayList,增加了对头部尾部插入的操作,如getFirst() getLast() addFirst() addLast(),remove(),removeFirst(),removeLast(),但底层实现时调用的方法一致,没什么大区别。
  • 支持泛型
  • linkedlist底层的实现是双向链表,在添加和删除元素时具有比ArrayList更好的性能,但非线程安全

2.2 vector

  • protect object[] obj 底层也是数组

vector特点:

  1. 相较于ArrayList,vector的方法带有synchronize关键字修饰,表示支持线程同步
  2. 常见方法与ArrayList差不多

2.3 Set(接口)

  1. set是一种不包括重复元素的Collection,所以随机访问没有意义
  2. 允许null的存在但是仅有一个,和List一样
2.31 HashSet

注意点:

  1. 无序不重复(重复则保留之前的那一个),所以没有get()方法
  2. 允许null(只能一个),底层是hashMap,
  3. 支持Java的JDK1.8的遍历方法
System.out.println("hashset.size:" + hashSet.size());
  1. 支持迭代器
//调用iterator的方法
Iterator<Book> iterator = hashSet.iterator();
  1. 实现不同步,线程不安全
  2. 默认的初始容量16,负载因子(loadFactor)0.75(16 x 0.75 = 12 在容量达到12变成13时,开始扩容到原来的2倍,也就是16*2=32)
		Book t1 = new Book("t1","Java从入门到放弃","12元");
		Book t2 = new Book("t2","PHP从入门到放弃","44元");
		Book t3 = new Book("t2","PHP从入门到放弃","44元");
		
		HashSet<Book> hashSet = new HashSet<Book>();
		
		hashSet.add(t1);
		hashSet.add(t2);
		hashSet.add(t3);
		//没有重写前,
		//重写后比较值,值相等就算重复
		System.out.println("hashset.size:" + hashSet.size());

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
面试题:哪个集合元素不能重复?判断是否重复依据?如果让我们自己定义的类也去遵循一定的“业务标准”【重写equals和hashCode方法】
大致思想:

  • 先判断hashCode()方法来确定元素的存储位置(也就是值是否相等),不等则认为不是同一个对象
  • 相等则去调用equals方法判断(比较值),如果返回true,认为重复;否则不重复
    源码再现
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

3 Iterator迭代器

  1. hasNext();——boolean
  2. next();——E(泛型所定义的一个类型)
  3. while循环使用迭代(循环次数不固定)
  4. 支持泛型写法
  5. 迭代时不允许删除,否则报illegalStateException异常
iterator()
//以正确的顺序返回该列表中的元素的迭代器

ArrayList中使用iterator()

		ArrayList<Book> arrayList = new ArrayList<Book>();
		arrayList.add(t1);
		Iterator<Book> itor1 = arrayList.iterator();
		while (itor1.hasNext()) {
			System.out.println(itor1.next().getName());
		}

LinkedList中使用iterator()

		LinkedList<Book> linkedList = new LinkedList<Book>();
		linkedList.addFirst(t1);
		Iterator<Book> itor2 = linkedList.iterator();
		while (itor2.hasNext()) {
			System.out.println(itor2.next().getName());
		}

Vector中使用iterator()

		Vector<Book> vector = new Vector<Book>();
		vector.add(t1);
		Iterator<Book> itor3  = vector.iterator();
		while (itor3.hasNext()) {
			System.out.println(itor3.next().getName());
		}

例题:
考察hasNext查询和next的索引移动规律

	ArrayList list = new ArrayList();
		list.add("a");
		list.add("b");
		list.add("c");
		//返回值为Iterator接口
		Iterator itor = list.iterator();
		System.out.println(itor.hasNext());
		System.out.println(itor.hasNext());
		System.out.println(itor.hasNext());
		System.out.println(itor.hasNext());
		System.out.println(itor.next());
		System.out.println(itor.next());
		System.out.println(itor.next());
		System.out.println(itor.hasNext());
		System.out.println(itor.next());

数组里面只有3个元素,4个next会找到索引为3的元素,因为没有,所以报错
**hasNext()**只是查找,没有索引的增加
在这里插入图片描述

4 Map

在这里插入图片描述

4.1 HashMap(无序)

注意点:

  1. 是基于哈希表的实现的Map接口非同步实现
  2. 在以前的版本,HahMap采用的是数组+链表实现,JDK1.8数组+链表+红黑树(平衡搜索二叉树) 实现
  3. 允许null值和null键
  4. 默认容量16,负(加)载因子0.75(内容达到160.75=12时会扩容到16 2倍=32)
  5. 不支持add()和addAll()
  6. 非线程安全,线程不同步
  7. set源码底层有HashMap的put方法
  8. get(K) put(K V) remove(K V) remove(K)
  9. key键不能重复,如果重复则后续会覆盖前一个值
		hashMap.put(1, "大哥");
		hashMap.put(1, "小哥");

在这里插入图片描述

  1. 可以重复
		hashMap.put(1, "大哥");
		hashMap.put(2, "大哥");

在这里插入图片描述

		//得到keyset -> 所有key集合   set
		System.out.println(hashMap.keySet());
		//得到value结合values Collection
		System.out.println(hashMap.values());
		//键+值	-> 整体
		System.out.println(hashMap.entrySet());

在这里插入图片描述
遍历方法

		//遍历——entrySet
		//object类型,如果是String类型的,因为类型不匹配,也不能转型(跟后面比较)
		for (Object object : hashMap.entrySet()) {
			System.out.println(object);
		}
		//遍历——key  迭代器
		Set keySet = hashMap.keySet();
		
		Iterator iterator = keySet.iterator();
		
		while (iterator.hasNext()) {
			Object key = (Object) iterator.next();
			System.out.println("it -> key" + key);
			//通过key得到value
			System.out.println("key -> value" + hashMap.get(key));
		}
		//遍历——key  keyset
		for (Object object : hashMap.keySet) {
			System.out.println(object);
		}
		//遍历——value  values
		for (Object object : hashMap.values) {
			System.out.println(object);
		}
		for (int i = 0; i < hashMap.size(); i++) {
			System.out.println(hashMap.get(i));
		}
		//foreach jdk 1.8
		hashMap。forEach(System.out::println);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4.2 TreeSet

注意点:

  1. 有序,按照自然顺序排序(字母则按字母顺序、数字按照大小)
ts.add("ane");
ts.add("")

在这里插入图片描述

  1. 实现(线程)不同步

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5 自然排序

5.1 Arrays

支持内部外部比较器
Arrays类包含用于操作数组的各种方法(如排序和搜索),还包含一个静态工厂,可以将数组视为列表。
在这里插入图片描述

comparable内部比较器
  1. 类如果想【支持排序】,就要实现comparable接口,该接口称为对象的内部比较器
    比如这边Integer就实现了Comparable接口
    在这里插入图片描述
  2. 支持排序,但只能有一种排序逻辑,比较受限制
comparator外部比较器
  1. 可以使用外部比较器Comparator,灵活为类定义多种比较器 ,此时类本身不需要实现Comparable接口
    Comparator接口方法:
在这里插入代码片

在这里插入图片描述
注意: 如果没有实现Comparable/Comparator会抛出ClassCastException异常

5.2 collections工具类

包含很多对集合的操作的静态方法
字段:list map set
支持内部外部比较器
内部比较器

	//重写compareTo的方法
	@Override
	public int compareTo(Student o) {
		// -1按照id升序(从小到大)
		return this.age < o.age ? -1 : this.age==o.age ? 0:1;
	}
	
	
	public static void main(String[] args) {
		Student s1 = new Student(200,"a",223);
		Student s2 = new Student(100,"b",333);
		Student s3 = new Student(300,"a",113);
		
		Student[] array = {s1,s2,s3};
		
		Arrays.sort(array);
		
		for (Student student : array) {
			System.out.println(student);
		}
	}

在这里插入图片描述
外部比较器

	public static void main(String[] args) {
		Teacher t1 = new Teacher(200, "a", 223);
		Teacher t2 = new Teacher(100, "b", 333);

		Teacher[] teachers = { t1, t2 };
		
		//匿名内部类实现
		//Arrays.sort(teachers,new IdComparator());
		Arrays.sort(teachers,new Comparator<Teacher>() {
			@Override
			public int compare(Teacher o1, Teacher o2) {
				// TODO Auto-generated method stub
				return o1.getAge() < o2.getAge() ? -1 : o1.getAge() == o2.getAge() ? 0 : 1;
			}
		});

		for (Teacher t : teachers) {
			System.out.println(t);
		}
	}
//新建外部类实现
class IdComparator implements Comparator<Teacher> {
	public int compare(Teacher o1, Teacher o2) {
		// TODO Auto-generated method stub
		return o1.getId() < o2.getId() ? -1 : o1.getId() == o2.getId() ? 0 : 1;
	}
}

在这里插入图片描述
在这里插入图片描述
Collection和Collections有什么区别,Array和Arrays有什么区别?

collectioncollections
接口
集合层次结构中,子接口有list,set提供了很多对集合操作的静态方法
add,clear,remove,size方法等Sort支持外部比较器reverse,copy,max,min,
Array[数组类型]/理解成Arrays
引用类型,代指[]
自己实现算法Sort提供很多操作数组的方法
Array类提供静态方法来动态创建和访问Java数组。在包Java.lang.reflect.Array

线程同步

多个线程同时请求一个集合对象的时候,比如List.add(),数据可能会丢失(ArrayList、LinkList、HashSet、HashMap)
map本身不是线程同步,但是他的ConcurrentHashMap是synochromnzied,支持线程同步。

泛型

List<String> list = new List();
//使用泛型

list<E>
//泛型的定义

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千鹤万象

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值