JavaSE进阶(day07,复习自用)

本文介绍了Java中如何创建和使用不可变集合,包括List、Set和Map的of方法。接着讲解了Stream流的基本概念、获取、中间方法和终结方法,展示了如何简化集合操作。此外,文章还详细讨论了异常处理机制,包括编译时异常和运行时异常的处理方式,以及自定义异常的原因和好处。

创建不可变集合

什么是不可变集合?
不可变集合,就是不可被修改的集合。
集合的数据项在创建的时候提供,并且在整个生命周期中都不可改变。否则报错。
为什么要创建不可变集合?
如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践。或者当集合对象被不可信的库调用时,不可变形式是安全的。
在这里插入图片描述

//目标:不可变集合
public class CollectionDemo {
    public static void main(String[] args) {

        //1.不可变的List集合
        List<Double> lists = List.of(569.5,700.5,523.0,570.5);
        //lists.add(689.0);//报错
        double score = lists.get(1);
        //lists.set(2,698.5);//报错
        System.out.println(lists);
        System.out.println(score);

        //2.不可变的Set集合
        Set<String> names = Set.of("迪丽热巴","迪丽热九","马尔扎哈","卡尔扎巴");
        //names.add("三少爷");//报错
        System.out.println(names);

        //3.不可变的Map集合
        Map<String,Integer> maps = Map.of("huawei",2,"Java开发",1,"手表",1);
        //maps.put("衣服",3);//报错

        System.out.println(maps);

    }
}

不可变集合的特点?
定义完成后不可以修改,或者添加、删除
如何创建不可变集合?
List、Set、Map接口中,都存在of方法可以创建不可变集合。

Stream流

Stream流的概述

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

//初步体验Stream流的方便与快捷
public class StreamTest {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        Collections.addAll(names,"张三丰","张无忌","周芷若","赵敏","张强");
        System.out.println(names);

//        //1.从集合中找出姓张的放到新集合
//        List<String> zhangList = new ArrayList<>();
//        for (String name : names) {
//            if(name.startsWith("张")){
//                zhangList.add(name);
//            }
//        }
//        System.out.println(zhangList);
//
//        //2.找名称长度是3的姓名
//        List<String> zhangThreeList = new ArrayList<>();
//        for (String name : zhangList) {
//            if(name.length()==3){
//                zhangThreeList.add(name);
//            }
//        }
//        System.out.println(zhangThreeList);

        //3.使用Stream实现的
        names.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(s -> System.out.println(s));



    }
}

Stream流的获取

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

/**
 目标:Stream流的获取

 Stream流式思想的核心:
 是先得到集合或者数组的Stream流(就是一根传送带)
 然后就用这个Stream流操作集合或者数组的元素。
 然后用Stream流简化替代集合操作的API.

 集合获取流的API:
 (1) default Stream<E> stream();

 小结:
 集合获取Stream流用: stream();
 数组:Arrays.stream(数组)   /  Stream.of(数组);
 */
public class StreamDemo02 {
    public static void main(String[] args) {
        /** --------------------Collection集合获取流-------------------------------   */
        Collection<String> list = new ArrayList<>();
        Stream<String> s =  list.stream();

        /** --------------------Map集合获取流-------------------------------   */
        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();

        /** ---------------------数组获取流------------------------------   */
        String[] names = {"赵敏","小昭","灭绝","周芷若"};
        Stream<String> nameStream = Arrays.stream(names);
        Stream<String> nameStream2 = Stream.of(names);

    }
}

Stream流的常用方法

中间方法

在这里插入图片描述

public class StreamDemo03 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        list.add("张三丰");

        list.stream().filter(s->s.startsWith("张")).forEach(s-> System.out.println(s));

        long size = list.stream().filter(s->s.length() == 3).count();
        System.out.println(size);

        //list.stream().filter(s->s.startsWith("张")).limit(2).forEach(s-> System.out.println(s));
        list.stream().filter(s->s.startsWith("张")).limit(2).forEach(System.out::println);//方法引用

        /**
         * System.out::println
         * 当对传入参数进行打印时,可以直接用方法引用
         */

        list.stream().filter(s->s.startsWith("张")).skip(2).forEach(System.out::println);//方法引用

        //Map加工方法
        //给集合元素的前面都加上一个 黑马的:
//        list.stream().map(new Function<String, String>() {
//            @Override
//            public String apply(String s) {
//                return "黑马的:" + s;
//            }
//        }).forEach(System.out::println);

        //简化后的代码:
        list.stream().map(s->"黑马的"+s).forEach(System.out::println);

        //需求:把所有的名称 都加工成一个学生对象。
//      list.stream().map(s->new Student(s)).forEach(s-> System.out.println(s));
        //简化之后的代码
        list.stream().map(Student::new).forEach(System.out::println);//构造器引用 方法引用

        //合并流
        Stream<String> s1 = list.stream().filter(s->s.startsWith("张"));
        Stream<String> s2 = Stream.of("Java1","Java2");
        Stream<String> s3 = Stream.concat(s1,s2);
        //s3.forEach(System.out::println);

        //去重复
        System.out.println("---------去重复------------");
        s3.distinct().forEach(System.out::println);
        
    }
}

终结方法

在这里插入图片描述
终结和非终结方法的含义是什么?
终结方法后流不可以继续使用,非终结方法会返回新的流,支持链式编程。

Stream流的综合应用

在这里插入图片描述

public class Employee {
    private String name;
    private char sex;
    private double salary;
    private double bonus;
    private String punish; // 处罚信息

    public Employee(){
    }

    public Employee(String name, char sex, double salary, double bonus, String punish) {
        this.name = name;
        this.sex = sex;
        this.salary = salary;
        this.bonus = bonus;
        this.punish = punish;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public double getBonus() {
        return bonus;
    }

    public void setBonus(double bonus) {
        this.bonus = bonus;
    }

    public String getPunish() {
        return punish;
    }

    public void setPunish(String punish) {
        this.punish = punish;
    }

    public double getTotalSalay(){
        return salary * 12 + bonus;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", sex=" + sex +
                ", salary=" + salary +
                ", bonus=" + bonus +
                ", punish='" + punish + '\'' +
                '}'+"\n";
    }
}

public class Topperformer {
    private String name;
    private double money;//月薪

    public Topperformer() {
    }

    public Topperformer(String name, double money) {
        this.name = name;
        this.money = money;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Topperformer{" +
                "name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

public class StreamDemo04 {
    public static double allMoney;
    public static double allMoney2;//2个部门去掉最高工资,最低工资
    public static void main(String[] args) {


        List<Employee> one = new ArrayList<>();
        one.add(new Employee("猪八戒",'男',30000 , 25000, null));
        one.add(new Employee("孙悟空",'男',25000 , 1000, "顶撞上司"));
        one.add(new Employee("沙僧",'男',20000 , 20000, null));
        one.add(new Employee("小白龙",'男',20000 , 25000, null));

        List<Employee> two = new ArrayList<>();
        two.add(new Employee("武松",'男',15000 , 9000, null));
        two.add(new Employee("李逵",'男',20000 , 10000, null));
        two.add(new Employee("西门庆",'男',50000 , 100000, "被打"));
        two.add(new Employee("潘金莲",'女',3500 , 1000, "被打"));
        two.add(new Employee("武大郎",'女',20000 , 0, "下毒"));

        //1.开发一部的最高工资的员工
        //制定大小规则
//        Employee e = one.stream().max((e1,e2)->Double.compare(e1.getSalary()+e1.getBonus(),e2.getSalary()+ e2.getBonus())).get();
//        System.out.println(e);
        Topperformer t = one.stream().max((e1,e2)->Double.compare(e1.getSalary()+e1.getBonus(),e2.getSalary()+ e2.getBonus()))
                .map(e ->new Topperformer(e.getName(),e.getSalary()+e.getBonus())).get();
        System.out.println(t);

        //2.统计平均工资,去掉最高工资和最低工资
        one.stream().sorted((e1,e2)->Double.compare(e1.getSalary()+e1.getBonus(),e2.getSalary()+ e2.getBonus()))
                .skip(1).limit(one.size()-2).forEach(e->{
                    allMoney += (e.getSalary()+e.getBonus());
        });

        System.out.println("开发一部的平均工资是:" + allMoney / (one.size() - 2));

        //3.合并2个集合之,再统计
        Stream<Employee> s1 = one.stream();
        Stream<Employee> s2 = two.stream();
        Stream<Employee> s3 = Stream.concat(s1,s2);
        s3.sorted((e1,e2)->Double.compare(e1.getSalary()+e1.getBonus(),e2.getSalary()+ e2.getBonus()))
                .skip(1).limit(one.size()+ two.size()-2).forEach(e->{
            allMoney2 += (e.getSalary()+e.getBonus());
        });

        //BigDecimal
        BigDecimal a = BigDecimal.valueOf(allMoney2);
        BigDecimal b = BigDecimal.valueOf(one.size()+ two.size() - 2);

        System.out.println("开发部门的平均工资是:" +  a.divide(b,2,RoundingMode.HALF_UP));

    }
}

收集Stream流

收集Stream流的含义:就是把Stream流操作后的结果数据转回到集合或者数组中去。

Stream流:方便操作集合/数组的手段
集合/数组:才是开发中的目的
在这里插入图片描述

/**
 目标:收集Stream流的数据到集合和数组中去
 */
public class StreamDemo05 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        list.add("张三丰");


        //下面是自己写的方法
//        List<String> zhanglist1 = new ArrayList<>();
//        list.forEach(l->{
//            if(l.startsWith("张")){
//                zhanglist1.add(l);
//            }
//        });
//        System.out.println(zhanglist1);

        Stream<String> s1  = list.stream().filter(s->s.startsWith("张"));
        List<String> zhanglist = s1.collect(Collectors.toList());
        zhanglist.add("Java1");
        System.out.println(zhanglist);
//        //新版本支持的方法
//        List<String> list1 = s1.toList();//但得到的是不可变集合
//        //list1.add("Java");//会报错
//        System.out.println(list1);


        //注意注意注意 :流只能使用一次
        Stream<String> s2  = list.stream().filter(s->s.startsWith("张"));
        Set<String> zhangSet = s2.collect(Collectors.toSet());
        System.out.println(zhangSet);
        
        Stream<String> s3  = list.stream().filter(s->s.startsWith("张"));
        Object[] arrs = s3.toArray();//第一种方法

        //另一种方法
//        String[] arrs = s3.toArray(new IntFunction<String[]>() {
//            @Override
//            public String[] apply(int value) {
//                return new String[value];
//            }
//        });
        //简化之后
        //String[] arrs = s3.toArray(s->new String[s]);
        //进一步简化
        //String[] arrs = s3.toArray(String[]::new);
        
        System.out.println("Arrays数组内容:" + Arrays.toString(arrs));
        
    }
}

异常处理

异常概述、体系

异常是程序在“编译”或者“执行”的过程中可能出现的问题,注意:语法错误不算在异常体系中。
比如:数组索引越界、空指针异常、 日期格式化异常,等…
异常一旦出现了,如果没有提前处理,程序就会退出JVM虚拟机而终止.
研究异常并且避免异常,然后提前处理异常,体现的是程序的安全, 健壮性。
在这里插入图片描述
异常分为几类?
编译时异常、运行时异常。
编译时异常:没有继承RuntimeExcpetion的异常,编译阶段就会出错。
运行时异常:继承自RuntimeException的异常或其子类,编译阶段不报错,运行可能报错
在这里插入图片描述

常见运行时异常

在这里插入图片描述

public class ExceptionDemo {
    public static void main(String[] args) {
        /** 1.数组索引越界异常: ArrayIndexOutOfBoundsException。*/
        int[] arr = {1,2,3};
        System.out.println(arr[2]);
//        System.out.println(arr[3]);//运行出错,程序终止


        /** 2.空指针异常 : NullPointerException。直接输出没有问题。但是调用空指针的变量的功能就会报错!! */
        String name = null;
        System.out.println(name);//null
//        System.out.println(name.length());//运行出错,程序终止

        /** 3.类型转换异常:ClassCastException。 */
        Object o = 23;
//        String s = (String)o;
//        System.out.println(s);//运行出错,程序终止


        /** 5.数学操作异常:ArithmeticException。 */
//        int c = 10/0;//运行出错,程序终止


        /** 6.数字转换异常: NumberFormatException。 */
//        String number = "23";//写这个不报错
        String number = "23aabbcc";
//        Integer it = Integer.valueOf(number);//运行出错,程序终止
//        System.out.println(it + 1);


    }
}

常见编译时异常

在这里插入图片描述

异常的默认处理流程

在这里插入图片描述

编译时异常的处理机制

在这里插入图片描述

方式1-throws

在这里插入图片描述

/**
 目标:编译时异常的处理方式一。

 编译时异常:编译阶段就会报错,一定需要程序员处理的,否则代码无法通过!!

 抛出异常格式:
 方法 throws 异常1 ,  异常2 , ..{

 }
 建议抛出异常的方式:代表可以抛出一切异常,
 方法 throws Exception{

 }

 方式一:
 在出现编译时异常的地方层层把异常抛出去给调用者,调用者最终抛出给JVM虚拟机。
 JVM虚拟机输出异常信息,直接干掉程序,这种方式与默认方式是一样的。
 虽然可以解决代码编译时的错误,但是一旦运行时真的出现异常,程序还是会立即死亡!
 这种方式并不好!

 小结:
 方式一出现异常层层跑出给虚拟机,最终程序如果真的出现异常,程序还是立即死亡!这种方式不好!

 */
public class ExceptionDemo01 {
//    public static void main(String[] args) throws ParseException, FileNotFoundException {
//        System.out.println("程序开始。。。。。");
//        parseTime("2011-11-11 11:11:11");
//        System.out.println("程序结束。。。。。");
//    }
//
//    public static void parseTime(String date) throws ParseException, FileNotFoundException {
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss");
//        Date d = sdf.parse(date);
//        System.out.println(d);
//
//        InputStream is = new FileInputStream("E://meinv.jpg");
//    }

    public static void main(String[] args) throws Exception {
        System.out.println("程序开始。。。。。");
        parseTime("2011-11-11 11:11:11");
        System.out.println("程序结束。。。。。");
    }

    public static void parseTime(String date) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = sdf.parse(date);
        System.out.println(d);

        InputStream is = new FileInputStream("E://meinv.jpg");
    }
}

方式2 try…catch…

在这里插入图片描述

public class ExceptionDemo02 {

    public static void main(String[] args) {
        System.out.println("程序开始。。。。。");
        parseTime("2011-11-11 11:11:11");
        System.out.println("程序结束。。。。。");
    }
//      第一种方式:分开判断异常类型(形式一)
//    public static void parseTime(String date) {
//        try {
//            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            Date d = sdf.parse(date);
//            System.out.println(d);
//        } catch (ParseException e) {
//            //解析出现问题
//            System.out.println("出现了解析时间异常哦,走点心!!");
//        }
//
//        try {
//            InputStream is = new FileInputStream("E://meinv.jpg");
//        } catch (FileNotFoundException e) {
//            System.out.println("目录下无该文件!");
//        }
//    }

    //形式二:
//    public static void parseTime(String date) {
//        try {
//            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            Date d = sdf.parse(date);
//            System.out.println(d);
//            InputStream is = new FileInputStream("E://meinv.jpg");
//        } catch (ParseException e) {
//            e.printStackTrace();//打印异常栈信息
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        }
//    }

    //形式三:
    public static void parseTime(String date) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date d = sdf.parse(date);
            System.out.println(d);
            InputStream is = new FileInputStream("E://meinv.jpg");
        } catch (Exception e) {//此处Exception可以改成ParseException|FileNotFoundException
            e.printStackTrace();//打印异常栈信息
        }
    }
}

方式3 前两者结合

在这里插入图片描述

public class ExceptionDemo03 {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。。");
        try {
            parseTime("2011-11-11 11:11:11");
            System.out.println("功能操作成功~~~");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("功能操作失败~~~");
        }
        System.out.println("程序结束。。。。。");
    }

    public static void parseTime(String date) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = sdf.parse(date);
        System.out.println(d);

        InputStream is = new FileInputStream("E://meinv.jpg");
    }
}

运行时异常的处理机制

在这里插入图片描述

/**
 * 目标:运行时异常的处理机制
 * 可以不处理,编译阶段又不报错
 * 按照理论规则:建议还是处理,只需要最外层捕获处理即可
 */
public class Test {
    public static void main(String[] args) {
        System.out.println("程序开始。。。");
        try {
            chu(10,0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("程序结束。。。");
    }

    public static void chu(int a,int b){//默认是有 throws RuntimeException
        System.out.println(a);
        System.out.println(b);
        int c = a/b;
        System.out.println(c);
    }
}

异常处理使代码更稳健的案例

在这里插入图片描述

/**
 * 需求:需要输入一个合法的价格未知,需求价格大于0
 */
public class Test2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(true){
            try {
                System.out.println("请您输入合法的价格:");
                String priceStr = sc.nextLine();
                //转换成Double类型的价格
                double price = Double.valueOf(priceStr);

                //判断价格是否大于0
                if(price > 0){
                    System.out.println("定价:" + price);
                    break;
                }else{
                    System.out.println("价格必须是正数~~");
                }
            } catch (Exception e) {
                System.out.println("说明用户输入的数据有毛病,请您输入合法的数值,建议为正数~~");
            }
        }
    }
}

自定义异常

原因和好处

Java无法为这个世界上全部的问题提供异常类。
如果企业想通过异常的方式来管理自己的某个业务问题,就需要自定义异常类
自定义异常的好处:
可以使用异常的机制管理业务问题,如提醒程序员注意。
同时一旦出现bug,可以用异常的形式清晰的指出出错的地方。

分类

1、自定义编译时异常
定义一个异常类继承Exception.
重写构造器。
在出现异常的地方用throw new 自定义对象抛出,
作用:编译时异常是编译阶段就报错,提醒更加强烈,一定需要处理!!

/**
 * 自定义的编译时异常
 * 1.继承Exception
 * 2.重写构造器
 *
 */
public class ItheimaAgeIllegalException extends Exception{
    public ItheimaAgeIllegalException() {

    }

    public ItheimaAgeIllegalException(String message) {
        super(message);
    }
}

2、自定义运行时异常
定义一个异常类继承RuntimeException.
重写构造器。
在出现异常的地方用throw new 自定义对象抛出!
作用:提醒不强烈,编译阶段不报错!!运行时才可能出现!!

/**
 * 自定义的编译时异常
 * 1.继承RuntimeException
 * 2.重写构造器
 *
 */
public class ItheimaAgeIllegalRuntimeException extends RuntimeException{
    public ItheimaAgeIllegalRuntimeException() {

    }

    public ItheimaAgeIllegalRuntimeException(String message) {
        super(message);
    }
}
/**
 目标:自定义异常(了解)

 引入:Java已经为开发中可能出现的异常都设计了一个类来代表.
 但是实际开发中,异常可能有无数种情况,Java无法为
 这个世界上所有的异常都定义一个代表类。
 假如一个企业如果想为自己认为的某种业务问题定义成一个异常
 就需要自己来自定义异常类.

 需求:认为年龄小于0岁,大于200岁就是一个异常。

 自定义异常:
 自定义编译时异常.
 a.定义一个异常类继承Exception.
 b.重写构造器。
 c.在出现异常的地方用throw new 自定义对象抛出!
 编译时异常是编译阶段就报错,提醒更加强烈,一定需要处理!!

 自定义运行时异常.
 a.定义一个异常类继承RuntimeException.
 b.重写构造器。
 c.在出现异常的地方用throw new 自定义对象抛出!
 提醒不强烈,编译阶段不报错!!运行时才可能出现!!

 */
public class ExceptionDemo {
    public static void main(String[] args) {
//        try {
//            checkAge2(-34);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        try {
            checkAge2(-23);
        } catch (ItheimaAgeIllegalRuntimeException e) {
            e.printStackTrace();
        }

    }

//    public static void checkAge(int age) throws ItheimaAgeIllegalException {
//        if(age < 0 || age > 200){
//            //抛出去一个异常对象给调用者
//            //throw:在方法内部直接创建一个异常对象,并从此抛出
//            //throws:用在方法声明上,抛出方法内部的异常
//            throw new ItheimaAgeIllegalException(age + " is llegal!");
//        }else{
//            System.out.println("年龄合法:推荐商品给其购买~~");
//        }
//    }

    //运行时异常
    public static void checkAge2(int age) throws ItheimaAgeIllegalRuntimeException {
        if(age < 0 || age > 200){
            //抛出去一个异常对象给调用者
            //throw:在方法内部直接创建一个异常对象,并从此抛出
            //throws:用在方法声明上,抛出方法内部的异常
            throw new ItheimaAgeIllegalRuntimeException(age + " is llegal!");
        }else{
            System.out.println("年龄合法:推荐商品给其购买~~");
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值