代码编织梦想

JavaSE(B站黑马)学习笔记

01Java入门
02数组、方法
03面向对象&Java语法
04-1Java高级(Stream流、异常处理、日志技术)



前言

JavaSE(B站黑马)学习笔记 04-1Java高级(Stream流、异常处理、日志技术)


04-1Java高级(Stream流、异常处理、日志技术)

Stream流

Stream流的概述

什么是Stream流?

  • 在Java 8中,得益于Lambda所带来的函数式编程, 引入了一个全新的Stream流概念。
  • 目的:用于简化集合和数组操作的API。
image1.png

案例
image2.png

未使用Stream流实现
image3.png

使用Stream流实现
image4.png

Stream流的思想
image5.png
image6.png

Stream流的获取

Stream操作集合或者数组的第一步是先得到Stream流,然后才能使用流的功能。

Stream流的三类方法

  • 获取Stream流

    • 创建一条流水线,并把数据放到流水线上准备进行操作
  • 中间方法

    • 流水线上的操作。一次操作完毕之后,还可以继续进行其他操作。()
  • 终结方法

    • 一个Stream流只能有一个终结方法,是流水线上的最后一个操作

集合获取Stream流的方式

  • 可以使用Collection接口中的默认方法stream()生成流
image7.png

数组获取Stream流的方式
image8.png
image9.png

Stream流的常用API

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

Stream map(Function<? super T, ? extends R> mapper);map加工方法:第一个参数是原材料 -> 第二个参数是加工后的结果
Optional max(Comparator<? super T> comparator)制定大小规则返回最大值,返回一个Optional对象,可用其对象的get方法获取这个值

注意:

  • 中间方法也称为非终结方法,调用完成后返回新的Stream流可以继续使用,支持链式编程。
  • 在Stream流中无法直接修改集合、数组中的数据。

Stream流的常见终结操作方法
image11.png

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

“流只能使用一次”,只要有一个方法没有再返回Stream流就终止了,就像水没有拿水管一节一节接着就没了

终结和非终结方法的含义是什么?

  • 终结方法后流不可以继续使用,非终结方法会返回新的流,支持链式编程。

image12.pngimage13.png
image14.png

Stream流的综合应用(案例)

image15.png

image16.pngimage17.png
image18.png
image19.png

1、筛选最高工资员工信息,封装成优秀员工对象Topperformer思路:

用流的max方法制定大小规则返回最大值,再用map加工方法封装成Topperformer对象后使用get方法返回Topperformer对象

2、去掉最高工资和最低工资后统计平均工资思路:

先用流的sorted方法对其进行升序排序,然后用skip方法跳过第一个的最低工资,再用limit方法获取除去最后一个最高工资和第一个最低工资后的其它元素(skip跳过了第一个元素,但是one.size的长度还是4,因为Stream流中无法直接修改集合、数组中的数据。除去skip跳过的就是取前两个了)得到去掉最高工资和最低工资后其它人的工资,最后用lambda表达式遍历其余工资相加的总和。

细节:

Lambda表达式是简化匿名内部类的写法,{ }内其实是个方法,而这个方法是属于匿名内部类的,有自己独立的栈,如果把allMoney变量定义到main方法里就属于另一个方法栈内,不同栈里是不能互相访问变量的。所以定义一个静态变量让其进行共享访问。

3、统计2个开发部门整体去掉最低和最高工资的平均工资思路:

获取两个部门的流,将两个流合并再用 2 的思路求平均工资。

细节:因为是两个部门进行计算,所以要把相应位置换成两个部门的总和。还有为了避免浮点类型计算的精度问题,要使用BigDecimal对其进行处理

收集Stream流

Stream流的收集操作

  • 收集Stream流的含义:就是把Stream流操作后的结果数据转回到集合或者数组中去。
  • Stream流:方便操作集合/数组的手段。
  • 集合/数组:才是开发中的目的。

Stream流的收集方法API
image20.png

Object[] toArray();返回成数组,返回类型为Object(因为怕里面类型不统一)
A[] toArray(IntFunction<A[]> generator);返回成数组,指定返回类型

JDK16开始支持直接流转换成不可变集合,可以不用提供收集方式

Collectors工具类提供了具体的收集方式
image21.png
image22.png

返回成数组,指定返回类型原理:

从s3流里知道元素有4个,传给匿名内部类的方法内的value,然后方法返回对应类型和长度的数组,最后遍历流里的元素赋给自定义的数组(一般返回Object数组就行)

异常处理

异常概述、体系

什么是异常?

  • 异常是程序在“编译”或者“执行”的过程中可能出现的问题,注意:语法错误不算在异常体系中。
  • 比如:数组索引越界、空指针异常、 日期格式化异常,等…

为什么要学习异常?

  • 异常一旦出现了,如果没有提前处理,程序就会退出JVM虚拟机而终止.
  • 研究异常并且避免异常,然后提前处理异常,体现的是程序的安全, 健壮性。
image23.png

异常体系
image24.png

Error:

  • 系统级别问题、JVM退出等,代码无法控制。

Exception: java.lang包下,称为异常类,它表示程序本身可以处理的问题

  • RuntimeException及其子类:运行时异常,编译阶段不会报错。 (空指针异常,数组索引越界异常)
  • 除RuntimeException之外所有的异常:编译时异常(写代码的时候),编译期必须处理的,否则程序不能通过编译。 (日期格式化异常)。

编译时异常和运行时异常
image25.png

常见运行时异常

运行时异常

  • 直接继承自RuntimeException或者其子类,编译阶段不会报错,运行时可能出现的错误。

运行时异常示例

  • 数组索引越界异常: ArrayIndexOutOfBoundsException
  • 空指针异常 : NullPointerException,直接输出没有问题,但是调用空指针的变量的功能就会报错。
  • 数学操作异常:ArithmeticException
  • 类型转换异常:ClassCastException
  • 数字转换异常: NumberFormatException
image26.png

运行时异常:一般是程序员业务没有考虑好或者是编程逻辑不严谨引起的程序错误,自己的水平有问题!

image27.png

常见编译时异常

编译时异常

  • 不是RuntimeException或者其子类的异常,编译阶就报错,必须处理,否则代码不通过。
  • 简单来说,编译时异常起到提醒作用,就是调用者在此处容易出错,比如传入参数错误,Java就在打代码时(编译时)就直接弹出错误提醒你,这里容易出错必须抛出异常或者try{}catch{}捕获处理异常(下面讲抛出异常和try{}catch{}捕获处理异常)

编译时异常示例
image28.png
image29.png

处理办法:光标位于异常处,按快捷键 Alt + 回车。会弹出两种解决办法,一种直接抛,一种try{}catch{}(后面解释,这里选择直接抛)

image30.png

编译时异常的作用是什么:

  • 是担心程序员的技术不行,在编译阶段就爆出一个错误, 目的在于提醒不要出错!
  • 编译时异常是可遇不可求。遇到了就遇到了呗。

异常的默认处理流程

  1. 默认会在出现异常的代码那里自动的创建一个异常对象:ArithmeticException。
  2. 异常会从方法中出现的点这里抛出给调用者,调用者最终抛出给JVM虚拟机。
  3. 虚拟机接收到异常对象后,先在控制台直接输出异常栈信息数据。
  4. 直接从当前执行的异常点干掉当前程序。
  5. 后续代码没有机会执行了,因为程序已经死亡。
image31.png

默认的异常处理机制并不好,一旦真的出现异常,程序立即死亡!

编译时异常的处理机制

编译时异常是编译阶段就出错的,所以必须处理,否则代码根本无法通过

编译时异常的处理形式有三种:

  • 出现异常直接抛出去给调用者,调用者也继续抛出去。
  • 出现异常自己捕获处理,不麻烦别人。
  • 前两者结合,出现异常直接抛出去给调用者,调用者捕获处理。

异常处理方式1 —— throws

  • throws:用在方法上,可以将方法内部出现的异常抛出去给本方法的调用者处理。
  • 这种方式并不好,发生异常的方法自己不处理异常,如果异常最终抛出去给虚拟机将引起程序死亡。(跟默认方式没啥区别,只是让程序在编译阶段通过,不出bug还好,一出就全死)

简单来说,就是一层一层往上抛,除非有谁处理,否则最后谁也不处理直接挂掉

抛出异常格式:
image32.png

规范做法:
image33.png

  • 代表可以抛出一切异常

一层一层往上抛,谁接到谁异常,最后抛给虚拟机将引起程序死亡。
image34.png

一个方法内部可能有很多异常要抛出,要一一抛出,谁先出现异常抛出谁
image35.png

如果需要抛的异常特别多,可以直接抛Exception,效果一样的
image36.png

快捷键: Alt + 回车。会弹出两种解决办法,选择第一个
image37.png

异常处理方式2 —— try…catch…

  • 监视捕获异常,用在方法内部,可以将方法内部出现的异常直接捕获处理。
  • 这种方式还可以,发生异常的方法自己独立完成异常的处理,程序可以继续往下执行。
image38.png

将可能出现异常的地方用try{}捕获,在catch{}进行处理。这样就能让程序继续运行不会直接死亡
image39.png

可以只用一个try{}捕获异常,然后使用Exception处理所有异常或者分开处理,因为开发中在中间出现异常就没必要往下走了,下面可能要使用上面的数据,所以整体处理。
image40.png
image41.png

异常处理方式3 —— 前两者结合

  • 方法直接将异常通过throws抛出去给调用者
  • 调用者收到异常后直接捕获处理。
image42.png

异常处理的总结

  • 在开发中按照规范来说第三种方式是最好的:底层的异常抛出去给最外层,最外层集中捕获处理。
  • 实际应用中,只要代码能够编译通过,并且功能能完成,那么每一种异常处理方式似乎也都是可以的。(人和代码有一个能跑就行)

运行时异常的处理机制

运行时异常的处理形式

  • 运行时异常编译阶段不会出错,是运行时才可能出错的,所以编译阶段不处理也可以。
  • 按照规范建议还是处理:建议在最外层调用处集中捕获处理即可。

image43.pngimage44.png

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

image45.png

理想状态下,用户只输入负数会一直循环,输入正数结束。但如果用户不老实,乱输入 如:abc21,程序就直接崩了。
image46.png
image47.png

虽然可以使用正则表达式判断输入或者用if else进行判断,但这里主要体验异常处理的强大

使用异常处理后,就算用户一顿乱输,都能被异常捕获重新进入循环,然后还乱输入的话继续捕获异常进行处理。
image48.png

自定义异常

自定义异常的必要?

  • Java无法为这个世界上全部的问题提供异常类。
  • 如果企业想通过异常的方式来管理自己的某个业务问题,就需要自定义异常类了。

自定义异常的好处:

  • 可以使用异常的机制管理业务问题,如提醒程序员注意。
  • 同时一旦出现bug,可以用异常的形式清晰的指出出错的地方。

自定义异常的分类

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

真实项目可能写成千上万行代码,使用异常就能够被记录下来快速定位哪里出现了异常,不然得一行一行找
image49.png
image50.png
image51.png

自定义编译异常就是在方法内部创建一个异常对象(此对象就是自定义编译异常),并从此点抛出,再向上抛,当其他人调用此方法时就直接报错,提醒它 意思是:请注意,这里容易出现年龄非法异常。然后调用者必须抛出异常或者try{}catch{}捕获处理异常

上面调用Java的日期格式异常的源码也是这样的原理,一调用就报错,目的就是提醒调用者,传入的参数容易出错,然后必须抛出一个ParseException异常或者try{}catch{}捕获处理异常
image52.png

  • 自定义运行时异常

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

认为不是很严重的错误,很少见,或者不用特别强烈的提醒就可以定义成运行时异常
image53.png
image54.png

日志技术

日志是什么

  • 希望系统能记住某些数据是被谁操作的,比如被谁删除了?
  • 想分析用户浏览系统的具体情况,以便挖掘用户的具体喜好?
  • 当系统在开发或者上线后出现了bug,崩溃了,该通过什么去分析、定位bug?
image55.png
  • 用来记录程序运行过程中的信息,并可以进行永久存储。好比生活中的日记,可以记录你生活的点点滴滴。
image56.png

日志技术应该具备哪些特点和优势

  • 可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)。
  • 可以随时以开关的形式控制是日志的记录和取消,无需侵入到源代码中去进行修改。
image57.png

打印语句写在代码里,拖慢程序运行时时间,日志技术是独立出来的

日志技术体系、Logback概述

日志体系结构
image58.png

  • 日志接口:一些规范,提供给日志的实现框架设计的标准。
  • 日志框架牛人或者第三方公司已经做好的实现代码,后来者直接可以拿去使用。
  • 注意:因为对Commons Logging接口不满意,有人就搞了SLF4J。因为对Log4j的性能不满意,有人就搞了Logback,Logback是基于slf4j的日志规范实现的框架。

常见的日志实现框架

  • Log4j
  • Logback(重点学习的,其它都大同小异)

Logback日志框架

  • Logback是由log4j创始人设计的另一个开源日志组件,性能比log4j要好
  • 官方网站:https://logback.qos.ch/index.html
  • Logback是基于slf4j的日志规范实现的框架

Logback日志框架分为以下模块:

  • logback-core: 该模块为其他两个模块提供基础代码。 (必须有
  • logback-classic:完整实现了slf4j API的模块。 (必须有
  • logback-access 模块与 Tomcat 和 Jetty 等 Servlet 容器集成,以提供 HTTP 访问日志功能(可选模块,以后接触

想使用Logback日志框架,至少需要在项目中整合如下三个模块:
image59.png

下载(配套资料有,下面介绍在哪可以下载)

方式一:

可到上方官网下载:打开官网,找到Download,点击Maven central,找到对应文件 点进去 选择相应版本即可(没找到slf4j-api)
image60.png
image61.png

方式二:

在maven中央仓库下载,官网:https://mvnrepository.com/ 搜索slf4j,点击进入,选择版本号下载,一般选择使用最多的。(logback-classic和logback-core也可以在这下载)
image62.png
image63.png
image64.png
image65.png

Logback快速入门

image66.png
  1. 导入logback框架到项目中去。在项目下新建文件夹lib(一般命名都为lib),导入Logback的jar包到该文件夹下
    image67.png

  2. 将存放jar文件的lib文件夹添加到项目依赖库中去。
    image68.png

  3. 将Logback的核心配置文件logback.xml直接拷贝到src目录下(必须是src下)。

logback.xml文件在官网(https://logback.qos.ch/manual/configuration.html),往下翻找到这段代码,在项目中新建logback.xml文件复制进去。(官网只是基础的,别人已经配好了更详细的配置直接拿来用即可——在配套资料里)
image69.png
image70.png

  1. 创建Logback框架提供的Logger日志对象,后续使用其方法记录系统的日志信息。
    image71.png
    image72.png

成功打印到控制台和输出日志文件
image73.png
image74.png

Logback配置详解

输出位置、格式设置

对Logback日志框架的控制,都是通过核心配置文件logback.xml来实现的。

Logback日志输出位置、格式设置:

  • 通过logback.xml 中的标签可以设置输出位置。
  • 通常可以设置2个日志输出位置:一个是控制台、一个是系统文件中

输出到控制台的配置标志
image75.png

输出到系统文件的配置标志
image76.png

找到对应的位置改就行了
image77.png
image78.png

日志级别设置

1、如果系统上线后想关闭日志,或者只想记录一些错误的日志信息,怎么办?

  • 可以通过设置日志的输出级别来控制哪些日志信息输出或者不输出。

日志级别

  • ALL 和 OFF分别是打开、及关闭全部日志信息。
  • 除此之外,日志级别还有: TRACE < DEBUG < INFO < WARN < ERROR ; 默认级别是DEBUG,对应其方法
  • 作用:当在logback.xml文件中设置了某种日志级别后,系统将只输出当前级别,以及高于当前级别的日志。

image79.pngimage80.png
image81.png


注:

该内容是根据B站黑马程序员学习时所记,相关资料可在B站查询:Java入门基础视频教程,java零基础自学就选黑马程序员Java入门教程(含Java项目和Java真题)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_48074431/article/details/129629647

java开发技术面试考点--javase部分-爱代码爱编程

一、JavaSE部分 ❤1、Java基础 1、为什么重写equals还要重写hashcode (1)两个对象相等,hashCode则一定相等;(2)hashCode相等,两个对象不一定相等;为了提高程序的效率,先进行ha

Java学习日志(十六): Stream流详解,Stream流综合案例-爱代码爱编程

JavaEE学习日志持续更新----> 必看!JavaEE学习路线(文章总汇) Java学习日志(十六) Stream引言流式模型获取Stream流的方式常用方法foreach:遍历filter:过滤count:统计limit:获取skip:跳过map:映射concat(静态方法):组合收集Stream结果Stream流转化为集合Strea

Java学习日志(十九): 字符输出流,字符输入流-爱代码爱编程

JavaEE学习日志持续更新----> 必看!JavaEE学习路线(文章总汇) Java学习日志(十九) 字符流ReaderFileReaderWriterFileWriter 字符流 字节流读取中文时,由于一次只能读写一个字节,一次不能把整个中文字符读全(UTF-8:1个中文=3个字节,GBK:1个中文=2个字节),会出现乱码,所以

JavaSE 进阶 - 第23章 IO流-爱代码爱编程

JavaSE 进阶 - 第23章 IO流 1、IO流,什么是IO?2、IO流的分类3、流应该怎样学习?4、java IO流的四大家族5、java.io包下需要掌握的16个流5.1 FileInputStream的使用(重点)5.2 FileOutputStream的使用(重点)5.3 文件复制1(字节流型)5.4 FileReader5.5 Fil

JavaSE学习总结---IO流-爱代码爱编程

概述 有的流按照字节的方式读取数据,一次读取一个字节byte,等同于一次读取8个二进制,万能的,什么文件都能读。比如 文件file1.txt,采用字节流是这样读的 a中国ba张三ddd 第一次读‘a’(虽然“a”在windows中占用一个字节) 第二次读‘中’的一半(虽然‘中’在windows中占用两个字节) 有的流是按照字符的方式读取数据,一次读一

JAVASE学习笔记-2-爱代码爱编程

流与文件 JAVA流概述 流根据方向可以分为:输入流和输出流。 注意:输入和输出是相对内存而言的,从内存出来就是输出,到内存中就是输入,输入流又叫做InputStream,输出流又叫做OutputStream;输入还叫做“读Read”,输出还叫做“写Write”.流根据读取数据的方式可以分为:字节流和字符流。 字节流是按照字节的方式读取,字符流是按

Java Stream流、 IO学习笔记-爱代码爱编程

6、Stream流 6.1 Stream流的概述 对于ArrayList来说有时候的需求直接使用list的API会很麻烦,而Stream流可以简化其需求 1、数组获取流的方式 int[] arr = {1,2,3} Stream<Integer> stream1 = Stream.of(1,2,3); Stream stream3 =

JavaSE进阶09:Stream流、File类-爱代码爱编程

系列文章目录 JavaSE进阶01:继承、修饰符JavaSE进阶02:多态、抽象类、接口JavaSE进阶03:内部类、Lambda表达式JavaSE进阶04:API中常用工具类JavaSE进阶05:包装类、递归、数组的高级操作、异常JavaSE进阶06:Collection集合、迭代器、List、ArrayList、LinkedListJavaSE进阶0

【0基础学java】教学日志:javaSE--Stream API-爱代码爱编程

本章概述:本章主要讲了Stream特性,Stream运行机制,Stream的创建,Stream常用API,以及Stream API在实际应用开发中的作用 目录 本章概述: 一、annotation 1、AnnotationDemo  2、FunctionInterfaceDemo  3、MetaAnnotation  4、Test1 二、l

javase进阶、stream流、异常处理和日志框架_飞翔的企鹅i的博客-爱代码爱编程

目录 一、Stream流 1、Stream流概述 2、stream流的思想 3、Stream流的三类方法 获取Stream流方法 中间方法 终结方法  4、Stream流的综合案例 5、收集Stream流  二、异常处理 1、异常概念  2、异常体系  常见运行时异常  常见编译时异常 3、异常的默认处理流程   4、编译时

javase学习路线以及学习建议_codecatpro的博客-爱代码爱编程

JavaSE基础学习路线 1.Java环境搭建、IDEA、Java语言 2.Java语法、运算符、随机数 3.分支、循环、控制关键字 4.数组详解、案例训练 5.方法详解、案例训练 6.面试常见编程案例题训练 7.面向对象基

javase基础笔记——不可变集合简介、stream流体系、异常处理_小曹爱编程!的博客-爱代码爱编程

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

【0基础学java】教学日志:javase-爱代码爱编程

本章概述:本章主要讲了BufferedWriter类,BufferedReader类,BufferedWriterDemo类的使用,以及从万维网上摘取百度网页的操作 目录 本章概述: 一、BufferedWriter的使用 1、BufferedWriterDemo 二、BufferedReader类 1、BufferedReaderDemo

javase学习笔记-爱代码爱编程

文章目录 序JavaSe零散点字符串多态时间类+格式化时间Date类SimpleDateFormat类Calendar类 正则表达式字符类预定义字符贪婪量词 Lambda表达式泛型迭代器Fo

javase进阶27 -爱代码爱编程

数据流 DataOutputStream package com.bjpowernode.javase.io; import java.io.DataOutputStream; import java.io.FileN

从零开始学java【javase-爱代码爱编程

文章目录 一、 面向对象1. final关键字2. 抽象类3. 接口(1)接口的基础语法。(2)接口的作用。类型和类型的区别: 4. 抽象类与接口的区别5. Object类5.1 **toSt