Java leraning Note v.2
集合嵌套
在Map集合中再放List集合:
1 | package com.D2; |
存入后统计投票结果:
1 | // data = {hutao2=[B, C, D, A], hutao=[B, C, D], luoyong=[A, C]} |
不可变集合
不可修改的集合,在创建时提供数据并且在生命周期中无法修改(否则会报错),类似于静态初始化数组。
1 | List<Double> lists = List.of(569.5,525.5,700.5,522.0); |
Stream流
目的:简化集合和数组操作的API
1 | public class StreamTest { |
Stream流的关键在得到Stream流对象。
- Collection集合只需要用.stream()即可,任何集合都可通过此方法得到Stream流对象
- Map集合需要分成键流和值流
1 | Map<String, Integer> maps = new HashMap<>(); |
也可用键值对流拿整体:
1 | Stream<Map.Entry<String, Integer>> keyAndValueStream = maps.entrySet().stream(); |
- 数组
1 | String[] names = {"小明","小红"}; |
Stream常用API
1 | names.stream().filter(s -> s.startsWith("张")) |
实际上为
1 | names.stream().filter(new Predicate<String>() { |
即lambda表达式。
应用—求平均工资:
1 | package com.D3_Stream; |
收集Stream流
将Stream类型转成其他类型:List,Set
1 | package com.D3_Stream; |
注意:流只能使用一次。收集完后的流不能再次收集。
异常
常见运行时异常:
- NullPointerException空指针
- ClassCastException类型转换
- ArrayIndexOutOfBoundsException数组越界
- NumberFormatException数字转换异常
- ArithmeticException数学操作异常
常见编译异常:
日期解析异常:
1 | public class D4_Exception { |
需要改成
1 | public static void main(String[] args) **throws ParseException** { |
异常处理流程
- throw抛出异常:
谁出现谁抛出,可以有多个throw但只能有一个被抛出(抛给虚拟机后结束程序),因此可写作
1 | public void test() throws Exception{ |
- 监视异常处理(可用ctrl+alt+t生成),不会抛出异常给JVM,可在出现异常的方法内处理完
1 | try{ |
- 前两者结合
1 | public class D4_Exception { |
既可防止抛出异常到JVM导致结束程序,又可让上层获取底层的处理结果。
自定义异常
继承Exception父类必要
注:throw 与 throws区别:
throw:用于在方法内部,直接创建一个异常对象,并从此处抛出异常
throws:用于在方法声明处,抛出方法内部异常
自定义日常实例:
1 | public class ExceptionTest extends Exception{ |
1 | public class ExceptionDemo { |
运行时显示:
日志框架
实例:
1 | public class Test { |
日志输出具体设置可用logback.xml控制。
FILE类
1 | File f = new File("E:/workplace") |
注:lastModified()返回long类型,可new一个SimpleDateFormat类解析转为Date类型。
多用第二个,可直接拿到文件对象。
listFiles()注意:
调用者不存在时,返回null
调用者是文件时,返回null
调用者为空文件夹时,返回长度为0的数组
调用者为有内容的文件夹时,将所有文件和文件夹路径放在File数组中返回
递归
递归死循环会导致栈内存溢出。
例如计算阶乘:
1 | public class main { |
递归核心:
- 能描述问题的公式—f(n - 1) * n
- 递归终结点—f(1)
- 递归方式必须走向终结点
猴子吃桃问题:
1 | public class RecusionDemo { |
递归解决文件搜索
1 | import java.io.File; |
字符集
字符集编码和解码
1 | import java.util.Arrays; |
IO流
字节流可读写所有文件,字符流只能读写文本文件
1 | public class main { |
如上为文件字节输入流的读取方法,is.read()用法。
如上每次读一个字节,一来效率低,二来无法解决中文乱码
用read()方法传入字节数组,可每次读取三个字节:当无法读出时返回-1
1 | byte[] buffer = new byte[3]; |
避免中文乱码:一次读完所有字符
1 | public class FileInutStreamDemo2 { |
也可用**is.readAllBytes()**方法读取所有字节。
文件字节输出流
默认为覆盖管道,可用:
1 | OutputStream os = new FileOutputStream("/test/src/com/hit/data.txt", **true**); |
使用追加流,不覆盖原内容。
os.write()写数据只能读取字节或字节数组,因此其他类型需要用getBytes(StandardCharsets.*UTF_8*)
转成字节数组。
1 | OutputStream os = new FileOutputStream("E:/Java_IDEA/logging_test/src/data1.txt"); |
文件复制:
1 | import java.io.*; |
资源释放方式
try-catch-finally防止在资源释放前程序已退出
注:在finally中释放资源前必须要做非空校验。
finally中不能写return,因为任何return都要先执行finally。
1 | public class CopyDemo { |
JDK7简化方案:
1 | public static void main(String[] args){ |
资源释放可自动进行。
()中只能放资源对象,放置其他类型会报错。
字符流
多用于读取文本,适用于不同的编码格式
读取字符数组:
1 | public class FileReaderDemo { |
读中文不会乱码而且效率较高。
文件字符输入流
1 | Writer fw = new FileWriter("E:/Java_IDEA/logging_test/src/data2.txt", true); |
与字节输入流区别不大,但更方便,可直接写入字符串。
缓冲流
缓存流自带8kb缓冲区,效率更高
缓存流包装原始流,缓冲流构造器均为接受原始流对象:
1 | try ( |
性能比较:
1 | public static void copy2(){ |
运行结果:
1 | 复制完成! |
文件字符缓冲流
readline方法按行读取,很常用
1 | public class char_buffer { |
转换流
InputStreamReader用于解决文件字符流读写编码不一致时的报错。
对象序列化
使用对象字节输出流ObjectOutputStream
1 | public class ObjectOutputStreamDemo { |
注:序列化的类必须实现了可序列化接口,即
1 | public class Student implements Serializable {} |
反序列化
ObjectInputStream
1 | public class ObjectInputStreamDemo { |
注:
1 | private transient String passWord; |
用transient修饰的变量不能序列化。
1 | private static final long serialVersionUID = 0; |
序列化版本号与反序列化必须一致。
打印流
1 | public class Demo1 { |
打印流是最强大的输出流,可将上面所有输出流替代。
注:打印流默认为覆盖管道
若用追加需要:
1 | PrintStream ps = new PrintStream(new FileOutputStream("path/data.txt",true)); |
打印流实现输出重定向
1 | public static void main(String[] args) throws Exception{ |
Properties(属性)
存数据:
1 | public class Demo1 { |
读数据:
1 | public class demo2 { |
IO框架:commons-io框架
一行代码完成复制
1 | import org.apache.commons.io.IOUtils; |