Stream流,异常体系

1.Stream流:

          Stream流的概述:

  Stream流指的是流式编程,用于简化集合和数组的操作。结合了lambda表达式。

          Stream流式思想的核心:

                1.先得到集合或者数组的Steam流。(传送带)

                2.然后用Stream流提供的方法对流中的数据进行操作。(加工的环节)

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

        //Stream流式编程,可以简化集合的操作,得到开头为张,字符串长度为3的新数组并遍历。
        list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(s-> System.out.println(s));
    }
}

          Stream流的获取:

只有单列集合才有获取Stream流的方法,双列集合必须转换为单列集合才能获取Stream流。

public class Demo2 {
    public static void main(String[] args) {
        //1.通过List、Set集合获取流
        //ArrayList<String> list = new ArrayList<>();
        HashSet<String> list = new HashSet<>();
        Collections.addAll(list, "张三丰","张无忌","张良","谢广坤","小龙女","尹志平");

        /**
         * default Stream<E> steam();获取当前集合对象的Stream流。
         */
        //调用stream()方法获取流, 并遍历输出元素
      list.stream().forEach(s -> System.out.println(s));
        System.out.println("-----------------");

        //2.通过Map集合获取流(Map集合不能直接获取流)
        HashMap<String,String> map = new HashMap<>();
        map.put("王宝强", "马蓉");
        map.put("贾乃亮", "李小璐");
        //2.1获取map的键集,再获取流
        map.keySet().stream().forEach(s -> System.out.println(s));
        //2.2获取map的值集,再获取流
        map.values().stream().forEach(s -> System.out.println(s));
        //2.3获取map键值对的集合,再获取流
        map.entrySet().stream().forEach(s-> System.out.println(s.getKey()+"..."+s.getValue()));
        System.out.println("--------------------------------------------------");

        //3.通过数组、元素获取流,需要传入的是引用数据类型,如果传入基本数据类型,返回的只是地址值。
        /**
         * public static<T> Stream<T> of(T... values):获取当前数组/可变数据的Stream流。
         */
        Integer[] arr = {10,20,30,40,50};
        Stream.of(arr).forEach(s-> System.out.println(s));

        int[] arr1= {10,20,34,40};
        Stream.of(arr1).forEach(s-> System.out.println(s));

        int[] arr2= {10,20,34,40};
        Arrays.stream(arr2).forEach(s-> System.out.println(s));
    }
}

          Stream流的常用API:

1.Stream流的常用API(中间操作方法)

        注意:

                1.中间方法也称为非终结方法,调用完成后返回新的Stream流可以继续使用,支持链式编程。

                2.在Stream流中无法直接修改集合,数组的数据。  

     

public class Demo3 {
    public static void main(String[] args) {
        List<String> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
        Collections.addAll(list1, "杨过","小龙女","周伯通","欧阳锋","尹志平","金轮法王");
        Collections.addAll(list2, "孙二娘","武松","武大郎","西门庆","潘金莲","潘金莲","张青");

        //1.concat(Stream a,Stream b)把a,b两个流合并为一个流
        Stream<String> stream = Stream.concat(list1.stream(), list2.stream());

        //2.filter(Predicate<? super T> predicate)用于对流中的数据进行过滤
        stream.filter(s->s.length()>=3).forEach(s-> System.out.println(s));
        System.out.println("------------------------------");

        //3.limit(long maxSize)获取前几个元素。
        Stream.concat(list1.stream(),list2.stream()).limit(10).forEach(s-> System.out.println(s));
        System.out.println("------------------------------");

        //4.skip(long n)跳过前面几个元素。
        Stream.concat(list1.stream(),list2.stream()).skip(3).forEach(s-> System.out.println(s));
        System.out.println("------------------------------");

        //5.distinct()去除流中重复的元素,依赖(hashCode和equals方法)
        list2.stream().distinct().forEach(s-> System.out.println(s));
        System.out.println("------------------------------");

        //由于filter、limit、skip等这些方法都是中间操作方法,返回值也是一个流,所以支持链式编程(流式编程)
        //"欧阳锋","尹志平","金轮法王","孙二娘","武大郎","西门庆","潘金莲"
        Stream.concat(list1.stream(),list2.stream())
                .filter(s->s.length()>=3)
                .limit(10)
                .skip(2)
                .distinct()
                .forEach(s-> System.out.println(s));
    }
}

2.Stream流的常用终结操作方法

        注意:

                终结操作方法,调用完成后流就无法继续使用了,原因是不会返回Stream了。

public class Demo4 {
    public static void main(String[] args) {
        List<String> list1 = new ArrayList<>();
        Collections.addAll(list1, "杨过","小龙女","周伯通","欧阳锋","尹志平","金轮法王");


        //1.forEach(Consumer action)对此流的每个元素执行遍历操作。
        list1.stream().filter(s -> s.length()==3).forEach(s-> System.out.println(s));
        System.out.println("-----------------------------------");

        //2.long count()返回此流中的元素数。
        long count = list1.stream().filter(s -> s.length() == 3).count();
        System.out.println(count);
    }
}

          Stream流的综合应用:

public class Demo5 {
    public static void main(String[] args) {
        ArrayList<Empolyee> list1 = new ArrayList<>();
        list1.add(new Empolyee("孙悟空","石",20000,5000,"大闹天宫"));
        list1.add(new Empolyee("沙和尚","男",15000,3000,"打碎琉璃盏"));
        list1.add(new Empolyee("猪八戒","公",13000,2000,"调戏嫦娥"));
        list1.add(new Empolyee("白龙马","公",14000,6000,"杀了鲤鱼精"));
        ArrayList<Empolyee> list2 = new ArrayList<>();
        list2.add(new Empolyee("西门庆","男",30000,-5000,"被武松打死"));
        list2.add(new Empolyee("潘金莲","女",2000,300,"被武松打死"));
        list2.add(new Empolyee("武大郎","男",5000,3000,"吃药"));
        list2.add(new Empolyee("武松","男",25000,10000,"发配沧州"));
        //分别获取两个部门的Stream流
        //Stream<Empolyee> stream1 = list1.stream();
        //Stream<Empolyee> stream2 = list2.stream();

        //2.分别将流中的元素从Employee对象转换为员工的实际收入
        Stream<Double> moneyStream1 = list1.stream().map(s -> s.getMoney());
        moneyStream1.forEach(s-> System.out.println(s));

        list2.stream().map(s -> s.getMoney()).forEach(s -> System.out.println(s));

        //3.分别求两个部门的平均月收入
        //mapToDouble(lambda表达式): 把流中的元素转换为double类型,返回值是DoubleStream
        //average():求DoubleStream中元素的平均值,返回值OptionalDouble
        //getAsDouble(): 获取到OptionalDouble里面封装的double值
        double avg1 = list1.stream().mapToDouble(s -> s.getMoney()).average().getAsDouble();
        double avg2 = list2.stream().mapToDouble(s -> s.getMoney()).average().getAsDouble();
        System.out.println("开发一部的平均收入是:"+avg1);
        System.out.println("开发二部的平均收入是:"+avg2);
        System.out.println("--------------------");

        //4.分别筛选出两个部门的最高收入的员工信息
        //max(比较器):求流中元素的最大值,返回值是Optional对象(它是有一个封装有元素的包装类)
        //get(): 获取Optional包装类中封装的元素对象
        Empolyee max1 = list1.stream().max((o1, o2) -> Double.compare(o1.getMoney(), o2.getMoney())).get();
        Empolyee max2 = list2.stream().max((o1, o2) -> Double.compare(o1.getMoney(), o2.getMoney())).get();
        System.out.println("开发一部收入最高的员工信息:"+max1);
        System.out.println("开发二收入最高的员工信息:"+max2);
        System.out.println("--------------------");

        //5.分别对两个部门的员工按照实际收入进行排序
        list1.stream().sorted((o1, o2) -> Double.compare(o1.getMoney(), o2.getMoney())).forEach(s-> System.out.println(s));
        list2.stream().sorted((o1, o2) -> Double.compare(o1.getMoney(), o2.getMoney())).forEach(s-> System.out.println(s));
        
        //6.统计2个开发部门整体的平均月收入,要求去掉最高收入和最低收入。
        double avg = Stream.concat(list1.stream(), list2.stream())
                .sorted((o1, o2) -> Double.compare(o1.getMoney(), o2.getMoney()))
                .limit(list1.size() + list2.size() - 1)
                .skip(1)
                .mapToDouble(s -> s.getMoney())
                .average()
                .getAsDouble();
        System.out.println("两个部门的整体平均月收入:"+avg);
    }
}

           收集Stream流:

/**
 * Stream流的收集方法:
 *   collect(Collector collector):开始搜集Stream流,指定收集器。
 *      public static <T> Collector toList():   把元素收集到List集合中。
 *      public static <T> Collector toSet():    把元素收集到Set集合中。
 *      public static Collector toMap(Function KeyMapper,Function valueMapper):把元素收集到Map集合中。
 */
public class Demo6 {
    public static void main(String[] args) {
        ArrayList<Empolyee> list1 = new ArrayList<>();
        list1.add(new Empolyee("孙悟空","石",20000,5000,"大闹天宫"));
        list1.add(new Empolyee("沙和尚","男",15000,3000,"打碎琉璃盏"));
        list1.add(new Empolyee("猪八戒","公",13000,2000,"调戏嫦娥"));
        list1.add(new Empolyee("白龙马","公",14000,6000,"杀了鲤鱼精"));

        List<Empolyee> list = list1.stream().filter(s -> s.getSalary() >= 14000).collect(Collectors.toList());
        System.out.println(list);

        Set<Empolyee> set = list1.stream().filter(s -> s.getSalary() >= 14000).collect(Collectors.toSet());
        System.out.println(set);

        Map<String, Integer> map = list1.stream().filter(s -> s.getSalary() >= 14000).collect(Collectors.toMap(s -> s.getName(), s -> s.getSalary()));
        System.out.println(map);

        Object[] arr1 = list1.stream().filter(s -> s.getSalary() >= 14000).toArray();
        for (Object o : arr1) {
            System.out.println(o);
        }
        Empolyee[] arr2 = list1.stream().filter(s -> s.getSalary() >= 14000).toArray(value -> new Empolyee[value]);
        for (Empolyee empolyee : arr2) {
            System.out.println(empolyee);
        }
    }
}

 2.异常:

异常是程序在编译或者执行的过程中可能出现的问题。Java语言的设计者们为了让开发者知道,异常产生的原因,把这些异常设计成了类。   

            

         目的:

  • 避免异常的出现
  • 提前处理可能出现的异常,让代码更稳健。

        常见运行时异常:

public class Demo2 {
    public static void main(String[] args) {
        //1.ArrayIndexOutOfBoundsException: 数组索引越界
//        int[] arr1=new int[3];
//        System.out.println(arr1[arr1.length]);

        //2.StringIndexOutOfBoundsException: 字符串索引越界
//        String str="aaa";
//        System.out.println(str.charAt(str.length()));

        //3.IndexOutOfBoundsException:  集合的索引越界
//        List<String> list=new ArrayList();
//        System.out.println(list.get(list.size()));

        //4.NullPointerException: 空指针异常
//        int[] arr4=null;
//        System.out.println(arr4.length);

        //5.ClassCastException: 类型转换异常
//        List<String> list=new ArrayList<>();
//        LinkedList<String> list1=(LinkedList<String>) list;


        //6.NumberFormatException: 数字格式异常
//       int num=Integer.parseInt("ass");

        //7.ArithmeticException: 数学操作异常
//        int a=23/0;

        //8.IllegalArgumentException: 非法参数异常
//        Random ran=new Random();
//        int num=ran.nextInt(0);
    }
}

                 编译时异常:

不管代码是否真的有问题,在编译阶段就会报错,目的是提醒程序员不要出错。

        特点:继承自Exception的异常或者其子类。

                必须处理,否则代码不通过。

 

 

异常如何产生:

                在写一个方法时,考虑到调用者可能传递非法数据,需要对调用者传递过来的数据进行合法性的校验,如何数据校验不合法就通过throw new 产生一个异常对象,并抛给调用者,让调用者知道为什么错了。

 

                

 

注意:

  1. 如果方法中产生的是运行时异常,不需要在方法上声明。
  2. 如果方法中产生的是编译时异常,需要在方法上用throws声明。
public class Demo4 {
    public static void main(String[] args) throws Exception {
        test(0);
    }

    public static void test(int num) throws Exception {
        if (num<1||num>100){
            throw new Exception("参数有问题啊!");
        }
        System.out.println("正常执行");
    }
}

 遇到异常该如何处理

/**
遇到异常如何处理:
   方案1: try...catch捕获异常格式
          try{
             有可能产生异常的代码
          }catch(Exception e){
             如果try里面产生了异常,异常对象会赋值给这里变量e
             在这里可以处理异常
          }
          特点:处理异常之后,程序还可以继续执行

    方案2: throws 在方法上声明异常,把异常交给下一个调用者,由调用者处理
        public void 方法名() throws 异常类{
            有异常产生的代码
        }
 */
public class Demo5 {
    public static void main(String[] args) {
        while (true) {
            try {
                Scanner sc = new Scanner(System.in);
                int num = sc.nextInt();
                System.out.println("你录入的数据是:"+num);
                break;
            } catch (Exception e) {
                //e.printStackTrace(); //打印异常信息
                System.out.println("你录入的数据格式不对,请重新录入");
            }
        }

        System.out.println("over");

        System.out.println("---------------");

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        Date date = null;
        try {
            date = sdf.parse("2008-08-08");
        } catch (ParseException e) {
            //e.printStackTrace();
            System.out.println("你解析的日期字符串格式不对");
        }
        System.out.println(date);
    }
}

注意:

  • 如果遇到的是运行时异常,一般不需要处理,直接改代码就行。如果改代码解决不了,也能使用try...catch处理。
  • 如果遇到编译时异常,可以使用try...catch捕获异常,也可以继续使用throws声明,抛给下一个调用者处理。

自定义异常类:

  1. 如果Java的API中提供的异常类,不足以描述你的问题;那么你就可以自定义异常类。
  2. 只需要让自定义类继承Exception或者RuntimeException即可。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值