1.Stream流
1.1 对Stream流的认识
1.2 Stream流的操作全过程
如果我们把Stream流理解成一条流水线(传送带),我们就需要最基本的三个操作:创建一个流水线,在流水线上进行中间操作,最后结束这个流水线。
1.2.1获取Stream流(创建流水线)
我们只有先获取流,才能使用流的功能。
(集合/数组)获取流:
//集合获取流:
Collection<String> list=new ArrayList<>(); //1.Collection集合获取流
Stream<String> s=list.stream();
Map<String,Integer> maps=new HashMap<>(); // 2.Map集合获取流
Stream<String> keyStream=maps.keySet().stream();//键流
Stream<Integer> valueStream=maps.values().stream();//值流
Stream<Map.Entry<String,Integer>> keyandValueStream=maps.entrySet().stream();
//"键值对"流
//数组获取流:
String[] arrs={"也许","本该","可能"};
Stream<String> arrsStream1=Arrays.stream(arrs);//方式一
Stream<String> arrsStream2=Stream.of(arrs); //方式二
1.2.2 Stream流的中间方法(流水线上的操作)
(1)Stream流的常用API:
(2)使用流:
18行那里省略了一个学生类(只有一个参数name,配有get和set方法、无参和有参构造器,还重写了toString方法)。map加工方法把第2行所有的人名都加工成了一个学生对象。
List<String> list=new ArrayList<>();
Collections.addAll(list,"张一二","张三四","江五","张六","李七八");//人名
//1.filter 过滤
list.stream().filter(s ->s.startsWith("江")).forEach(s -> System.out.println(s));
//2.count 元素的数目
long size=list.stream().count();
//3.limit 取前几个元素,直接输出会返回地址
list.stream().limit(2).forEach(System.out::println);
System.out.println(list.stream().limit(3));
//4.skip 跳过前几个元素
list.stream().skip(4).forEach(System.out::println);
//5.map 加工方法 第一个参数材料 -> 第二个参数材料
list.stream().map(s ->"聪明的"+s).forEach(a -> System.out.println(a));
//在所有人名前都加上"聪明的"
list.stream().map(s ->new Student(s)).forEach(s -> System.out.println(s));
//简化为:
list.stream().map(Student::new).forEach(System.out::println);
// 构造器引用 方法引用
//6.contact 合并流
Stream<String> s1=list.stream().filter(s ->s.startsWith("李"));
Stream<Integer> s2=Stream.of(18);
Stream<Object> s3= Stream.concat(s1,s2);
s3.forEach(s -> System.out.println(s));
1.2.3 终结Stream流(结束流水线)
注意:
调用完成终结方法后,由于不会再返回Stream流,也就无法再继续使用了。
1.3 收集Stream流
1.3.1 收集Stream流的含义
1.3.2 Stream流的收集方法
收集流:
流只能收集一次,故以下是不同的流。由于Map集合是双列集合,因此将Stream流收集到Map集合是较为麻烦和不实用的,这里不做介绍。
(1)将Stream流收集到集合中:
List<String> list=new ArrayList<>();
Collections.addAll(list,"张一二","张三四","张三四","江五","张六","李七八");
//1.Collectors工具类的toList和toSet方法:(得到可变的List和Set集合)
Stream<String> s1=list.stream().filter(s->s.startsWith("张"));
List<String> zhanglist=s1.collect(Collectors.toList());
Stream<String> s2=list.stream().filter(s->s.startsWith("张"));
Set<String> zhangSet=s2.collect(Collectors.toSet());
(2)将Stream流收集到数组中:
Stream<String> s3=list.stream().filter(s->s.startsWith("张"));
Object[] arrs=s3.toArray();
Arrays.toString(arrs1)//Arrays.toString 返回数组内容
14行这里用Object类型肯定能接,但如果已知数组类型就是String,该怎么写呢?如下:
String[] arrs=s3.toArray(new IntFunction<String[]>() {
@Override
public String[] apply(int value) {
return new String[value];
}
});
//用lambda表达式简化为:
String[] arrs3=s3.toArray(String[]::new);
改进:上面调用Collectors工具类把Stream流收集成List、Set集合,较为麻烦。那么有没有简单一点的方法呢,就像收集数组时可以直接调用toArray()方法。如下:改进List集合收集流:
List<String> list=new ArrayList<>();
Collections.addAll(list,"张一二","张三四","张三四","江五","张六","李七八");
Stream<String> s1=list.stream().filter(s->s.startsWith("张"));
List<Strig> list=s1.toList();
在第4行,一行把Stream流收集到List集合中了。不过,较为遗憾的是:目前还没有类似的toSet()收集流方法。这就要靠各位将来去开发了,未来可期哈哈哈。
注意:
用toArray和toList收集到的是不可变的数组和集合。
2.异常处理
2.1 对异常的理解
2.2 异常体系
2.2.1 两种重要异常
我们结合JAVA程序的运行过程来看:
什么是编译时异常和运行时异常呢?
2.2.2 两种异常的实例
运行时异常
实例:
int arr[] = {1, 2, 3};
System.out.println(arr[3]);
//1.数组索引越界异常 (ArrayIndexOutOfBoundsException)
String name = null;
System.out.println(name.length());
//2.空指针异常 (NullPointerException)
Object o = 23;
String s = (String) o;
//3.类型转换异常 (ClassCastException)
int c = 10 / 0;
//4.数学操作异常 (ArithmeticException)
String number = "23adgsa";
Integer it = Integer.valueOf(number);
//5.数字转换异常 (NumberFormatException)
编译时异常
实例:
public static void main(String[] args) throws ParseException {
String date = "1973-01-03 10:54:37";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d = sdf.parse(date); //日期解析异常(时间格式不对应)
System.out.println(d);
}
2.3 编译时异常处理
由于编译时异常是在编译时期不得不处理的,提醒作用很强烈。所以这里我们先讲编译时异常的三种处理方式。
2.3.1 throws抛出异常
实例:
这里throws抛出的异常都为Exception的子类,如ParseException等,因此直接抛出Excepetion。
public static void main(String[] args) throws Exception {
System.out.println("程序开始----------");
praseTime("2011-11-11 11:11:11");
System.out.println("程序结束。。。。。。");
}
public static void praseTime(String date) throws Exception {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d=sdf.parse(date); //1.解析异常
System.out.println(d);
InputStream is=new FileInputStream("E:/meinv.jpg");//2.输入异常(我根本没有E盘)
2.3.2 try-catch 监视捕获异常
实例:
public static void main(String[] args) {
System.out.println("程序开始---------");
praseTime("2011-11-11 11:11:11");
System.out.println("程序结束。。。。。。");
}
public static void praseTime(String date) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d = sdf.parse(date); //1.解析异常
System.out.println(d);
InputStream is = new FileInputStream("E:/meinv.jpg");
} catch (Exception e) { //2.输入异常(我根本没有E盘)
e.printStackTrace();
}
}
补充:打印异常栈信息
这里打印的上面那个实例里的异常栈信息。由于我省略了一些东西,所以行数不对应。
2.3.3 throws与try-catch结合
实例:
public static void main(String[] args) {
System.out.println("程序开始--------");
try {
praseTime("2011-11-11 11:11:11");
System.out.println("功能操作成功~~~~~~~");
} catch (Exception e) {
e.printStackTrace(); //打印异常栈信息
System.out.println("功能操作失败!!!!!!!");
}
System.out.println("程序结束。。。。。。");
}
public static void praseTime(String date) throws Exception {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d=sdf.parse(date); //1.解析异常
System.out.println(d);
InputStream is=new FileInputStream("E:/meinv.jpg");
//2.输入异常(我根本没有E盘)
}
小结:编译时异常处理
2.4 运行时异常处理
2.5 自定义异常
自定义编译异常:直接继承Exception。编译时异常在编译阶段就报错,提醒强烈!!!
自定义运行异常:继承RuntimeException。运行时异常只在运行阶段报错,提醒不强烈。
可以根据需求来定义不同的异常。以下是自定义编译异常实例:
public static void main(String[] args) throws PeopleAgeIlleglException
try {
checkAge(-36);
} catch (PeopleAgeIlleglException e) {
e.printStackTrace();
}
}
public static void checkAge(int age) throws PeopleAgeIlleglException {
if(age <0 | age >150){
throw new PeopleAgeIlleglException(age+" is illegal!");
}else{
System.out.println("年龄合法~~~");
}
}
class PeopleAgeIlleglException extends Exception{
public PeopleAgeIlleglException() {
}
public PeopleAgeIlleglException(String message) { //重写构造器
super(message);
}
}
补充:throw与throws
throw与throws抛出去一个异常对象给调用者:
throw:在方法内部直接创建一个异常对象,并由此点抛出。
throws:用在方法声明上的,抛出方法内部的异常。