一、常见算法(排序与查找)
(一) 冒泡排序
- 核心逻辑:每轮相邻元素比较,将当前未排序区间的最大值“冒泡”到末尾,重复直至全排序。
- 关键规则:共数组长度-1轮,第 i 轮比较数组长度 - i - 1次,arr[ j ] > arr[ j+1] 时交换;
(二) 选择排序
- 核心逻辑:每轮从当前位置开始,找到未排序区间的最小值,与当前位置元素交换,重复直至全排序。
- 关键规则:共数组长度-1轮,第 i 轮初始将 minIndex 设为 i,从 j = i+1 开始遍历,更新最小值索引; minIndex != i 时交换 arr[ i] 与 arr[ minIndex ]。
(三) 二分查找
- 前提:数组必须有序;
- 核心逻辑:折半缩小范围,每次排除一半数据;
- 步骤:
- 定义 left=0、right=数组长度-1,
- 循环( left<=right )计算mid=(left+right)/2
- 若 目标值 > arr[mid]:目标在右半区,left = mid + 1;
- 若 目标值 < arr[mid]:目标在左半区,right = mid - 1;
- 若 目标值 == arr[mid]:找到目标,返回 mid,未找到返回-1。
(四) 正则表达式(规则表达式)
- 校验数据格式:验证手机号、邮箱、日期等格式是否合法;
- 查找文本内容:从一段文本中提取满足规则的信息(如手机号、邮箱);
- 替换与分割:按规则替换文本内容(如脱敏)、分割字符串(如按任意空白符分割)。
1. 字符类(匹配单个字符)
| 符号 |
含义 |
示例 |
| [abc] |
匹配 a、b、c 中的任意一个 |
[abc] 匹配 “a”、“b” |
| [^abc] |
匹配除 a、b、c 外的任意字符 |
[^abc] 匹配 “d”、“1” |
| [a-z] |
匹配小写字母(a-z) |
[a-z] 匹配 “x”、“y” |
| [a-zA-Z0-9] |
匹配字母或数字 |
[a-zA-Z0-9] 匹配 “A”、“5” |
| [a-z&&[m-p]] |
交集,匹配 a-z 且 m-p 的字符(m-p) |
[a-z&&[m-p]] 匹配 “n” |
2. 预定义字符(匹配单个字符)
| 符号 |
含义 |
示例 |
| . |
匹配任意字符(不包括回车) |
a.b 匹配 “aab”、“acb” |
| \d |
匹配数字(0-9),等价于 [0-9] |
\d{11} 匹配11位数字 |
| \D |
匹配非数字,等价于 [^0-9] |
\D 匹配 “a”、“!” |
| \s |
匹配空白符(空格、制表符等) |
a\sb 匹配 “a b” |
| \S |
匹配非空白符 |
\S 匹配 “x”、“1” |
| \w |
匹配单词字符(字母、数字、下划线) |
\w 匹配 “A”、“5”、“_” |
| \W |
匹配非单词字符 |
\W 匹配 “!”、“@” |
3. 数量词(控制字符出现次数)
| 符号 |
含义 |
示例 |
| X? |
X 出现 0 次或 1 次 |
ab? 匹配 “a”、“ab” |
| X* |
X 出现 0 次或多次 |
ab* 匹配 “a”、“ab”、“abb” |
| X+ |
X 出现 1 次或多次 |
ab+ 匹配 “ab”、“abb” |
| X{n} |
X 恰好出现 n 次 |
\d{11} 匹配11位手机号 |
| X{n,} |
X 至少出现 n 次 |
\d{6,} 匹配6位及以上数字 |
| X{n,m} |
X 出现 n 到 m 次(含边界) |
\d{6,18} 匹配6-18位密码 |
4. 分组与逻辑
| 含义 |
示例 |
| 分组,将 X 视为一个整体 |
(ab)+ 匹配 “ab”、“abab” |
| X|Y |
逻辑或,匹配 X 或 Y |
5. 常用方法与案例
(一) 校验格式
- 语法:
String str.matches(String regex) → 返回 boolean(匹配返回 true)。
String phone = "13811112222";
String regex = "1[3-9]\\d{9}";
System.out.println(phone.matches(regex));
(二) 查找内容
-
步骤:
- 用 Pattern.compile(regex) 封装正则规则;
- 用 pattern.matcher(data) 获取匹配器;
- 用 matcher.find() 循环查找,matcher.group() 提取结果(group(1) 提取第一组)。
-
案例:提取文本中的邮箱:
String data = "邮箱:bozai@itcast.cn,邮箱2:dlei0009@163.com";
String regex = "([a-zA-Z0-9_]+)@([a-zA-Z0-9.]+)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(data);
while (matcher.find()) {
System.out.println("用户名:" + matcher.group(1));
System.out.println("完整邮箱:" + matcher.group());
}
(三) 替换与分割
| 方法 |
作用 |
示例 |
| replaceAll(regex, newStr) |
数字脱敏,按正则替换所有匹配内容 |
str.replaceAll(“\d”, "") → 数字替换为 |
| split(regex) |
按正则分割字符串,返回数组 |
str.split(“\s+”) → 按任意空白符分割 |
二、IO流
(一) 字符编码(IO流基础)
- 核心规则:编码/解码需同一字符集,否则乱码。
- Java实现:
- 编码(String → byte[ ]):
String.getBytes(字符集)(如str.getBytes(“UTF8”));
- 解码(byte[ ] → String):
new String(字节数组, 字符集)(如new String(bytes, “UTF-8”))
| 字符集 |
特点 |
适用场景 |
| ASCII |
1字节存储,仅含英文、数字、符号 |
英文文档 |
| GBK |
中文2字节,兼容ASCII |
中文文档(Windows默认) |
| UTF-8 |
中文3字节,英文1字节,兼容ASCII |
推荐(跨平台、互联网通用) |
(二) IO流体系(核心)
IO流用于读写数据(文件、网络等),按“方向”和“数据单位”分类,核心是四大抽象类及实现类。

| 分类维度 |
类型 |
核心特点 |
适用场景 |
| 按方向 |
输入流(Input) |
从外部(磁盘/网络)读入内存 |
读取文件内容 |
| 输出流(Output) |
从内存写出到外部(磁盘/网络) |
写入文件内容 |
| 按数据单位 |
字节流(byte) |
以字节为单位,可处理所有类型文件(音视频、图片等) |
文件复制、非文本文件读写 |
| 字符流(char) |
以字符为单位,仅处理纯文本文件(.txt、.java等) |
文本文件读写(避免乱码) |
| 流类型 |
抽象类 |
常用实现类 |
核心作用 |
| 字节输入流 |
InputStream |
FileInputStream(文件字节输入流) |
从文件读字节到内存 |
| BufferedInputStream(字节缓冲输入流) |
包装低级流,提升读性能(8KB缓冲区) |
| 字节输出流 |
OutputStream |
FileOutputStream(文件字节输出流) |
从内存写字节到文件 |
| BufferedOutputStream(字节缓冲输出流) |
包装低级流,提升写性能(8KB缓冲区) |
| 字符输入流 |
Reader |
FileReader(文件字符输入流) |
从文件读字符到内存(纯文本) |
| BufferedReader(字符缓冲输入流) |
包装低级流,提升性能,支持按行读 |
| InputStreamReader(字符输入转换流) |
指定编码读文本,解决乱码 |
| 字符输出流 |
Writer |
FileWriter(文件字符输出流) |
从内存写字符到文件(纯文本) |
| BufferedWriter(字符缓冲输出流) |
包装低级流,提升性能,支持换行 |
| OutputStreamWriter(字符输出转换流) |
指定编码写文本,控制输出编码 |
1. 字节流(FileInputStream/FileOutputStream)
核心作用:处理所有类型文件(如图片、视频),以字节为单位读写。
| 流类型 |
构造器 |
核心方法 |
| FileInputStream |
FileInputStream(File/路径) |
read() (读1字节)、read(byte[]) (读字节数组)、close() (关闭流) |
| FileOutputStream |
FileOutputStream(File/路径, boolean append) |
write(int) (写1字节)、write(byte[]) (写字节数组)、close() |
案例:文件复制(字节流核心场景)
try (
InputStream is = new FileInputStream("D:/src.png");
OutputStream os = new FileOutputStream("C:/dest.png")
) {
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
2. 字符流(FileReader/FileWriter)
核心作用:处理纯文本文件,避免字节流读中文乱码(需编码一致)。
| 流类型 |
构造器 |
核心方法 |
注意事项 |
| FileReader |
FileReader(File/路径) |
read()(读1字符)、read(char[]) (读字符数组) |
依赖默认编码,编码不一致会乱码 |
| FileWriter |
FileWriter(File/路径, boolean append) |
write(int/char[]/String) (写字符)、flush() (刷新缓冲) |
需调用flush()或close(),否则数据可能残留缓冲 |
3. 缓冲流(BufferedXXX)
核心作用:包装低级流(如FileInputStream),自带8KB缓冲区,大幅提升读写性能。
| 缓冲流类型 |
构造器 |
新增核心方法 |
| BufferedInputStream |
BufferedInputStream(InputStream) |
无新增,性能提升 |
| BufferedOutputStream |
BufferedOutputStream(OutputStream) |
无新增,性能提升 |
| BufferedReader |
BufferedReader(Reader) |
readLine() (按行读文本,返回 null 表示结束) |
| BufferedWriter |
BufferedWriter(Writer) |
newLine() (跨平台换行,替代 \r\n ) |
4. 转换流(InputStreamReader/OutputStreamWriter)
核心作用:解决编码乱码,指定编码读写。
| 转换流类型 |
构造器 |
核心作用 |
| InputStreamReader |
InputStreamReader(InputStream, String charset) |
按指定编码将字节流转为字符流(读文本) |
| OutputStreamWriter |
OutputStreamWriter(OutputStream, String charset) |
按指定编码将字符流转为字节流(写文本) |
案例:指定UTF-8读文本
try (
Reader isr = new InputStreamReader(new FileInputStream("D:/test.txt"), "UTF-8");
BufferedReader br = new BufferedReader(isr)
) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
5. 打印流(PrintStream/PrintWriter)
核心作用:方便打印任意类型数据(如int、String),性能高效,支持自动刷新。
| 打印流类型 |
特点 |
核心方法 |
| PrintStream |
继承字节输出流,支持写字节 |
println( 任意类型 )、printf( 格式 , 参数 ) |
| PrintWriter |
继承字符输出流,支持写字符,可指定编码 |
println( 任意类型 )、flush() |
应用:输出重定向(将System.out输出到文件)
try (PrintStream ps = new PrintStream("D:/log.txt", "UTF-8")) {
System.setOut(ps);
System.out.println("日志内容:程序启动成功");
} catch (IOException e) {
e.printStackTrace();
}
6. 数据流(DataInputStream/DataOutputStream)
核心作用:读写数据时保留数据类型(如int、double),需按写入顺序读取。
| 数据流类型 |
构造器 |
核心方法 |
| DataInputStream |
DataInputStream(InputStream) |
readInt()、readDouble()、readUTF() |
| DataOutputStream |
DataOutputStream(OutputStream) |
writeInt()、writeDouble()、writeUTF() |
7. 序列化流(ObjectInputStream/ObjectOutputStream)
核心作用:实现“对象序列化”(将Java对象写入文件)和“反序列化”(从文件读入对象)。
| 序列化流类型 |
核心方法 |
注意事项 |
| ObjectOutputStream |
writeObject(Object obj) |
对象必须实现 Serializable 接口(标记接口,无方法) |
| ObjectInputStream |
readObject() |
读取顺序需与写入顺序一致,反序列化类需存在 |
批量序列化:用ArrayList存储多个对象(ArrayList已实现Serializable):
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:/students.txt"))) {
List<Student> list = new ArrayList<>();
list.add(new Student("张三", 20));
list.add(new Student("李四", 22));
oos.writeObject(list);
} catch (IOException e) {
e.printStackTrace();
}
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/students.txt"))) {
List<Student> list = (List<Student>) ois.readObject();
System.out.println(list);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
(三) IO框架(Commons-IO)
封装原生IO,简化操作,提升效率(Apache开源)。
| 工具类 |
核心方法 |
说明 |
| FileUtils |
copyFile(File src, File dest) |
复制文件 |
| copyDirectory(File srcDir, File destDir) |
复制文件夹(含子文件夹) |
| deleteDirectory(File dir) |
删除非空文件夹 |
| readFileToString(File file, String charset) |
按指定编码读文件为字符串 |
| IOUtils |
copy(InputStream in, OutputStream out) |
复制输入流到输出流(支持字节/字符流) |
| write(String data, OutputStream out, String charset) |
按指定编码写字符串到输出流 |
三、集合
集合是可变容量的容器,解决数组容量固定问题,核心差异是元素存储形式(单值/键值对)。
| 集合类型 |
元素形式 |
顶层接口 |
核心实现类 |
| 单列集合 |
单个值(如"张三") |
Collection |
List(ArrayList、LinkedList)、Set(HashSet、LinkedHashSet、TreeSet) |
| 双列集合 |
键值对(如"张三"=20) |
Map |
HashMap、LinkedHashMap、TreeMap |
(一) 单列集合(Collection)
| 方法名 |
说明 |
| add(E e) |
添加元素,成功返回 true |
| clear() |
清空集合所有元素 |
| remove(E e) |
删除指定元素,成功返回 true |
| contains(Object obj) |
判断是否包含指定元素 |
| isEmpty() |
判断集合是否为空 |
| size() |
返回元素个数 |
| toArray() |
转为Object数组 |
| 遍历方式 |
适用场景 |
核心代码 |
| 迭代器 (Iterator) |
所有单列集合(最底层方式) |
Iterator it = c.iterator(); while(it.hasNext()) { E e = it.next(); } |
| 增强for循环 |
简化迭代器,无需手动控制索引 |
for (E e : 集合 ) { … } |
| Lambda表达式 |
JDK8+,代码最简洁 |
集合 .forEach(e -> System.out.println(e)); |
1. List集合(有序、可重复、有索引)
| 实现类 |
底层原理 |
核心优势 |
适用场景 |
| ArrayList |
动态数组(初始10,扩容1.5倍) |
查询快(索引定位) |
频繁查询、少量增删 |
| LinkedList |
双链表 |
首尾增删快,支持首尾操作特有方法 |
频繁操作首尾(如栈/队列) |
List特有方法(索引相关)
| 方法名 |
说明 |
| add(int index, E e) |
在指定索引插入元素 |
| remove(int index) |
删除指定索引元素,返回被删元素 |
| set(int index, E e) |
修改指定索引元素,返回旧值 |
| get(int index) |
返回指定索引元素 |
LinkedList特有方法(首尾操作)
| 方法名 |
说明 |
| addFirst(E e) / addLast(E e) |
首尾添加元素 |
| getFirst() / getLast() |
获取首尾元素 |
| removeFirst() / removeLast() |
删除首尾元素,返回被删元素 |
2. Set集合(无序/有序、不重复、无索引)
| 实现类 |
底层原理 |
核心特点 |
去重/排序机制 |
| HashSet |
哈希表 (数组+链表+红黑树) |
无序 |
依赖 hashCode() + equals() |
| LinkedHashSet |
哈希表+双链表 |
有序(记插入顺序) |
同HashSet,双链表保顺序 |
| TreeSet |
红黑树 |
可排序(默认升序) |
实现 Comparable 或传 Comparator |
注意:
- HashSet去重:自定义对象需重写hashCode() 和equals() ,确保“内容相同则哈希值相同、equals返回true”;
- TreeSet排序:
- 方式1:自定义类实现Comparable 接口,重写compareTo() (如return this.age - o.age );
- 方式2:创建TreeSet 时传入Comparator (如new TreeSet<>((a,b)
-> b.age - a.age) ,降序);
- 哈希表优化:JDK8后,链表长度>8且数组长度≥64时,链表自动转红黑树,提升查询性能。
(二) 双列集合(Map)
元素是键值对(key=value),key不重复、value可重复,特点由key决定;
| 实现类 |
底层原理 |
核心特点 |
适用场景 |
| HashMap |
哈希表(同 HashSet) |
无序、key不重复、无索引 |
通用场景,增删改查性能好 |
| LinkedHashMap |
哈希表+双链表 |
有序(记住key添加顺序)、key不重复 |
需要保留插入顺序的场景 |
| TreeMap |
红黑树(同 TreeSet) |
key可排序、不重复、无索引 |
需要对key排序的场景 (如按年龄排序) |
| 方法名 |
说明 |
| put(K key, V value) |
添加键值对(key重复则覆盖value) |
| get(Object key) |
根据key获取value(无则返回null) |
| remove(Object key) |
根据key删除键值对,返回value |
| containsKey(Object key) |
判断是否包含指定key |
| containsValue(Object v) |
判断是否包含指定value |
| keySet() |
获取所有key的Set集合 |
| values() |
获取所有value的Collection集合 |
| entrySet() |
获取所有键值对(Map.Entry)的Set集合 |
| 遍历方式 |
核心逻辑 |
代码示例 |
| 键找值 |
先遍历key,再通过key找value |
Set keys = map.keySet(); for (K k : keys) { V v = map.get(k); } |
| 键值对 |
直接遍历键值对对象 |
Set<Map.Entry<K,V>> entries = map.entrySet(); for (Map.Entry<K,V> e : entries) { K k = e.getKey(); V v = e.getValue(); } |
| Lambda表达式 |
JDK8+,简化遍历 |
map.forEach( (k, v) -> System.out.println(k + “=” + v) ); |
(三) Stream流(JDK8+)
Stream流是简化集合/数组操作的API,结合Lambda表达式,代码更简洁,支持“链式编程”。
关键步骤:
- 获取Stream流:从集合/数组创建流;
- 中间操作:过滤、排序、转换等(返回新流,支持链式);
- 终结操作:遍历、统计、收集结果(无返回值或返回非流结果)。
| 数据源 |
获取方式 |
示例 |
| 集合 |
Collection.stream() |
List list = new ArrayList<>(); Stream s = list.stream(); |
| 数组 |
Arrays.stream( 数组 ) |
int[] arr = {1,2,3}; Stream<int[]> s = Arrays.stream(arr); |
| 零散数据 |
Stream.of( 数据1, 数据2… ) |
Stream s = Stream.of(“a”, “b”, “c”); |
中间方法(返回新Stream):
| 方法名 |
说明 |
示例 |
| filter(Predicate p) |
过滤元素(满足条件保留) |
s.filter(e -> e.startsWith(“张”)) |
| sorted() / sorted(Comparator c) |
升序排序/自定义排序 |
s.sorted((a,b) -> b.length() - a.length()) (按长度降序) |
| limit(long n) |
保留前n个元素 |
s.limit(3) (保留前3个) |
| skip(long n) |
跳过前n个元素 |
s.skip(2) (跳过前2个) |
| distinct() |
去重(依赖 equals() ) |
s.distinct() |
| map(Function f) |
元素转换(如 String→Integer) |
s.map(Integer::parseInt) (字符串转整数) |
| concat(Stream a, Stream b) |
合并两个流 |
Stream.concat(s1, s2) |
终结方法(无返回Stream):
| 方法名 |
说明 |
示例 |
| forEach(Consumer c) |
遍历元素 |
s.forEach(System.out::println) |
| count() |
统计元素个数(返回 long) |
long size = s.count(); |
| max(Comparator c) / min(Comparator c) |
获取最大/最小值(返回 Optional) |
Optional max = s.max((a,b) -> a.compareTo(b)); |
| collect(Collector c) |
收集到集合/数组 |
List list = s.collect(Collectors.toList()); |
通过Collectors工具类将流结果转为集合/数组:
| 收集方式 |
说明 |
| Collectors.toList() |
收集到List集合 |
| Collectors.toSet() |
收集到Set集合(去重) |
| Collectors.toMap(kf, vf) |
收集到Map集合(kf为key映射,vf为value映射) |
| toArray() |
收集到Object数组 |
(四) 工具类与补充知识
1. Collections工具类(操作集合的静态工具)
| 方法名 |
说明 |
| addAll(Collection c, T… elements) |
批量添加元素 |
| shuffle(List<?> list) |
打乱List元素顺序 |
| sort(List list) / sort(List list, Comparator c) |
List升序/自定义排序 |
2. 可变参数(灵活接收数据)
- 格式:
数据类型... 参数名(如int… nums);
- 特点:
- 方法内部视为数组;
- 一个方法仅能有一个可变参数,且需在形参列表末尾;
示例:
public static int sum(int... nums) {
int s = 0;
for (int n : nums)
s += n;
return s;
}
3. 并发修改异常(遍历中修改集合)
- 场景:迭代器/增强for遍历集合时,用集合remove() 删除元素;
- 解决:
- 迭代器遍历:用
iterator.remove()删除;
- for循环遍历:倒序遍历或删除后 i - - 。
(五) 集合选型建议
| 需求场景 |
推荐集合 |
| 频繁查询、有序可重复 |
ArrayList |
| 频繁增删首尾元素 |
LinkedList |
| 无序不重复、增删改查快 |
HashSet |
| 有序不重复、需保留插入顺序 |
LinkedHashSet |
| 需排序不重复 |
TreeSet |
| 键值对存储、无序 |
HashMap |
| 键值对存储、需保留插入顺序 |
LinkedHashMap |
| 键值对存储、需对key排序 |
TreeMap |
| 简化集合/数组操作(过滤、排序等) |
Stream流 |
四、日志
记录程序运行信息(如错误、操作),可存控制台/文件/数据库,无需改代码即可控制启停,优于System.out(仅控制台、需改代码)。
(一) Logback日志框架(重点)
基于SLF4J接口,需导3个模块:
- slf4j-api.jar:SLF4J接口;
- logback-core.jar:基础模块;
- logback-classic.jar:SLF4J接口实现(核心功能)。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%level] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/app-%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%level] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
代码中使用:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogbackTest {
private static final Logger LOGGER = LoggerFactory.getLogger(LogbackTest.class);
public static void main(String[] args) {
LOGGER.trace("追踪信息(程序轨迹)");
LOGGER.debug("调试信息(开发调试)");
LOGGER.info("普通信息(如启动成功)");
LOGGER.warn("警告信息(如参数异常)");
LOGGER.error("错误信息(如异常堆栈)");
}
}
(二) 日志级别(核心控制)
| 级别 |
说明 |
适用场景 |
| TRACE |
程序运行轨迹(最详细,极少用) |
深度调试 |
| DEBUG |
调试信息 |
开发阶段验证逻辑 |
| INFO |
普通运行信息(默认核心级别) |
系统启动、关键操作记录(如登录) |
| WARN |
警告信息(非致命问题) |
参数不合法、资源不足 |
| ERROR |
错误信息(致命问题) |
异常、功能失败 |
| ALL |
输出所有级别日志 |
全量调试 |
| OFF |
关闭所有日志 |
生产环境临时关闭 |
级别作用:
- 配置文件中设置root level=“级别” 后,仅输出 ≥该级别的日志 (如设置INFO ,则INFO / WARN / ERROR 会输出,TRACE / DEBUG 被过滤)。
- 用途:开发阶段用DEBUG ,生产阶段用INFO / WARN,减少日志冗余。
所有评论(0)