学习日记(Stream 流、异常处理案例、日志框架)

学习日记(Stream 流、异常处理案例、日志框架)

一、Stream 流

1. 概述

在 Java 8 中,得益于 Lambda 表达式所带来的函数式编程,引入了一个全新的 Stream 流概念。

目的:用于简化集合数组操作的 API。

核心思想:先得到集合或数组的 Stream 流(就是一跟传送带)—> 把元素放上去 —> 然后用 Stream 流简化的 API 来方便地操作元素。

需求:输出同学中姓”王“并且名字为三个字的同学。

2. 获取 Stream 流

获取 Stream 流是用 Stream 流操作集合或数组的第一步,获取 Stream 流的 API 如下。

集合或数组方法名说明
Collection 或 Map 集合default Stream stream()集合获取 Stream 流
数组public static Stream stream(T[] array)数组获取 Stream 流的方法一(Arrays 类的方法)
数组public static Stream of(T… values)数组获取 Stream 流的方法二(Stream 的方法)

注意:数组获取 Stream 流的方法二其实和方法一相同,但是方法一的参数必须是数组,而方法二的参数是可变参数(可以直接传入元素也可以传入数组)。

3. 常用 API

中间操作的方法(非终结方法)说明
Stream filter(Predicate<? super T> predicate)对流中的数据进行过滤(筛选)
Stream limit(long maxSize)提取前几个元素
Stream skip(long n)跳过前几个元素
Stream map(Function<? super T, ? extends R> mapper)对流中的数据进行加工
Stream distinct()除流中重复的元素,依赖 hashCode 和 equals 方法
public static Stream concat(Stream<? extends T> a, Stream<? extends T> b)合并 a 流和 b 流为一个流,此时 a 流和 b 流会关闭
终结操作方法说明
long count()返回此流中的元素数,返回值类型为 long
void forEach(Consumer<? super T> action)对此流中的每个元素进行遍历

注意

  • 中间方法也称为非终结方法,调用完成之后会返回新的 Stream 流,可以继续使用,支持链式编程
  • 终结方法调用后,流就无法继续使用了,原因是不会返回 Stream 了。
  • 在 Stream 流中无法直接修改原集合或原数组的数据。
  • 在合并流(concat)时,只能同时合并两个流,并且合并之后,原先两个流会关闭。
  • 流只能使用一次!

示例

运行结果

4. 综合应用

需求:给定 5 个员工信息,包括姓名、性别、工资信息,要求

  • 筛选出最高工资的员工信息,封装成优秀员工对象(Topperformer);
  • 统计出所有员工的平均工资,要求去掉最高和最低工资。
用到流的方法说明
Optional max(Comparator<? super T> comparator)自定义比较规则,先排序,然后剩最大值的对象
public T get()从流中取对象
Stream sorted(Comparator<? super T> comparator)自定义比较规则,排序

运行结果

package com.residue.stream;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class StreamDemo04 {

    /*
    需求:给定 5 个员工信息,包括姓名、性别、工资信息,要求:
        - 筛选出最高工资的员工信息,封装成优秀员工对象(Topperformer);
        - 统计出所有员工的平均工资,要求去掉最高和最低工资。
     */

    public static double sumSalary = 0;

    public static void main(String[] args) {

        Employee e1 = new Employee("张一", '男', 17008.89);
        Employee e2 = new Employee("刘二", '女', 27005.12);
        Employee e3 = new Employee("李三", '男', 19210.95);
        Employee e4 = new Employee("赵四", '女', 18312.24);
        Employee e5 = new Employee("孙五", '男', 25629.71);

        List<Employee> list1 = new ArrayList<>();
        Collections.addAll(list1, e1, e2, e3, e4, e5);
        System.out.println(list1);
        System.out.println("===========================================");

        //需求一:筛选出最高工资的员工信息,封装成优秀员工对象(Topperformer)。
        Topperformer topperformer = list1.stream().
                max((o1, o2) -> Double.compare(o1.getSalary(), o2.getSalary())).
                map(s -> new Topperformer(s.getName(), s.getSex(), "Top")).
                get();

        System.out.println(topperformer);
        System.out.println("===========================================");


        //需求二:统计出所有员工的平均工资,要求去掉最高和最低工资。
        list1.stream().sorted((o1, o2) -> Double.compare(o1.getSalary(), o2.getSalary())).
                skip(1).limit(list1.size() - 2).
                forEach(s -> {
            sumSalary += s.getSalary();
        });

        BigDecimal sumSalary1 = BigDecimal.valueOf(sumSalary);
        BigDecimal num = BigDecimal.valueOf(list1.size() - 2);

        BigDecimal result = sumSalary1.divide(num, 2, RoundingMode.HALF_UP);

        double average = result.doubleValue();

        System.out.println("员工的平均工资为(去掉最低和最高):" + average);

    }
}

5. 收集 Stream 流

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

注意:Stream 流是方便操作集合或数组的手段,而集合或数组才是目的

方法

  • 把流 stream1 中的元素收集到 List 集合中:List<Integer> collectList = stream1.collect(Collectors.toList());

  • 把流 stream2 中的元素收集到 Set 集合中: Set<Integer> collectSet = stream2.collect(Collectors.toSet());

  • 把流 stream3 中的元素收集到数组中,注意返回值类型为 Object 数组Object[] collectArray = stream3.toArray();

  • 把流 stream4 中的元素收集到数组中,注意返回值类型为 Integer 数组Integer[] collectArray1 = stream3.toArray(s -> new Integer[s]);


二、异常处理案例

需求:键盘录入价格,直到价格的格式正确:必须为数字,必须大于 0。

写法一:直接把输入不是数字和输入数字为负数的情况排除。

写法二:用异常处理


三、日志框架

1. 概述

程序中的日志可以用来记录程序运行过程中的信息,并可以进行永久存储

输出语句与日志技术对比:

输出语句日志技术
输出位置只能是控制台可以将日志信息选择性地记录到控制台文件或者数据库
取消日志需要修改代码,灵活性较差可以随时以开关的形式控制是否记录日志,不需要修改代码,灵活性比较好
多线程性能较差性能较好

2. 日志技术体系

日志规范指一些接口,提供给日志的实现框架设计的标准。(相当于接口

日志规范接口有:Commons Logging(简称:JCL)和 Simle Logging Facade for Java(简称:slf4j)。

日志实现框架指已经做好的日志记录实现代码,可以直接拿来使用。(相当于实现类

日志实现框架有:Log4JJULLogback 等等。

3. Logback 日志框架

官网点此进入):https://logback.qos.ch/index.html

Logback 日志框架有三个模块:logback-core、logback-classic 和 logback-access。

  • logback-core:必须有,为其他两个模块奠定了基础;
  • logback-classic:是 Log4J 的一个改良版本,完整地实现了 Log4J API。
  • logback-access:与Tomcat 和 Jetty 等 Servlet 容器集成,以提供 HTTP 访问日志功能。

Logback 日志框架的后续内容由于部分原因以后再学吧!


注意:

  1. Lambda 表达式在 Stream 流的作用!

  1. 在合并流(concat)时,只能同时合并两个流,并且合并之后,原先两个流会关闭

  1. 在使用终结方法后,流会关闭,不能再调用方法。

  1. Java 中局部内部类和匿名内部类访问的局部变量必须由 final 修饰。

  1. 流只能使用一次!

  1. 一个 haxNextInt 应该对应一个 nextInt,这样可以使得后面重新输入,也可以只有 nextInt。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sun 3285

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值