文章目录
-
- 一、常见算法详解
- 二、正则表达式深入解析
- 三、异常处理机制
-
- [3.1 异常体系结构](#3.1 异常体系结构)
- [3.2 异常处理方式](#3.2 异常处理方式)
- [3.3 自定义异常](#3.3 自定义异常)
- [3.4 异常处理最佳实践](#3.4 异常处理最佳实践)
- 四、总结与应用场景
-
- [4.1 算法应用场景](#4.1 算法应用场景)
- [4.2 正则表达式应用场景](#4.2 正则表达式应用场景)
- [4.3 异常处理应用场景](#4.3 异常处理应用场景)
本文将深入探讨Java中三大核心技术:常见算法、正则表达式和异常处理,帮助开发者掌握这些必备技能。
一、常见算法详解
1.1 排序算法
冒泡排序
原理 :通过相邻元素比较和交换,每一轮将最大元素"冒泡"到数组末尾
关键步骤:
- 确定轮数:数组长度-1
- 每轮比较次数:数组长度-当前轮数-1
- 相邻元素比较,顺序错误则交换
java
// 冒泡排序实现
public static void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
选择排序
原理 :每轮选择一个固定位置元素,与后面元素比较找到最小元素并交换
关键步骤:
- 确定轮数:数组长度-1
- 每轮从当前位置开始向后比较
- 找到最小元素索引并交换
java
// 选择排序实现
public static void selectionSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
1.2 查找算法
二分查找
前提 :数组必须有序
原理 :每次将查找范围缩小一半
步骤:
- 定义左右边界(left, right)
- 计算中间位置 mid = (left + right) / 2
- 比较中间元素与目标值:
- 目标值大:left = mid + 1
- 目标值小:right = mid - 1
- 相等:返回mid
- 循环直到left > right,未找到返回-1
java
// 二分查找实现
public static int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}

二、正则表达式深入解析
2.1 正则表达式基础
核心作用:
- 数据格式校验(如手机号、邮箱验证)
- 文本内容提取(爬取特定信息)
- 文本替换与分割
基础语法 :
类别 | 表达式 | 说明 |
---|---|---|
字符类 | [abc] | 匹配a、b或c |
[^abc] | 匹配除a、b、c外的字符 | |
[a-zA-Z] | 匹配任意字母 | |
预定义字符 | . | 匹配任意单个字符 |
\d | 匹配数字[0-9] | |
\D | 匹配非数字 | |
\s | 匹配空白字符 | |
\S | 匹配非空白字符 | |
数量词 | X? | 0或1次 |
X* | 0或多次 | |
X+ | 1或多次 | |
X{n} | 恰好n次 | |
X{n,} | 至少n次 | |
X{n,m} | n到m次 | |
边界匹配 | ^ | 行首 |
$ | 行尾 | |
\b | 单词边界 |
2.2 正则表达式应用案例
测试
java
public static void main(String[] args) {
// 1、字符类(只能匹配单个字符)
System.out.println("a".matches("[abc]")); // [abc]只能匹配a、b、c
System.out.println("e".matches("[abcd]")); // false
System.out.println("d".matches("[^abc]")); // [^abc] 不能是abc
System.out.println("a".matches("[^abc]")); // false
System.out.println("b".matches("[a-zA-Z]")); // [a-zA-Z] 只能是a-z A-Z的字符
System.out.println("2".matches("[a-zA-Z]")); // false
System.out.println("k".matches("[a-z&&[^bc]]")); // [a-z&&[^bc]] a到z,除了b和c
System.out.println("b".matches("[a-z&&[^bc]]")); // false
System.out.println("ab".matches("[a-zA-Z0-9]")); // false 注意:以上带 [内容] 的规则都只能用于匹配单个字符
// 2、预定义字符(只能匹配单个字符) . \d \D \s \S \w \W
System.out.println("徐".matches(".")); // .可以匹配任意字符
System.out.println("徐徐".matches(".")); // false
// \转义
System.out.println("\"");
// \n \t
System.out.println("3".matches("\\d")); // \d: 0-9
System.out.println("a".matches("\\d")); //false
System.out.println(" ".matches("\\s")); // \s: 代表一个空白字符
System.out.println("a".matches("\s")); // false
System.out.println("a".matches("\\S")); // \S: 代表一个非空白字符
System.out.println(" ".matches("\\S")); // false
System.out.println("a".matches("\\w")); // \w: [a-zA-Z_0-9]
System.out.println("_".matches("\\w")); // true
System.out.println("徐".matches("\\w")); // false
System.out.println("徐".matches("\\W")); // [^\w]不能是a-zA-Z_0-9
System.out.println("a".matches("\\W")); // false
System.out.println("23232".matches("\\d")); // false 注意:以上预定义字符都只能匹配单个字符。
// 3、数量词: ? * + {n} {n, } {n, m}
System.out.println("a".matches("\\w?")); // ? 代表0次或1次
System.out.println("".matches("\\w?")); // true
System.out.println("abc".matches("\\w?")); // false
System.out.println("abc12".matches("\\w*")); // * 代表0次或多次
System.out.println("".matches("\\w*")); // true
System.out.println("abc12张".matches("\\w*")); // false
System.out.println("abc12".matches("\\w+")); // + 代表1次或多次
System.out.println("".matches("\\w+")); // false
System.out.println("abc12张".matches("\\w+")); // false
System.out.println("a3c".matches("\\w{3}")); // {3} 代表要正好是n次
System.out.println("abcd".matches("\\w{3}")); // false
System.out.println("abcd".matches("\\w{3,}")); // {3,} 代表是>=3次
System.out.println("ab".matches("\\w{3,}")); // false
System.out.println("abcde徐".matches("\\w{3,}")); // false
System.out.println("abc232d".matches("\\w{3,9}")); // {3, 9} 代表是 大于等于3次,小于等于9次
// 4、其他几个常用的符号:(?i)忽略大小写 、 或:| 、 分组:()
System.out.println("abc".matches("(?i)abc")); // true
System.out.println("ABC".matches("(?i)abc")); // true
System.out.println("aBc".matches("a((?i)b)c")); // true
System.out.println("ABc".matches("a((?i)b)c")); // false
// 需求1:要求要么是3个小写字母,要么是3个数字。
System.out.println("abc".matches("[a-z]{3}|\\d{3}")); // true
System.out.println("ABC".matches("[a-z]{3}|\\d{3}")); // false
System.out.println("123".matches("[a-z]{3}|\\d{3}")); // true
System.out.println("A12".matches("[a-z]{3}|\\d{3}")); // false
// 需求2:必须是"我爱"开头,中间可以是至少一个"编程",最后至少是1个"666"
System.out.println("我爱编程编程666666".matches("我爱(编程)+(666)+"));
System.out.println("我爱编程编程66666".matches("我爱(编程)+(666)+"));
}
数据校验
java
// 手机号校验(支持手机和座机)
public static boolean validatePhone(String phone) {
return phone.matches("(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})");
//表示手机号 1开头,第二位是3-9,后面是9位的数字
//或 座机号:以0开头,后面区号长度2-7位,-? -至多出现1次,开头1-9,后面4-19位的数字
}
// 邮箱校验
public static boolean validateEmail(String email) {
/**
* dlei0009@163.com
* 25143242@qq.com
* itheima@itcast.com.cn
*/
return email.matches("\\w{2,}@\\w{2,20}(\\.\\w{2,10}){1,2}");
// \\w 可能是英文字符或数字,{2,} 2位以上,有一个@,2-20位的字符或数字,
//有一个. \\. 第一个\ 告诉第二个\:你就是个\,第二个\告诉后面的.:你就是个.
//\\w{2,10} 2-10位的字符或数字
// (\\.\\w{2,10}){1,2} 表示(\\.\\w{2,10}) 这个表达式可能出现1-2次
}
信息爬取
java
// 从文本中提取所有电话号码
public static List<String> extractPhones(String text) {
List<String> phones = new ArrayList<>();
String regex = "(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
phones.add(matcher.group());
}
return phones;
}
// 需求:从以下内容中爬取出,手机,邮箱,座机、400电话等信息。
public static void method1(){
String data = " 来学习Java,电话:1111111111,18699997777" +
" 或者联系邮箱:boniufe@com.cn,\n" +
" 热线电话:400-618-90960 40061897090";
// 1、定义爬取规则
//(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19}) 手机或座机的正则表达式
//(\\w{2,}@\\w{2,20}(\\.\\w{2,10}){1,2}) 邮箱的表达式
//(400-?\\d{3,7}-?\\d{3,7}) 400开头,-可有可无,3-7位数字
String regex = "(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})|(\\w{2,}@\\w{2,20}(\\.\\w{2,10}){1,2})"
+ "|(400-?\\d{3,7}-?\\d{3,7})";
// 2、把正则表达式封装成一个Pattern对象
Pattern pattern = Pattern.compile(regex);
// 3、通过pattern对象去获取查找内容的匹配器对象。
Matcher matcher = pattern.matcher(data);
// 4、定义一个循环开始爬取信息
while (matcher.find()){
String rs = matcher.group(); // 获取到了找到的内容了。
System.out.println(rs);
}
}
文本处理
正则表达式用于搜索替换、分割内容,需要结合String提供的如下方法完成:

java
// 需求1:请把 古力娜扎ai8888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴,中间的非中文字符替换成 "-"
String s1 = "古力娜扎ai8888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴";
System.out.println(s1.replaceAll("\\w+", "-")); //数字或字符替换成-
// 需求2(拓展):某语音系统,收到一个口吃的人说的"我我我喜欢编编编编编编编编编编编编程程程!",需要优化成"我喜欢编程!"。
String s2 = "我我我喜欢编编编编编编编编编编编编程程程";
/**
* (.)一组:.匹配任意字符的。
* \\1 :为这个组声明一个组号:1号
* +:声明必须是重复的字
* $1可以去取到第1组代表的那个重复的字
*/
System.out.println(s2.replaceAll("(.)\\1+", "$1"));
// 替换所有非汉字字符
String result = text.replaceAll("[^\\u4e00-\\u9fa5]", "-");
// 按数字分割字符串
String[] parts = text.split("\\d+");
2.3 高级技巧
- 非贪婪匹配:在量词后加?(如.*?)
- 分组引用:使用()分组,$n引用分组
- 前瞻后顾:(?=exp)正向前瞻,(?!exp)负向前瞻
java
// 提取用户名(非贪婪匹配)
public static List<String> extractUsernames(String text) {
List<String> usernames = new ArrayList<>();
Pattern pattern = Pattern.compile("欢迎(.+?)光临");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
usernames.add(matcher.group(1)); // 获取第一个分组
}
return usernames;
}
三、异常处理机制
3.1 异常体系结构
Java异常体系:
异常分类:
- 编译时异常:必须显式处理(如IOException)
- 运行时异常:可处理也可不处理(如NullPointerException)
3.2 异常处理方式

抛出异常(throws)
java
public void readFile() throws IOException {
// 可能抛出IOException的代码
FileReader reader = new FileReader("file.txt");
// ...
}
alt+回车 跑出异常
捕获异常(try-catch)

java
try {
// 可能出错的代码
int result = 10 / 0;
} catch (ArithmeticException e) {
// 处理算术异常
System.out.println("除数不能为零");
e.printStackTrace();
} catch (Exception e) {
// 处理其他异常
System.out.println("发生未知错误");
} finally {
// 无论是否异常都会执行
System.out.println("清理资源");
}
3.3 自定义异常

自定义编译时异常:
java
public class InvalidAgeException extends Exception {
public InvalidAgeException() {
super("年龄无效");
}
public InvalidAgeException(String message) {
super(message);
}
}
自定义运行时异常:
java
public class BusinessException extends RuntimeException {
public BusinessException(String message) {
super(message);
}
}
使用自定义异常:
java
public void setAge(int age) throws InvalidAgeException {
if (age < 0 || age > 150) {
throw new InvalidAgeException("年龄必须在0-150之间");
}
this.age = age;
}
3.4 异常处理最佳实践

上图表示A调用B,B调用C,处理异常时,C抛出异常给B,B抛出异常给A,A是最上层,不能再抛, 需要处理,处理方法有两种:(1)记录异常反馈给用户,(2)尝试重新修复
- 优先处理具体异常:先捕获具体异常,再捕获通用异常
- 避免空catch块:至少记录异常信息
- 使用finally释放资源:确保资源正确关闭
- 异常信息清晰:提供足够的问题描述
- 合理使用自定义异常:封装业务相关异常
- 异常与返回码结合:根据场景选择合适方式
java
// 标准异常处理模板
public void processFile(String path) {
FileInputStream fis = null;
try {
fis = new FileInputStream(path);
// 处理文件
} catch (FileNotFoundException e) {
log.error("文件不存在: {}", path);
throw new BusinessException("文件不存在");
} catch (IOException e) {
log.error("文件读取错误", e);
throw new BusinessException("文件处理失败");
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
log.warn("关闭文件流失败", e);
}
}
}
}
四、总结与应用场景
4.1 算法应用场景
- 冒泡/选择排序:小型数据集排序
- 二分查找:有序数据集快速查找
- 复杂算法:大型系统性能优化
4.2 正则表达式应用场景
- 表单验证:手机号、邮箱、身份证号等
- 日志分析:提取关键信息
- 文本处理:批量替换、格式转换
- 数据清洗:去除无效字符
4.3 异常处理应用场景
- 资源管理:文件、网络连接等
- 业务校验:参数检查、状态验证
- 系统边界:第三方服务调用
- 错误恢复:事务回滚、重试机制
综合最佳实践:
- 对用户输入使用正则验证
- 核心业务逻辑使用自定义异常
- 数据处理结合合适算法
- 资源操作使用try-with-resources
java
// 综合应用示例:用户注册
public void registerUser(String username, String phone, String email)
throws InvalidInputException {
// 正则验证输入
if (!validatePhone(phone)) {
throw new InvalidInputException("手机号格式错误");
}
if (!validateEmail(email)) {
throw new InvalidInputException("邮箱格式错误");
}
// 使用高效算法检查用户名是否已存在
if (binarySearch(existingUsers, username) >= 0) {
throw new BusinessException("用户名已存在");
}
// 保存用户(数据库操作)
try {
userDao.save(new User(username, phone, email));
} catch (SQLException e) {
throw new PersistenceException("用户保存失败", e);
}
}
掌握这些核心技术,能够显著提升代码质量和开发效率。在实际项目中,合理组合使用算法、正则和异常处理,可以构建出健壮高效的Java应用程序。