day24-java(改)

异常

异常概述

package com.itheima.exception;

/**
    目标:异常的概念和体系。

    什么是异常?
         异常是程序在"编译"或者"执行"的过程中可能出现的问题。
         异常是应该尽量提前避免的。
         异常可能也是无法做到绝对避免的,异常可能有太多情况了,开发中只能提前干预!!
         异常一旦出现了,如果没有提前处理,程序就会退出JVM虚拟机而终止,开发中异常是需要提前处理的。

         研究异常并且避免异常,然后提前处理异常,体现的是程序的安全, 健壮性!!!
         Java会为常见的代码异常都设计一个类来代表。

    异常的体系:
         Java中异常继承的根类是:Throwable。

             Throwable(根类,不是异常类)
          /              \
         Error           Exception(异常,需要研究和处理)
                        /            \
                       编译时异常      RuntimeException(运行时异常)

         Error : 错误的意思,严重错误Error,无法通过处理的错误,一旦出现,程序员无能为力了,
            只能重启系统,优化项目。
            比如内存奔溃,JVM本身的奔溃。这个程序员无需理会。

         Exception:才是异常类,它才是开发中代码在编译或者执行的过程中可能出现的错误,
            它是需要提前处理的。以便程序更健壮!

    Exception异常的分类:
         1.编译时异常:继承自Exception的异常或者其子类,编译阶段就会报错,
                必须程序员处理的。否则代码编译就不能通过!!

         2.运行时异常: 继承自RuntimeException的异常或者其子类,编译阶段是不会出错的,它是在
                运行时阶段可能出现,运行时异常可以处理也可以不处理,编译阶段是不会出错的,
                但是运行阶段可能出现,还是建议提前处理!!
    小结:
        异常是程序在编译或者运行的过程中可能出现的错误!!
        异常分为2类:编译时异常,运行时异常。
            -- 编译时异常:继承了Exception,编译阶段就报错,必须处理,否则代码不通过。
            -- 运行时异常:继承了RuntimeException,编译阶段不会报错,运行时才可能出现。
        异常一旦真的出现,程序会终止,所以要研究异常,避免异常,处理异常,程序更健壮!!
 */
public class ExceptionDemo01 {
    public static void main(String[] args) {
        int[] arr = {10, 20, 40};
        System.out.println(arr[0]);
        System.out.println(arr[1]);
        System.out.println(arr[2]);
        System.out.println(arr[3]);
        System.out.println("-----------程序截止---------");
    }
}

常见运行时异常

package com.itheima.exception;
/**
    拓展: 常见的运行时异常。(面试题)
         运行时异常的概念:
             继承自RuntimeException的异常或者其子类,
             编译阶段是不会出错的,它是在运行时阶段可能出现的错误,
             运行时异常编译阶段可以处理也可以不处理,代码编译都能通过!!

             1.数组索引越界异常: ArrayIndexOutOfBoundsException。
             2.空指针异常 : NullPointerException。
               直接输出没有问题。但是调用空指针的变量的功能就会报错!!
             3.类型转换异常:ClassCastException。
             4.迭代器遍历没有此元素异常:NoSuchElementException。
             5.数学操作异常:ArithmeticException。
             6.数字转换异常: NumberFormatException。

    小结:
        运行时异常继承了RuntimeException ,编译阶段不报错,运行时才可能会出现错误!
 */
public class ExceptionDemo02 {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。。。");
        /** 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;  // 运行出错,程序终止

        /** 5.数学操作异常:ArithmeticException。 */
        //int c = 10 / 0;

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

        System.out.println("程序结束。。。。。");
    }
}

编译时异常

package com.itheima.exception;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
    目标:常见的编译时异常认识。

    编译时异常:继承自Exception的异常或者其子类,没有继承RuntimeException
         "编译时异常是编译阶段就会报错",
         必须程序员编译阶段就处理的。否则代码编译就报错!!

    编译时异常的作用是什么:
         是担心程序员的技术不行,在编译阶段就爆出一个错误, 目的在于提醒!
         提醒程序员这里很可能出错,请检查并注意不要出bug。
         编译时异常是可遇不可求。遇到了就遇到了呗。

    了解: 
 */
public class ExceptionDemo03 {
    public static void main(String[] args) throws ParseException {
        String date = "2015-01-12 10:23:21";
        // 创建一个简单日期格式化类:
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM-dd HH:mm:ss");
        // 解析字符串时间成为日期对象
        Date d = sdf.parse(date);
        //
        System.out.println(d);
    }
}

异常默认处理

package com.itheima.exception;
/**
     目标:异常的产生默认的处理过程解析。(自动处理的过程!)
    (1)默认会在出现异常的代码那里自动的创建一个异常对象:ArithmeticException。
    (2)异常会从方法中出现的点这里抛出给调用者,调用者最终抛出给JVM虚拟机。
    (3)虚拟机接收到异常对象后,先在控制台直接输出异常栈信息数据。
    (4)直接从当前执行的异常点干掉当前程序。
    (5)后续代码没有机会执行了,因为程序已经死亡。

    小结:
         异常一旦出现,会自动创建异常对象,最终抛出给虚拟机,虚拟机
         只要收到异常,就直接输出异常信息,干掉程序!!

         默认的异常处理机制并不好,一旦真的出现异常,程序立即死亡!
 */
public class ExceptionDemo04 {
    public static void main(String[] args) {
        System.out.println("程序开始。。。。。。。。。。");
        chu(10, 0);
        System.out.println("程序结束。。。。。。。。。。");
    }

    public static void chu(int a , int b){
        System.out.println(a);
        System.out.println(b);
        int c = a / b;
        System.out.println(c);
    }
}

编译时异常处理方式一

package com.itheima.exception.exceptionhandle;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

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

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

    抛出异常格式:
        方法 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");
    }

}

编译时异常处理方式二

package com.itheima.exception.exceptionhandle;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

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

    方式二:在出现异常的地方自己处理,谁出现谁处理。

    自己捕获异常和处理异常的格式:捕获处理
         try{
            // 监视可能出现异常的代码!
         }catch(异常类型1 变量){
            // 处理异常
         }catch(异常类型2 变量){
            // 处理异常
         }...

    监视捕获处理异常企业级写法:
         try{
             // 可能出现异常的代码!
         }catch (Exception e){
            e.printStackTrace(); // 直接打印异常栈信息
         }
         Exception可以捕获处理一切异常类型!

    小结:
        第二种方式,可以处理异常,并且出现异常后代码也不会死亡。
        这种方案还是可以的。
        但是从理论上来说,这种方式不是最好的,上层调用者不能直接知道底层的执行情况!

 */
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);

            InputStream is = new FileInputStream("E:/meinv.jpg");
        } catch (Exception 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 (FileNotFoundException|ParseException 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 (FileNotFoundException e) {
//           e.printStackTrace(); // 打印异常栈信息
//        } catch (ParseException 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);
//        } catch (ParseException e) {
//            // 解析出现问题
//            System.out.println("出现了解析时间异常哦,走点心!!");
//        }
//
//        try {
//            InputStream is = new FileInputStream("E:/meinv.jpg");
//        } catch (FileNotFoundException e) {
//            System.out.println("您的文件根本就没有啊,不要骗我哦!!");
//        }
//    }
}

编译时异常处理方式三

package com.itheima.exception.exceptionhandle;

import java.io.FileInputStream;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

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

    方式三: 在出现异常的地方把异常一层一层的抛出给最外层调用者,
            最外层调用者集中捕获处理!!(规范做法)

    小结:
        编译时异常的处理方式三:底层出现的异常抛出给最外层调用者集中捕获处理。
        这种方案最外层调用者可以知道底层执行的情况,同时程序在出现异常后也不会立即死亡,这是
        理论上最好的方案。

        虽然异常有三种处理方式,但是开发中只要能解决你的问题,每种方式都又可能用到!!
 */
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("D:/meinv.jpg");
    }

}

运行时异常处理机制

package com.itheima.exception.runtimeexception;
/**
 目标:运行时异常的处理机制。

 可以不处理,编译阶段又不报错。
 按照理论规则:建议还是处理,只需要在最外层捕获处理即可
 */
public class Test1 {
    public static void main(String[] args) {
        System.out.println("程序开始");
        try {
            chu(1,0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("程序结束");
    }
    public static void chu(int a,int b){
        System.out.println(a/b);
    }
}

运行时异常案例

package com.itheima.exception.runtimeexception;

import java.util.Scanner;

/**
 需求:需要输入一个合法的价格为止 要求价格大于 0
 */
public class Test2 {
    public static void main(String[] args) {
        System.out.println("程序开始");
        Scanner sc = new Scanner(System.in);
        while (true){
            try {
                System.out.println("请输入价格:");
                //这里使用nextDouble方法接收会因为用户输入字符串导致无法接收成功而造成死循环
                double v = Double.valueOf(sc.nextLine());
                if (v>0){
                    System.out.println("价格合法");
                    break;
                }else {
                    System.out.println("价格必须为正数");
                }
            } catch (Exception e) {
                System.out.println("价格不合法");
            }
        }
        System.out.println("程序结束");
    }
}

自定义异常

package com.itheima.exception.customexception;

import com.itheima.exception.customexception.domain.ageIllegalException;
import com.itheima.exception.customexception.domain.ageIllegalRuntimeException;

/**
 目标:自定义异常(了解)

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

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

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

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

 */
public class Demo01 {
    public static void main(String[] args) {
        System.out.println("程序开始");
        //编译时就报错,必须立刻处理
        try {
            checkAge(23);
        } catch (ageIllegalException e) {
            e.printStackTrace();
        }
        //运行时才报错,建议处理
        try {
            checkAge1(-10);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("程序结束");
    }

    /**
     * 测试方法抛出编译时异常
     * @param age
     * @throws ageIllegalException
     */
    public static void checkAge(int age) throws ageIllegalException {
        if (age<0||age >200){
            throw new ageIllegalException(age+" is illegal");
        }else {
            System.out.println("年龄合法");
        }
    }
    public static void checkAge1(int age) {
        if (age<0||age >200){
            throw new ageIllegalRuntimeException(age+" is illegal");
        }else {
            System.out.println("年龄合法");
        }
    }
}

ageIllegalException类

package com.itheima.exception.customexception.domain;
/**
 自定义的编译时异常
 1、继承Exception
 2、重写构造器
 */
public class ageIllegalException extends Exception {
    public ageIllegalException() {
    }

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

ageIllegalRuntimeException类

package com.itheima.exception.customexception.domain;
/**
 自定义的运行时异常
 1、继承RuntimeException
 2、重写构造器
 */
public class ageIllegalRuntimeException extends RuntimeException {
    public ageIllegalRuntimeException() {
    }

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

不可变集合

package com.itheima.unchangeablegather;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 不可变集合
 * List、Set、Map集合都有of()方法可用于创建不可变集合
 * 创建后集合中的元素不能再改变
 */
public class Demo01 {
    public static void main(String[] args) {
        //1.不可变List集合
        List<Integer> list = List.of(2,56,63,99);
        System.out.println(list);
//        list.add(3);//UnsupportedOperationException不支持操作异常,无法添加

        //2.不可变Set集合
//        Set<String> set = Set.of("张三","李四","王五","王五");元素重复报错
        Set<String> set = Set.of("张三","李四","王五");
        System.out.println(set);

        //3.不可变Map集合
        Map<String,String> map = Map.of("林尧","汉区","王梁","汉川","陈阳","孝区","李小航","十堰");
        System.out.println(map);
    }
}

Stream流

概述

package com.itheima.stream;

import java.util.ArrayList;
import java.util.List;

/**
 * Stream流概述
 * 相当于流水线
 * 作用:
 * 简化集合、数组操作API,结合了Lambda表达式
 * 思想步骤:
 * 先得到集合或数组的Stream流
 * 把元素放上去
 * 然后用这个Stream流简化的API操作元素
 */
public class Demo01 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张勇");
        list.add("张三丰");
        System.out.println(list);
        ArrayList<String> list1 = new ArrayList<>();
        ArrayList<String> list2 = new ArrayList<>();
        for (String s : list) {
            if ("张".equals(s.charAt(0)+"")){
                list1.add(s);
            }
            if ("张".equals(s.charAt(0)+"")&&s.length()==3){
                list2.add(s);
            }
        }
        System.out.println(list1);
        System.out.println(list2);
        System.out.println("----------------------------------------------------");

        //使用stream流,支持链式编程
        list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length()==3).forEach(System.out::println);
    }
}

集合数组获取Stream流的方式

package com.itheima.stream;

import java.util.*;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 集合、数组获取Stream流
 */
public class Demo02Stream {
    public static void main(String[] args) {
        //-----------------Collection集合获取Stream流------------------
        Collection<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();

        //-----------------Map集合获取Stream流----------------------
        Map<String,Integer> map = new HashMap<>(16);
        //获取键流
        Set<String> keys = map.keySet();
        Stream<String> stream1 = keys.stream();
        //获取值流
        Collection<Integer> values = map.values();
        Stream<Integer> stream2 = values.stream();
        //获取键值对流
        Set<Map.Entry<String,Integer>> entries = map.entrySet();
        Stream<Map.Entry<String, Integer>> stream3 = entries.stream();

        //------------------数组获取Stream流--------------
        int[] arr = {23,56,90,100};
        //方式一:
        IntStream stream4 = Arrays.stream(arr);
        //方式二:
        Stream<int[]> stream5 = Stream.of(arr);
    }
}

Stream流常用API

package com.itheima.stream;

import com.itheima.stream.domain.Student;

import java.util.ArrayList;
import java.util.stream.Stream;

/**
 * Stream流常用API
 * 中间操作方法:返回Stream流对象,可以继续操作
 * Stream<T> filter(Predicate<? super T> predicate)	用于对流中的数据进行过滤。
 * Stream<T> limit​(long maxSize)	获取前几个元素
 * Stream<T> skip​(long n)	跳过前几个元素
 * Stream<T> distinct​()	去除流中重复的元素。依赖(hashCode和equals方法)
 * static <T> Stream<T> concat​(Stream a, Stream b)	合并a和b两个流为一个流
 * map方法:加工方法
 * 终结方法:调用后Stream流就结束了
 * void forEach​(Consumer action)	对此流的每个元素执行遍历操作
 * long count​()	返回此流中的元素数
 */
public class Demo03API {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张勇");
        list.add("张三丰");
        //[张无忌, 周芷若, 赵敏, 张勇, 张三丰]
        System.out.println(list);

        //对流中的数据进行过滤并输出
        //张无忌  张勇  张三丰
        list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.print(s+"  "));
        System.out.println();

        //获取前三个元素
        //张无忌  周芷若  赵敏
        list.stream().limit(3).forEach(s -> System.out.print(s+"  "));
        System.out.println();

        //跳过前两个元素
        //赵敏  张勇  张三丰
        list.stream().skip(2).forEach(s -> System.out.print(s+"  "));
        System.out.println();

        list.add("张勇");
        System.out.println(list);
        //去除重复元素
        list.stream().distinct().forEach(System.out::println);
        //统计元素个数
        //6
        long count = list.stream().count();
        System.out.println(count);
        System.out.println("----------------------------------------------------");
        //合并Stream流
        Stream<String> poet = Stream.of("李白", "李商隐");
        Stream<String> stream = list.stream();
        Stream<String> concat = Stream.concat(stream, poet);
        concat.forEach(System.out::println);

        //给元素前都加上"黑马的"三个字
        list.stream().map(s -> "黑马的"+s).forEach(System.out::println);
        //将元素封装成学生对象
//        list.stream().map(s -> new Student(s)).forEach(student -> System.out.println(student));
        list.stream().map(Student::new).forEach(System.out::println);//构造器引用  方法引用
    }
}

案例

package com.itheima.stream;

import com.itheima.stream.domain.Employee;
import com.itheima.stream.domain.Topperformer;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/**
 * 需求:某个公司的开发部门,分为开发一部和二部,现在需要进行年中数据结算。
 * 员工信息至少包含了(名称、性别、工资、奖金、处罚记录)
 * 开发一部有4个员工、开发二部有5名员工
 * 分别筛选出2个部门的最高工资的员工信息,封装成优秀员工对象Topperformer
 * 分别统计出2个部门的平均月收入,要求去掉最高和最低工资。
 * 统计2个开发部门整体的平均工资,去掉最低和最高工资的平均值。
 */
public class Demo04Case {
    //存储开发二部总工资
    public static double sum1;
    //存储开发部总工资
    public static double sum;

    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, "下毒"));

        /*筛选出开发二部的最高工资的员工信息,封装成优秀员工对象Topperformer
        使用max方法自定义比较规则筛选出工资最高的员工,然后使用map方法将其封装为优秀员工对象
        再调用get方法取得该对象
        */
        Topperformer t = two.stream().max(((o1, o2) -> Double.compare(o1.getSalary() + o1.getBonus(), o2.getSalary() + o2.getBonus())))
                .map(employee -> new Topperformer(employee.getName(), employee.getSalary() + employee.getBonus())).get();
        System.out.println(t);

        /*
        统计出开发二部的平均月收入,要求去掉最高和最低工资。
        使用sorted方法给定排序规则进行排序,然后截取需要的员工对象
        遍历统计总工资
         */
        two.stream().sorted((o1, o2) ->Double.compare(o1.getSalary() + o1.getBonus(), o2.getSalary() + o2.getBonus()) )
                .skip(1).limit(two.size()-2).forEach(e->{
                    //此方法内无法使用main方法中的局部变量,所以应使用类静态成员变量
            sum1+=e.getSalary()+e.getBonus();
                });
        BigDecimal a = BigDecimal.valueOf(sum1);
        BigDecimal b = BigDecimal.valueOf(two.size()-2);
        System.out.println("开发二部平均工资:"+a.divide(b,2, RoundingMode.HALF_UP));

        /*
        统计2个开发部门整体的平均工资,去掉最低和最高工资的平均值。
         */
        Stream<Employee> concat = Stream.concat(one.stream(), two.stream());
        concat.sorted((o1, o2) ->Double.compare(o1.getSalary() + o1.getBonus(), o2.getSalary() + o2.getBonus()))
                .skip(1).limit(one.size()+two.size()-2).forEach(e-> sum+=e.getBonus()+e.getSalary());
        BigDecimal s = BigDecimal.valueOf(sum);
        BigDecimal len = BigDecimal.valueOf(one.size() + two.size() - 2);
        System.out.println("开发部平均工资:"+s.divide(len, 2, RoundingMode.HALF_UP));
    }
}

Employee类

package com.itheima.stream.domain;

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";
    }
}

Topperformer类

package com.itheima.stream.domain;

public class Topperformer {
    private String name;
    private double salary;

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

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

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

    public Topperformer() {
    }

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

Stream流收集

package com.itheima.stream;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Stream流收集
 * 意义:把Stream流操作后的结果数据转回到集合或者数组中去。
 * R collect​(Collector collector)	开始收集Stream流,指定收集器
 * Collectors工具类提供了具体收集方式
 * public static <T> Collector toList​()	把元素收集到List集合中
 * public static <T> Collector toSet​()	把元素收集到Set集合中
 * public static  Collector toMap​(Function keyMapper , Function valueMapper)
 * 把元素收集到Map集合中
 */
public class Demo05StreamCollect {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张勇");
        list.add("张三丰");
        //[张无忌, 周芷若, 赵敏, 张勇, 张三丰]
        System.out.println(list);

        Stream<String> s = list.stream().filter(e -> e.startsWith("张"));
        List<String> zhangList = s.collect(Collectors.toList());
        zhangList.add("张亚");
        System.out.println(zhangList);
        Stream<String> sss = list.stream().filter(e -> e.startsWith("张"));
        List<String> str = sss.toList();//得到不可变集合
        //str.add("aa");报错
        System.out.println(str);

        //注意:流只能使用一次
        Stream<String> s1 = list.stream().filter(e -> e.startsWith("张"));
//        Object[] zhangArr = s1.toArray();
        //如果非要用String类型数组接收
//        String[] zhangArr = s1.toArray(String[]::new);
        String[] zhangArr = s1.toArray(ss->new String[ss]);
        zhangArr[0] = "张三";
        System.out.println(Arrays.toString(zhangArr));

        Stream<String> s2 = list.stream().filter(e -> e.startsWith("张"));
        Set<String> c = s2.collect(Collectors.toSet());
        System.out.println(c);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值