不可变集合
集合的数据项在创建的时候提供,并且在整个生命周期中都不可改变。否则报错
为什么要不可变合集
如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践。 或者当集合对象被不可信的库调用时,不可变形式是安全的
List<Double> lists = List.of(666.3,555.2,777.2);
Set<String> names = Set.of("我", "是", "笨", "蛋" );
Map<String, Integer> maps = Map.of("豹女",3, "索子哥", 5 , "迭嘉", 8);
定义完成后不可以修改,或者添加、删除
List、Set、Map接口中,都存在of方法可以创建不可变集合
Stream流
Stream初体验
目的是写一个String name 的名字的集合 把其中的名字是三个字的和姓张的给筛选出来
public class test {
public static void main(String[] args) {
List<String> name=new ArrayList<>();
Collections.addAll(name,"张三","张无忌","张三丰","李四");//原始方法
// List<String>zhang=new ArrayList<>();
// for (String names : name) {
// if(names.startsWith("张")){
// zhang.add(names);
// }
// }
// System.out.println(zhang);
// List<String> zhangsan=new ArrayList<>();
// for (String namess : zhang) {
// if(namess.length()==3){
// zhangsan.add(namess);
// }
// }
// System.out.println(zhangsan);
name.stream().filter(s->s.startsWith("张")&& s.length()==3).forEach(s-> System.out.println(s));//Stream 的方法
}
}
Stream流核心思想
先得到集合或者数组的Stream流, 把元素放上去 然后就用这个Stream流简化的API来方便的操作元素
Stream 的作用
简化集合、数组操作的API。结合了Lambda表达式
Stream流的三类方法
获取Stream流 创建一条流水线,并把数据放到流水线上准备进行操作
中间方法 流水线上的操作。一次操作完毕之后,还可以继续进行其他操作。
终结方法 一个Stream流只能有一个终结方法,是流水线上的最后一个操作
获取stream流
Collection<String> list = new ArrayList<>();
Stream<String> s = list.stream();
//Collection集合获取流
Map<String, Integer> maps = new HashMap<>();// 键流
Stream<String> keyStream = maps.keySet().stream(); // 值流
Stream<Integer> valueStream = maps.values().stream();// 键值对流(拿整体)
Stream<Map.Entry<String,Integer>> keyAndValueStream = maps.entrySet().stream();
// Map获取Stream流
//数组获取Stream流
String[] names = {"张三","张无忌","张三丰","李四"};
Stream<String> nameStream = Arrays.stream(names);
Stream<String> nameStream2 = Stream.of(names);
总结
集合通过Stream()方法调用
Stream的常用Api
forEach : 逐一处理(遍历) count:统计个数 -- long count(); filter : 过滤元素 -- Stream<T> filter(Predicate<? super T> predicate) limit : 取前几个元素 skip : 跳过前几个 map : 加工方法 concat : 合并流
public class teat3 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
Collections.addAll(list,"王牛马","张牛马","牛爷爷","牛图图","牛马");
//过滤元素 filter 和 遍历 forEach
list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));//这是过滤的姓张的
System.out.println("_____________________________");
long size =list.stream().count();//计算个数 4
long sizes=list.stream().filter(s -> s.length()==3).count(); //只要长度为3的 有4个
System.out.println(size);
System.out.println(sizes);
//取前2个元素
list.stream().limit(2).forEach(s -> System.out.println(s));
System.out.println("_____________________________");
//跳过前3个元素
list.stream().skip(3).forEach(s -> System.out.println(s));
System.out.println("_____________________________");
//map加工方法
//原理 第一个参数原材料 -> 第二个参数是加工后的结果
list.stream().map(s -> "我是"+s).forEach(s -> System.out.println(s));
System.out.println("_____________________________");
//合并流
Stream<String> s1= list.stream().filter(s -> s.startsWith("牛"));
Stream<String> s2= Stream.of("nb","nb");
Stream<String> s3=Stream.concat(s1,s2);
//s3.forEach(s -> System.out.println(s));
System.out.println("_____________________________");
//去重复元素
s3.distinct().forEach(s -> System.out.println(s));
结果
张牛马
_____________________________
5
4
王牛马
张牛马
_____________________________
牛图图
牛马
_____________________________
我是王牛马
我是张牛马
我是牛爷爷
我是牛图图
我是牛马
_____________________________
_____________________________
牛爷爷
牛图图
牛马
nb
Stream 流的收集操作
public class test5 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
Collections.addAll(list,"王牛马","张牛马","牛爷爷","牛图图","牛马","牛皮","牛皮");
//把元素收集到List集合中
Stream<String> s1= list.stream().filter(s -> s.startsWith("牛"));
List<String> niu= s1.collect(Collectors.toList());
System.out.println(niu);
//流只能使用一次 用完s1就没了,重新定义set的s2
//把元素收集到Set集合中
Stream<String> s2=list.stream().filter(s ->s.startsWith("牛"));
Set<String> niuSet=s2.collect(Collectors.toSet());
System.out.println(niuSet);
//把元素收集到数组中
Stream<String> s3=list.stream();
Object []arr=s3.toArray();
//System.out.println(arr);
//要是有其他类型的
// String[] arrs = s3.toArray(String[]::new);
System.out.println("Arrays数组内容:" + Arrays.toString(arr));
}
}
结果
[牛爷爷, 牛图图, 牛马, 牛皮, 牛皮]
[牛爷爷, 牛图图, 牛皮, 牛马]
Arrays数组内容:[王牛马, 张牛马, 牛爷爷, 牛图图, 牛马, 牛皮, 牛皮]
什么是异常
异常是程序在“编译”或者“执行”的过程中可能出现的错误,注意:语法错误不算在异常体系中。 比如:数组索引越界、空指针异常、 日期格式化异常,等…
为什么要学习异常
异常一旦出现了,如果没有提前处理,程序就会退出JVM虚拟机而终止. 研究异常并且避免异常,然后提前处理异常,体现的是程序的安全, 健壮性
异常分为
编译时异常,是在编译成class文件时必须要处理的异常,也称之为受检异常
运行时异常,在编译成class文件不需要处理,在运行字节码文件时可能出现的异常
常见的异常
数组索引越界异常: ArrayIndexOutOfBoundsException。*/
int[] arr = {1, 2, 3}
System.out.println(arr[3]); // 运行出错,程序终止
空指针异常 : NullPointerException。直接输出没有问题。但是调用空指针的变量的功能就会报错
String name = null;
System.out.println(name.length());
类型转换异常:ClassCastException
Object o = 23;
String s = (String) o; // 运行出错,程序终止
数学操作异常:ArithmeticException
int c = 10 / 0;
数字转换异常: NumberFormatException
String number = "23aabbc";//
//Integer it = Integer.valueOf(number); // 运行出错,程序终止
//System.out.println(it + 1);
编译时异常
编译时异常:继承自Exception的异常或者其子类 编译阶段报错,必须处理,否则代码不通过。
异常处理方式
方式1
throws:用在方法上,可以将方法内部出现的异常抛出去给本方法的调用者处理
抛出异常格式
方法 throws 异常1 ,异常2 ,异常3 ..{ }
规范做法
throws Exception{ }
方式2
监视捕获异常,用在方法内部,可以将方法内部出现的异常直接捕获处理。 这种方式还可以,发生异常的方法自己独立完成异常的处理,程序可以继续往下执行。
格式:
try{ // 监视可能出现异常的代码! }catch(异常类型1 变量){ // 处理异常 }catch(异常类型2 变量){ // 处理异常 }...
ctrl+ALT+T 快捷键
方式3
前两者集合
方法直接将异通过throws抛出去给调用者 调用者收到异常后直接捕获处理。
总结
底层的异常抛出去给最外层,最外层集中捕获处理。
自定义异常
Java无法为这个世界上全部的问题提供异常类
如果需要管理业务问题就西药自己定义异常类
好处是
可以提醒自己业务问题
如果出现bug,可以很清晰的指出出出错的地方
自定义编译时异常 定义一个异常类继承Exception. 重写构造器。 在出现异常的地方用throw new 自定义对象抛出,
自定义运行时异常 定义一个异常类继承RuntimeException. 重写构造器。 在出现异常的地方用throw new 自定义对象抛出!