创建表不可变集合
不可变集合,就是不可被修改的集合
集合的数据项在创建的时候提供,并且在整个生命周期种豆不可被改变。否则报错
为什么要创建不可变集合
如果某个数据不能被修改,把它防御性的拷贝到不可变集合中十个很好的实践
或者当集合对象被不可信任的库调用时,不可变性是是安全的
如何创建不可变集合
在List,Set,Map接口中,都存在of方法,或者创建一个不可变集合
List<String> list =List.of("再看一眼就会爆炸","再靠近点就被融化");
Set<String> ikun=Set.of("小黑子树脂666","香精煎鱼");
Map<String, Integer> map=Map.of("食不食油饼", 1,"蒸虾头",2);
Stream流
什么是Stream流
在java8中,得益于Lambda表达式所带来的函数式变成,引入了一个全新的Stream流的概念
目的:用于简化集合和数组的ApI
Stream流的思想
Stream流像是一个传送带流水线,对数据进行各种处理
得到集合或者数组的Stream流
将元素加入到传送带上
使用Stream流简化的API来方便的操作元素
Stream流的三类方法
获取Stream流
使用Collection接口中的默认方法Stream()生成流
这些都是中间方法,也称为非终结方法,可以返回新的流,支持链式编程
在stream流中无法直接修改集合数组中的元素,可以创建新的对象
Set<site> sites=new TreeSet<>();
sites.add(new site(110,500,"数值"));
sites.add(new site(120,400,"小黑子"));
sites.add(new site(130,300,"ikun"));
sites.add(new site(140,200,"蒸虾头"));
sites.add(new site(130,300,"ikd"));
sites.add(new site(140,200,"小虾头"));
Set<String> list=new TreeSet<>();
list.add("ikun");
list.add("只因");
list.add("再看一眼就会爆炸");
list.add("在靠近点就会融化");
//过滤名字开头为“小”的数据
sites.stream().filter(site-> site.getName().startsWith("小")).forEach(site->System.out.println(site));
//得到名字长度为三的数量
long a=sites.stream().filter(site -> site.getName().length()==3).count();
System.out.println(a);
//得到开头为i的前三个数据
sites.stream().filter(site->site.getName().startsWith("i")).limit(3).forEach(site-> System.out.println(site));
//得到开头为“小”的数据,跳过符合条件的前0个
System.out.println("-------------");
sites.stream().filter(site->site.getName().startsWith("小")).skip(0).forEach(site-> System.out.println(site));
//map加工方法,新创建的类为加工后的类型
list.stream().map(( s-> "黑马"+s)).forEach(s-> System.out.println(s));
list.stream().map((String s)->new site(120 ,130,s)).forEach(s-> System.out.println(s));
Stream s1=sites.stream().filter(site->site.getName().startsWith("i"));
Stream s2=sites.stream().filter(site->site.getName().startsWith("小"));
//当两个不同类型的数据合并,
Stream.concat(s1,s2).forEach(s-> System.out.println(s));
//去重复方法
s2.distinct();
Stream流的收集
收集Stream流的作用
Stream流是操作集合/数组的手段
操作的结果数据最终要回到集合或者数组中去

异常处理
异常概述
什么是异常
异常是程序在编译或者执行的过程中可能出现的问题,注意语法错误不算在异常体系中
比如:数组索引越界,空指针异常,日期格式化异常,等.....
为什么要学习异常
异常一旦出现,如果没有提前处理,程序就会退出JVM虚拟机而终止
处理异常并且避免异常,然后提前处理异常,体现的是程序的安全性,健壮性
异常体系

Error:
系统级别问题,JVM退出等,代码无法控制
Exception:java.lang包下,称为异常类,它表示程序本身可以处理的问题
RuntimeException及其子类:运行时异常,编译阶段不会报错(空指针异常,数组索引越界异常)
除RuntimeException之外所有的异常:编译时异常,编译期必须处理的,否则程序不能通过编译。(日期格式化异常)
常见运行时异常
直接继承自RuntimeException或者其子类,编译阶段不会报错,运行时可能出现的错误
运行时异常示例
数组索引越界异常:ArrayIndexOutOfBoundsException
空指针异常:NullPointerException.直接输出没有问题,但是调用空指针的变量的功能就会报错
数学操作异常:ArithmeticException
类型转换异常ClassCastException
数字转换异常:NumberFormatException
运行时异常,一般是程序员业务没有考虑好或者编程逻辑不严谨引起的程序错误
常见编译时异常
不是RuntimeException或者其子类的异常,编译阶段就报错,必须处理,否则代码不通过
编译时异常的作用
在编译阶段报错,提醒程序员一些容易出错的地方
异常的默认处理流
默认会在出现异常的地方自动创建一个异常对象:ArithmeticException
异常会从方法中出西安的点这里抛出给调用者,低走用着最终抛出给JVM虚拟机
虚拟机接收到异常对象后,会现在控制台直接输出异常栈信息数据
直接从当前执行的异常点干掉当前程序
后续代码没有机会执行
默认异常处理机制并不好,容易引起程序死亡
编译时异常的处理机制
异常处理方式1-throws
用在方法上,可以将方法内部出现的异常抛出给本方法的调用者处理
这种方式并不好,发生异常的方法自己不处理异常,如果一场最终抛出给虚拟机将引起程序死亡
使用格式
方法 throws 异常1,异常2....{
}
规范做法:
方法 throws Exception{
}
异常处理方式方式2——try...catch...
监视捕获异常,用在方法内部,可以将方法内部出现的异常直接捕获处理
这种方式还可以,发生异常的方法自己独立完成异常的处理,程序可以继续往下执行
使用格式:
try{
可能出现异常的代码
}catch(异常类型1 变量){
处理异常
}catch(异常类型2 变量){
处理异常
}...
建议格式
try{
可能出现异常的代码
}catch(Exception 变量){
e.printStackTrace();
}
异常处理方式3——前两者结合
当方法出现异常时,先将异常抛出到main方法,
再在main方法中进行try...catch...操作,进行提醒或其他操作
在开发中按照规范来说,第三种方式是最好的,底层的异常抛出给最外层,组外层集中处理
实际应用中,只要代码能编译通过,并且功能完成,是可以使用其他方法的
运行时异常的处理机制
按照规范还是按照上文异常处理方式3处理较好
异常处理使代码更稳健的案例
自定义异常
1,自定义编译时异常
定义一个异常类继承Exception
重写构造器
再出现异常的地方用throw new对象抛出
throw和throw的区别:
throw:在方法内部直接创建一个异常对象,并从此点抛出
throws:用在方法生命上,抛出方法内部的异常
2,自定义运行时异常
定义一个异常类继承RuntimeException
重写构造器
在出现异常的地方用throw new自定义对象抛出
不需要再方法声明上抛出异常了,在最外层捕获抛出即可