当前位置: 首页 > news >正文

Java从入门到精通 - 算法、正则、异常

算法、正则、异常

此笔记参考黑马教程,仅学习使用,如有侵权,联系必删

文章目录

  • 算法、正则、异常
    • 1. 常见算法
      • 1.1 简单认识算法
        • 1.1.1 什么是算法?
        • 1.1.2 为什么要学习算法?
      • 1.2 排序算法
        • 1.2.1 冒泡排序
          • 1.2.1.1 实现冒泡排序的关键步骤分析
          • 代码实现
        • 1.2.2 选择排序
          • 1.2.2.1 选择排序的关键
          • 代码实现
      • 1.3 查找算法
        • 1.3.1 基本查找/顺序查找
        • 1.3.2 二分查找(折半查找)
          • 代码实现
    • 2. 正则表达式
      • 2.1 概述、初体验
      • 2.2 书写规则
        • 2.2.1 正则表达式的书写规则
        • 2.2.2 其他几个常用的符号
      • 2.3 应用案例
        • 代码演示
      • 2.4 用于查找信息
        • 代码实现
      • 2.5 用于搜索替换、分割内容
        • 代码演示
    • 3. 异常
      • 3.1 认识异常
        • 3.1.1 什么是异常?
        • 3.1.2 异常的体系
        • 3.1.3 抛出异常(throws)
        • 3.1.4 捕获异常(try...catch)
        • 代码演示
      • 3.2 自定义异常
        • 3.2.1 自定义异常的种类
          • 自定义运行时异常
          • 自定义编译时异常
        • 3.2.2 异常有什么作用?
        • 代码演示
      • 3.3 异常的处理
        • 3.3.1 开发中对于异常的常见处理方式
        • 3.3.2 抛出异常(throws)
        • 3.3.3 捕获异常(try...catch)
        • 代码演示

1. 常见算法

1.1 简单认识算法

1.1.1 什么是算法?
  • 解决某个实际问题的过程和方法
1.1.2 为什么要学习算法?
  • 编程思维
  • 面试

1.2 排序算法

学习算法的技巧:

  1. 先搞清楚算法的流程
  2. 直接去推敲如何写代码
1.2.1 冒泡排序
  • 每次从数组中找出最大值放在数组的后面去

1.2.1.1 实现冒泡排序的关键步骤分析
  • 确定总共需要做几轮:数组的长度 - 1
  • 每轮比较几次:

  • 当前位置大于后一个位置则交换数据
代码实现
package Advanced.b_algorithm;import java.util.Arrays;/*** 目标:掌握冒泡排序的编写*/
public class 冒泡排序 {public static void main(String[] args) {// 1. 准备一个数组int[] arr = {5, 2, 3, 1};// 2.定义一个循环控制排几轮for (int i = 0; i < arr.length; i++) {// 3. 定义一个循环控制比较几轮for (int j = 0; j < arr.length - i - 1; j++) {// 判断当前位置的元素值,是否大于后一个位置处的元素值,如果大则交换if (arr[j] > arr[j + 1]) {int temp = arr[j + 1];arr[j + 1] = arr[j];arr[j] = temp;}}}System.out.println(Arrays.toString(arr)); // [1, 2, 3, 5]}
}

1.2.2 选择排序
  • 每轮选择当前位置,开始找出后面的较小值与该位置交换

![](https://i-blog.csdnimg.cn/direct/f12c90ff90bb4ebaa843b3406d24ea5b.png#pic_center =500)

1.2.2.1 选择排序的关键
  • 确定总共需要选择几轮:数组的长度 - 1
  • 控制每轮从以前位置为基准,与后面元素选择几次

代码实现
package Advanced.b_algorithm;import java.util.Arrays;/*** 目标:掌握选择排序*/
public class 选择排序 {public static void main(String[] args) {// 1. 准备好一个数组int[] arr = {5, 1, 3, 2};// 2. 控制选择几轮for (int i = 0; i < arr.length - 1; i++) {// 3. 控制每轮选择几次for (int j = i + 1; j < arr.length; j++) {// 判断当前位置是否大于后面位置处的元素值,若大于则交换if (arr[i] > arr[j]) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}}System.out.println(Arrays.toString(arr)); // [1, 2, 3, 5]}
}
  • 优化
package Advanced.b_algorithm;import java.util.Arrays;/*** 目标:掌握选择排序*/
public class 选择排序 {public static void main(String[] args) {// 1. 准备好一个数组int[] arr = {5, 1, 3, 2};// 2. 控制选择几轮for (int i = 0; i < arr.length - 1; i++) {int minIndex = i;// 3. 控制每轮选择几次for (int j = i + 1; j < arr.length; j++) {// 判断当前位置是否大于后面位置处的元素值,若大于则交换if (arr[minIndex] > arr[j]) {minIndex = j;}}// 决定是否交换if (i != minIndex) {int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}}System.out.println(Arrays.toString(arr)); // [1, 2, 3, 5]}
}

1.3 查找算法

1.3.1 基本查找/顺序查找

就是暴力一个一个循环查找

注意:在数据量特别大的时候,基本查找这种从前往后挨个找的形式,性能是很差的!

1.3.2 二分查找(折半查找)

前提条件:数组中的数据必须是有序的

核心思想:每次排除一半的数据,查询数据的性能明显提高极多

二分查找正常的折半条件应该是开始位置 left <= 结束位置 right

代码实现
package Advanced.b_algorithm;import java.util.Arrays;/*** 目标:掌握二分查找*/
public class 二分查找 {public static void main(String[] args) {// 1. 准备号一个数组int[] arr = {7, 23, 79, 81, 103, 127, 131, 147};System.out.println(binarySearch(arr, 81)); // 3System.out.println(Arrays.binarySearch(arr, 81)); // 3}public static int binarySearch(int[] arr, int data) {// 1. 定义两个变量,一个站在左边位置,一个站在右边位置int left = 0;int right = arr.length - 1;// 2. 定义一个循环控制折半while (left <= right) {// 3. 每次折半,都算出中间位置处的索引int middle = (left + right) / 2;// 4. 判断当前要找的元素值,与中间位置处的元素值的大小情况if (data < arr[middle]) {// 往左走,截止位置(右边位置) = 中间位置 - 1right = middle - 1;} else if (data > arr[middle]) {// 往右边找,起始位置(左边位置) = 中间位置 + 1} else {// 中间位置处的元素值,正好等于我们要找的元素值return middle;}}return -1; // -1特殊结果,就代表没有找到数据,数组中不存在该数据}
}

2. 正则表达式

2.1 概述、初体验

  • 就是由一些特定的字符组成,代表的是一个规则

作用一:用来校验数据格式是否合法

作用二:在一段文本中查找满足要求的内容

使用正则表达式校验数据,你的代码风格会非常的简单、便捷

package Advanced.c_regex;/*** 目标:体验一下使用正则表达式来校验数据格式的合法性* 需求:校验QQ号是否正确:要求全部是数字,长度是(6-20)之间,不能以0开头*/
public class RegexTest1 {public static void main(String[] args) {System.out.println(checkQQ(null)); // falseSystem.out.println(checkQQ("123456789")); // trueSystem.out.println(checkQQ("21478fadf15")); // falseSystem.out.println("------------------------");System.out.println(checkQQ1(null)); // falseSystem.out.println(checkQQ1("123456789")); // trueSystem.out.println(checkQQ1("21478fadf15")); // false}public static boolean checkQQ1(String qq) {return qq != null && qq.matches("[1-9]\\d{5,19}");}public static boolean checkQQ(String qq) {// 1. 判断qq号码是否为nullif (qq == null || qq.startsWith("0") || qq.length() < 6 || qq.length() > 20) {return false;}// 2. qq至少不是null,不是以0开头,满足6-20之间的长度// 判断qq号码中是否都是数字for (int i = 0; i < qq.length(); i++) {// 根据索引提取当前位置处的字符char ch = qq.charAt(i);// 判断ch记住的字符,如果不是数字,qq号就不合法if (ch < '0' || ch > '9') {return false;}}// 3. 说明qq号肯定是合法的return true;}
}

2.2 书写规则

String 提供了一个匹配正则表达式的方法

public boolean matches(String regex) 判断字符串是否匹配正则表达式,匹配返回 true,不匹配返回 false

2.2.1 正则表达式的书写规则
字符类(只能匹配单个字符)说明
[abc]只能是 a,b 或 c
[^abc]除了 a,b,c 之外的任何字符
[a-zA-Z]a 到 z,A 到 z,包括(范围)
[a-d[m-p]]a 到 d,或 m 到 p
[a-z&&[def]]d,e 或 f(交集)
[a-z&&[^bc]]a 到 z,除了 b 和 c(等同于 [ad-z]
[a-z&&[^m-p]]a 到 z,除了 m到 p(等同于 [a-lq-z]
预定义字符(只能匹配单个字符)说明
.任何字符
\d一个数字:[0-9]
\D非数字:[^0-9]
\s一个空白字符
\S非空白字符:[^\s]
\w[a-zA-Z_0-9]
\W[^\w] 一个非单词字符
数量词说明
X?X,一次或0次
X*X,零次或多次
X+X,一次或多次
X{n}X,正好 n 次
X{n, }X,至少 n 次
X{n,m}X,至少 n 但不超过 m 次
2.2.2 其他几个常用的符号

(?i) :忽略大小写

| :或

() :分组


2.3 应用案例

需求:

校验用户输入的电话、邮箱、时间是否合法

代码演示
package Advanced.c_regex;import java.util.Scanner;/*** 目标:校验用户输入的电话、邮箱、时间是否合法*/
public class RegexTest3 {public static void main(String[] args) {checkPhone();}public static void checkPhone() {while (true) {System.out.println("请您输入您的电话号码(手机|座机):");Scanner sc = new Scanner(System.in);String phone = sc.nextLine();if (phone.matches("(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})")) {System.out.println("您输入的号码格式正确~~~");break;} else {System.out.println("您输入的号码格式不正确");}}}public static void checkEmail() {while (true) {System.out.println("请您输入您的邮箱:");Scanner sc = new Scanner(System.in);String phone = sc.nextLine();if (phone.matches("\\w{2,}@\\w{2,20}(\\.\\w{2,10}){1,2}")) {System.out.println("您输入的邮箱格式正确~~~");break;} else {System.out.println("您输入的邮箱格式不正确");}}}
}

2.4 用于查找信息

在一段文本中查找满足要求的内容

需求:

请把下面文本中的电话、邮箱、座机号码、热线都爬取出来

代码实现
package Advanced.c_regex;import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** 目标:掌握使用正则表达式查找内容*/
public class RegexTest4 {public static void main(String[] args) {method1();}// 需求1:从一下内容中爬取出:手机、邮箱、座机、400电话等信息public static void method1() {String data = "来黑马程序员学习Java,\n" +"电话:1866668888,18699997777,\n" +"或者联系邮箱:boniu@itcast.cn,\n" +"座机电话:01036517895,010-98951256\n" +"邮箱:bozai@itcast.cn,\n" +"邮箱:dlei0009@163.com,\n" +"热线电话:400-618-9090,400-618-4000,400618400,4006189090";// 1. 定义爬取规则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);}}
}

2.5 用于搜索替换、分割内容

正则表达式用于搜索替换、分割内容,需要结合 String 提供的如下方法完成:

方法名说明
public String replaceAll(String regex, String newStr)按照正则表达式匹配的内容进行替换
public String[] split(String regex)按照正则表达式匹配的内容进行分割字符串,返回一个字符串数组
代码演示
package Advanced.c_regex;import java.util.Arrays;/*** 目标:掌握使用正则表达式做搜索替换、内容分割*/
public class RegexTest5 {public static void main(String[] args) {// 1. public String replaceAll(String regex, String newStr):按照正则表达式匹配的内容进行替换// 需求1:请把 古力娜扎ai888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴,中间的非中文字符替换成 ”-“String s1 = "古力娜扎ai888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴";System.out.println(s1.replaceAll("\\w+", "-")); // 古力娜扎-迪丽热巴-马尔扎哈-卡尔扎巴// 需求2(拓展):某语言系统,收到一个口吃的人说”我我我喜欢编编编编编编程!“,需要优化成”我喜欢编程“String s2 = "我我我喜欢编编编编编编程!";/*** (.)一组,匹配任意字符的* \\1:为这个组声明一个组号:1号* +:声明必须是重复的字* $1:可以去到第1组代表的那个重复的字*/System.out.println(s2.replaceAll("(.)\\1+", "$1")); // 我喜欢编程!// 2. public String[] split(String regex):按照正则表达式的内容进行分割字符串,返回一个字符串数组// 需求1:请把 古力娜扎ai888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴 中的人名获取出来String s3 = "古力娜扎ai888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴";String[] names = s3.split("\\w+");System.out.println(Arrays.toString(names)); // [古力娜扎, 迪丽热巴, 马尔扎哈, 卡尔扎巴]}
}

3. 异常

3.1 认识异常

3.1.1 什么是异常?

异常就是代表程序出现的问题

3.1.2 异常的体系

Error:代表的系统级别错误(属于严重问题),也就是说系统一旦出现问题,sun 公司会把这些问题封装成 Error 对象给出来,说白了,Error 是给 sun 公司自己用的,不是给我们程序员用的,因此我们开发人员不用管它

Exception:叫异常,它代表的才是我们程序员可能出现的问题,所以,我们程序员通常会用 Exception 以及它的孩子来封装程序出现的问题

  • 运行时异常:RuntimeException 及其子类,编译阶段不会出现错误提醒,运行时出现异常(如:数组索引越界异常)
  • 编译时异常:编译阶段就会出现错误提醒的(如:日期解析异常)
3.1.3 抛出异常(throws)
  • 在方法上使用 throws 关键字,可以将方法内部出现的异常抛出去给调用者处理
方法 throws 异常1, 异常2, 异常3...{...
}
3.1.4 捕获异常(try…catch)
  • 直接捕获程序出现的异常
try{// 监视可能出现异常的代码!
} catch (异常类型1 变量) {// 处理异常
} catch (异常类型2 变量) {// 处理异常
}...
代码演示
package Advanced.d_exception;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;/*** 目标:认识异常*/
public class ExceptionTest1 {public static void main(String[] args) throws ParseException {
//        Integer.valueOf("abc");//        int[] arr = {11,22,33};
//        System.out.println(arr[5]);//        try {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date d = sdf.parse("2023-11-11 10:24");System.out.println(d);
//        } catch (ParseException e) {
//            e.printStackTrace();
//        }}
}

3.2 自定义异常

  • Java 无法为这个世界上全部的问题都提供异常类来代表,如果企业自己的某种问题,想通过异常来表示,以便用异常来管理该问题,那就需要自己来定义异常类了
3.2.1 自定义异常的种类
自定义运行时异常
  • 定义一个异常类继承 RuntimeException
  • 重写构造器
  • 通过 throw new 异常类(xxx) 来创建异常对象并抛出
  • 编译阶段不报错,提醒不强烈,运行时才可能出现!!!
自定义编译时异常
  • 定义一个异常类继承 Exception
  • 重写构造器
  • 通过 throw new 异常类(xxx) 来创建异常对象并抛出
  • 编译阶段就报错,提醒更加强烈!
3.2.2 异常有什么作用?
  1. 异常是用来查询系统 Bug 的关键参考信息
  2. 异常可以作为方法内部的一种特殊返回值,以便通知上层调用者底层的执行情况
代码演示
  • AgeIllegalRuntimeException.java
package Advanced.d_exception;// 1. 必须让这个类继承自RuntimeException,才能成为一个运行时异常类
public class AgeIllegalRuntimeException extends RuntimeException {public AgeIllegalRuntimeException() {}public AgeIllegalRuntimeException(String message) {super(message);}
}
  • AgeIllegalException.java
package Advanced.d_exception;// 1. 必须让这个类继承自Exception,才能成为一个编译时异常类
public class AgeIllegalException extends Exception {public AgeIllegalException() {}public AgeIllegalException(String message) {super(message);}
}
  • ExceptionTest2.java
package Advanced.d_exception;/*** 目标:掌握自定义异常,以及异常的作用*/
public class ExceptionTest2 {public static void main(String[] args) {// 需求:保存一个合法的年龄try {saveAge(160);System.out.println("底层执行成功!");} catch (Exception e) {e.printStackTrace();System.out.println("底层出现了bug!");}try {saveAge2(195);System.out.println("saveAge2底层执行是成功的!");} catch (AgeIllegalException e) {e.printStackTrace();System.out.println("saveAge2底层执行是出现bug的!");}}public static void saveAge(int age) {if (age > 0 && age < 150) {System.out.println("年龄被成功保存:" + age);} else {// 用一个异常对象封装这个问题// throw 抛出去这个异常对象throw new AgeIllegalRuntimeException("/age is illegal, your age is " + age);}}public static void saveAge2(int age) throws AgeIllegalException {if (age > 0 && age < 150) {System.out.println("年龄被成功保存:" + age);} else {// 用一个异常对象封装这个问题// throw 抛出去这个异常对象// throws 用在方法上,抛出方法内部的异常throw new AgeIllegalException("/age is illegal, your age is " + age);}}
}

3.3 异常的处理

3.3.1 开发中对于异常的常见处理方式

3.3.2 抛出异常(throws)
  • 在方法上使用 throws 关键字,可以将方法内部出现的异常抛出去给调用者处理
方法 throws 异常1, 异常2, 异常3...{...
}
// 推荐方式
方法 throws Exception{
}
// Exception代表可以捕获一切异常
3.3.3 捕获异常(try…catch)
  • 直接捕获程序出现的异常
try{// 监视可能出现异常的代码!
} catch (异常类型1 变量) {// 处理异常
} catch (异常类型2 变量) {// 处理异常
}...
// 推荐方式
try {// 可能出现异常的代码!
} catch (Exception e) {e.printStackTrace(); // 直接打印异常对象的信息
}
// Exception代表可以捕获一切异常
代码演示
  • ExceptionTest3_2.java
package Advanced.d_exception;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;/*** 目标:异常的处理*/
public class ExceptionTest3_2 {public static void main(String[] args) {try {test1();} catch (Exception e) {System.out.println("您要找的文件不存在!");e.printStackTrace(); // 打印出这个异常对象的信息,记录下来}}public static void test1() throws Exception {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date d = sdf.parse("2023-11-11 10:24:11");System.out.println(d);test2();}public static void test2() throws Exception {// 读取文件的FileInputStream is = new FileInputStream("D:/meinv.png");}
}
  • ExceptionTest4.java
package Advanced.d_exception;import java.util.Scanner;/*** 目标:掌握异常的处理方式:捕获异常,尝试修复*/
public class ExceptionTest4 {public static void main(String[] args) {// 需求:调用一个方法,让用户输入一个合适的价格返回为止// 尝试修复while (true) {try {System.out.println(getMoney());break;} catch (Exception e) {System.out.println("请您输入合法的数字!!!");}}}public static double getMoney() {Scanner scanner = new Scanner(System.in);while (true) {System.out.println("请您输出合适的价格:");double money = scanner.nextDouble();if (money >= 0) {return money;} else {System.out.println("您输入的价格是不合适的!");}}}
}

http://www.lryc.cn/news/609500.html

相关文章:

  • 深入浅出 RabbitMQ:简单队列实战指南
  • 【Linux指南】软件安装全解析:从源码到包管理器的进阶之路
  • 小杰数据结构(five day)——知人者智,自知者明。
  • WPF 按钮背景色渐变
  • 飞算 JavaAI:给需求分析装上 “智能大脑“
  • VPS云服务器Linux性能分析与瓶颈解决方案设计
  • 机器学习 决策树案例电信用户流失
  • 豆包新模型+PromptPilot深度评测:提示词工程的智能化突破
  • Chrontel 【CH7104B-BF】CH7104B HDMI to HDTV/VGA Converter
  • SJW-app-1
  • 力扣热题100——双指针
  • Android GPU测试
  • 豹女篇章-人形态技能加攻速
  • 数据离不开哈希
  • 【Linux | 网络】网络层(IP协议、NAT技术和ICMP协议)
  • 【前端:Html】--1.3.基础语法
  • 【人工智能99问】什么是Post-Training,包含哪些内容?(19/99)
  • 3.JVM,JRE和JDK的关系是什么
  • Linux 系统重置用户密码指南
  • 【09】C++实战篇——C++ 生成静态库.lib 及 C++调用lib,及实际项目中的使用技巧
  • vue3指定设置了dom元素的ref但是为null问题
  • 大模型 与 自驾 具身 3D世界模型等相关知识
  • 华为OD机考2025C卷 - 最小矩阵宽度(Java Python JS C++ C )
  • vim 组件 使用pysocket进行sock连接
  • 408数据结构排序部分知识的复盘:从原理到辨析的系统化梳理
  • 抗辐照DCDC与MCU在核环境监测设备中的集成应用
  • 远程测控终端RTU:工业物联的“神经末梢”与远程操控核心
  • CVPR论文解析:告别Janus问题,text-to-3D更一致!
  • 5G专网与SD-WAN技术融合:某饮料智能工厂网络架构深度解析
  • Planner 5D v2.29.0 安卓高级解锁版,手机3D家装,全套家具免费