文章目录
1. Arrays数组工具类
作用: 提供数组相关操作的工具类
1.1 基本使用
- 常见方法
方法名 说明 public static String toString(类型[] a) 返回指定数组的内容的字符串表示形式 public static 类型[] copyOfRange(类型[] arr, 起始索引,结束索引) 拷贝数组(指定范围),并将得到的新数组返回 public static 类型[] copy(类型[] arr,int newLength) 拷贝数组(指定新数组的长度),并将得到的新数组返回 public static setAll(类型[] array,Function generator) 把数组中的原数据改为新数据支持 int[] -> int[] ,double[],long[] 引用数据类型[] -> 引用数据类型[] public static void sort(类型[] a) 对数组进行排序(默认升序,自定义数据类型需要手动指定排序规则) public static int binarySearch(类型[] a, 类型 key) 利用二分查找返回指定元素的索引(要求数组有序,找不到返回负数) int[] arr = {11,22,33,44,55,66}; // public static String toString(类型[] a) 返回指定数组的内容的字符串表示形式 System.out.println(Arrays.toString(arr)); // public static 类型[] copyOfRange(类型[] arr, 起始索引,结束索引) 拷贝数组(指定范围),并将得到的新数组返回 含头不含尾(左闭右开) int[] newArr = Arrays.copyOfRange(arr, 1, 5); System.out.println(Arrays.toString(newArr)); // public static 类型[] copyOf(类型[] arr,int newLength) 拷贝数组(指定新数组的长度),并将得到的新数组返回 int[] newArr2 = Arrays.copyOf(arr, 20); //int[] newArr2 = Arrays.copyOf(arr, arr.length); System.out.println(Arrays.toString(newArr2));
public class Demo1 { // public static setAll(类型[] array,Function generator) public static void main(String[] args) { // method1(); // method2(); // method3(); method4(); } /* 包装类型和 String类型转换 包装类型转String toString() String.valueOf(数值) String转数值 Integer.parseInt(字符串) Integer.valueOf(字符串) public static <T> void setAll(T[] array, IntFunction<? extends T> generator) 参数一: 新数组 参数二: 指定数据转换规则 Arrays.setAll(newArr, i -> arr[i].toString()); i 依次表示原数组中的索引 arr[i].toString() Integer类型的数据转换为String类型后 添加到新数组中 */ private static void method4() { Integer[] arr = {11,22,33,44,55,66}; String[] newArr = new String[arr.length]; Arrays.setAll(newArr, i -> arr[i].toString()); for (int i = 0; i < newArr.length; i++) { String s = newArr[i]; System.out.println(s.length()); } } /* int[] => long[] public static void setAll(long[] array, IntToLongFunction generator) 参数一: 新数组 参数二: 指定存入新数组数据的规则 示例: Arrays.setAll(newArr,i -> arr[i]); i 依次表示元素数组的索引 arr[i] 把什么样的数据存到新数组 */ private static void method3() { int[] arr = {11,22,33,44,55,66,77}; long[] newArr = new long[arr.length]; Arrays.setAll(newArr,i -> arr[i]); System.out.println(Arrays.toString(newArr)); } /* int[] => double[] setAll(double[] array, IntToDoubleFunction generator) 参数一: double类型的数组 参数二: 指定修改数据的规则 示例: Arrays.setAll(newArr,i -> arr[i]); i依次表示原数组中的每一个索引 arr[i] 把什么样的数据存到新数组 */ private static void method2() { int[] arr = {11,22,33,44,55,66,77}; double[] newArr = new double[arr.length]; // 创建了一个double类型的数组,和原数组的长度相同 Arrays.setAll(newArr,i -> arr[i]); System.out.println(Arrays.toString(newArr)); } /* int[] => int[] Arrays.setAll(int[],IntUnaryOperator generator) 参数一: 新数组 参数二: 数据转换规则 示例: Arrays.setAll(newArr,i -> arr[i] + 1); lambda表达式涵义: i依次表示原数组中的每一个索引, arr[i] + 1 将结果装到新数组中 */ private static void method1() { int[] arr = {11,22,33,44,55,66,77}; int[] newArr = new int[arr.length]; // 创建了一个新数组 长度和原数组相同 // int[] => int[] Arrays.setAll(新数组,数据转换规则) Arrays.setAll(newArr, new IntUnaryOperator() { @Override public int applyAsInt(int operand) { // 底层代码会遍历原数组 参数operand 依次表示每一个索引 // 返回值 新数组中的每一个元素 return arr[operand] + 1; } }); // lambda表达式: i表示原数组中的每一个索引, arr[i] + 1 把什么样的数据放到新数组中 Arrays.setAll(newArr,i -> arr[i] + 1); System.out.println(Arrays.toString(newArr)); } }
sort基本数据类型数组排序
sort方法操作基本数据类型的数据只能升序
手动实现数组反转
数组反转思路一
数组反转思路二
public class Demo2 { public static void main(String[] args) { // 演示Arrays.sort(类型[] 数组名) 默认使用升序排序 int[] arr = {90, 79, 100, 11, 200}; Arrays.sort(arr); // 升序 reverse1(arr); // 反转 System.out.println(Arrays.toString(arr)); // 基本数据类型的数组 使用Arrays.sort方法只能是升序, 如果实现降序 // 方案一: Arrays.sort升序,反转数组 自己实现 // 方案二: 使用其他排序算法手动实现 } /* 实现数组中数据反转 核心思路首尾互换 第一个和最后一个交换 第二个和倒数第二个交换 第三个和倒数第三个交换 .... */ // [11, 79, 90, 100, 200] => [200,79,90,100,11] => [200,100,90,79,11] public static void reverse(int[] arr) { for (int i = 0; i < arr.length / 2; i++) { int temp = arr[i]; arr[i] = arr[arr.length - 1 - i]; arr[arr.length - 1 - i] = temp; } } public static void reverse1(int[] arr) { // 定义两个变量分别记录第一个和最后一个位置的索引 // int start = 0; // int end = arr.length - 1; // int start = 0 ,end = arr.length - 1; for (int start = 0, end = arr.length - 1; start < end; start++, end--) { int temp = arr[start]; arr[start] = arr[end]; arr[end] = temp; } } }
1.2 指定排序规则方式一
- 自定义的类要想排序必须指定排序规则
1.2.1 步骤
- 自定义类实现Comparable接口,泛型与当前类一样
- 重写
comparTo
方法:public int comparTo
(对象)
- 方法返回值约定
- 如果左边对象 大于 右边对象, 返回正整数
- 如果左边对象 小于 右边对象, 返回负整数
- 如果左边对象 等于 右边对象, 返回0
1.2.2 示例
public class Student implements Comparable<Student>{ private String name; private double height; private int age; @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", height=" + height + ", age=" + age + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String name, double height, int age) { this.name = name; this.height = height; this.age = age; } public Student() { } @Override public int compareTo(Student o) { // 按学生的年龄升序排序 // this // o // 约定: // 如果认为左边的对象 大于 右边的对象 返回正整数 // 如果认为左边的对象 小于 右边的对象 返回负整数 // 如果认为左边的对象 等于 右边的对象 返回0 return o.age - this.age; } }
// 自定义类型数组要想使用Arrays.sort方法排序,必须要指定排序规则 public static void main(String[] args) { Student stu1 = new Student("蜘蛛精", 169.5, 23); Student stu2 = new Student("紫霞", 163.8, 26); Student stu3 = new Student("紫霞", 163.8, 26); Student stu4 = new Student("至尊宝", 167.5, 24); Student[] students = {stu1, stu2, stu3, stu4}; Arrays.sort(students); System.out.println(Arrays.toString(students)); }
1.2.3 comparTo
方法理解
1.2.4 细节: JDK
提供的部分类如何排序
- String、Integer、Double、Character、Boolean…等类型的数组为什么可以直接排序
- 它们都实现了Comparable接口,并指定了排序规则
- String: 按照码表(ASCII)的顺序逐个比较排序,中文按照Unicode码表排序
zhangsan lisi wangwu zhoaliu -> lisi wangwu zhangsan zhoaliu
- Character: 也是按照码表排序
- 数字: 按自然数排序
- Boolean: false在前,true在后
Integer[] arr = {78,67,11,100}; Arrays.sort(arr); System.out.println(Arrays.toString(arr)); System.out.println("=================="); Boolean[] strArr = {true,false,true,false}; Arrays.sort(strArr); System.out.println(Arrays.toString(strArr)); System.out.println("=================="); String[] strArr = {"zhangsan","lisi","wangwu","zhaoliu"}; Arrays.sort(strArr); System.out.println(Arrays.toString(strArr));
1.2.5 综合练习
- 需求: 年龄降序;如果年龄相同,按身高降序;如果身高也相同,按姓名降序
public class Student implements Comparable<Student>{ private String name; private double height; private int age; public Student() { } public Student(String name, double height, int age) { this.name = name; this.height = height; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", height=" + height + ", age=" + age + '}'; } @Override public int compareTo(Student o) { // 按学生的年龄降序排序 //this //o int result = o.age-this.age; //年龄相同,按身高升序 result = result == 0 ? Double.compare(this.height,o.height) : result; //身高相同,按姓名升序 result = result == 0 ? this.name.compareTo(o.name) :result; return result; } }
public class Demo { public static void main(String[] args) { Student stu1 = new Student("zhangsan",169.5,23); Student stu2 = new Student("lisi",163.8,26); Student stu3 = new Student("wangwu",178.9,26); Student stu4 = new Student("zhoaliu",163.8,26); Student stu5 = new Student("zhouqi",167.5,24); Student[] students = {stu1,stu2,stu3,stu4,stu5}; Arrays.sort(students); System.out.println(Arrays.toString(students)); } }
1.3 指定排序规则方式二
1.3.1 步骤
- 使用带有Comparator参数的sort方法,传递匿名内部类或者lambda表达式
- 自动重写compare方法: public int compar(对象1,对象2)
- 方法返回值约定
- 如果左边对象 大于 右边对象, 返回正整数
- 如果左边对象 小于 右边对象, 返回负整数
- 如果左边对象 等于 右边对象, 返回0
1.3.2 示例
Student stu1 = new Student("蜘蛛精", 169.5, 23);
Student stu2 = new Student("紫霞", 163.8, 26);
Student stu3 = new Student("紫霞", 163.8, 26);
Student stu4 = new Student("至尊宝", 167.5, 24);
Student[] students = {stu1, stu2, stu3, stu4};
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// 按身高降序
return Double.compare(o2.getHeight(),o1.getHeight());
}
});
System.out.println(Arrays.toString(students));
1.4 Arrays工具类小结
重点掌握,两种指定排序规则的方式
- 自定义类实现Comparable接口 ,重写comparTo方法
- 调用Arrays.sort(数组,Comparator接口的实现类对象)
- Comparator排序 比Comparable优先级更高
TreeSet
集合还会用到这两种方式
2. 正则表达式
什么是正则表达式: 就是由一些特定的字符组成,代表的是一个规则。
有什么用:
- 校验: 字符串校验(手机号,邮箱,
- 查找: 从一段文本中查找满足要求的内容
- 替换: 按照正则表达式匹配的内容进行替换
- 切割: 按照正则表达式匹配的内容切割字符串
2.1 初体验
// 体验正则表达式 // 需求: 校验QQ号码是否正确,要求全部是数字,长度是(6~20)之间,不能以0开头 public class Demo { public static void main(String[] args) { System.out.println(checkQQ(null)); // null System.out.println(checkQQ("1")); // 长度不满足条件 System.out.println(checkQQ("023123123")); // 以0开头 System.out.println(checkQQ("23a1231b23")); // 不全是数字 System.out.println(checkQQ("23123123")); // 满足条件 System.out.println("================="); System.out.println(checkQQRegex(null)); // null System.out.println(checkQQRegex("1")); // 长度不满足条件 System.out.println(checkQQRegex("023123123")); // 以0开头 System.out.println(checkQQRegex("23a1231b23")); // 不全是数字 System.out.println(checkQQRegex("23123123")); // 满足条件 } // 使用传统方式校验qq号,返回qq号是否符合要求 public static boolean checkQQ(String qq){ // 如果qq为null 或者 qq以0开头 或者 qq号的长度不在6~20之间 if (qq == null || qq.startsWith("0") || qq.length() < 6 || qq.length() > 20){ return false; } // 方法如果能走到这,说明: qq号不为null 不以0开头 长度在6~20之间 // 遍历字符串,对每一个字符做判断,是否为数字 for (int i = 0; i < qq.length(); i++) { char ch = qq.charAt(i); // 通过索引获取该位置的字符 if (ch <'0' || ch > '9'){ return false; // 只要有一个字符不是数字就返回false } } // 方法如果能走到这里 说明条件都满足 return true; } // 使用正则表达式校验qq号 public static boolean checkQQRegex(String qq){ return qq != null && qq.matches("[1-9]\\d{5,19}"); } }
2.2 书写规则和校验
- String类中提供的字符串校验的方法
public boolean matches(String regex) 判断字符串是否匹配正则表达式,匹配返回true,不匹配返回false。
- 正则表达式的规则
- 字符类型(只匹配单个字符)
[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次
- 演示
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,除了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)+")); }
2.3 校验练习
校验手机|座机,邮箱
- 手机|座机:
- 手机要求: 1开头,第二位(3~9),总计11位
- 座机: 区号-号码: 区号要求0开头总计3 ~ 8位;号码要求首位不能是0,总计5 ~ 20位
- 邮箱:
- xxxx@139.com
- xxxxx@qq.com
- xxxxx@itcast.com.cn
- @符号前: 数字字母下划线 至少2位
- 必须有一个@符号
- @符号后: 2~20个数字或字母 . 2~10个字母或数字 支持二级域名
- 时间: yyyy-MM-dd HH:mm:ss
- 不考虑闰年,公元前
public class Demo { public static void main(String[] args) { System.out.println("===========phone==========="); checkPhone("18877029441"); checkPhone("023-40491888"); System.out.println("===========email==========="); checkEmail("1448880888@qq.com"); checkEmail("yishooox33@163.com"); checkEmail("admin@www.baidu.com"); System.out.println("===========time==========="); checkTime("2023-04-01 17:21:33"); } //验证手机号 public static void checkPhone(String phone){ /* 手机|座机: 手机要求:1开头,第二位(3~9),总计11位 座机: 区号-号码: 区号要求0开头总计3~8位;号码要求首位不能是0,总计5~20位 */ String phoneRegex = "(1[3-9]\\d{9})|0\\d{2,7}-[1-9]\\d{4,19}"; System.out.println(phone.matches(phoneRegex)); } //验证邮箱 public static void checkEmail(String email){ /* - xxxx@139.com - xxxxx@qq.com - xxxxx@itcast.com.cn - @符号前: 数字字母下划线 至少2位 - 必须有一个@符号 - @符号后: 2~20个数字或字母 . 2~10个字母或数字 支持二级域名 */ String emailRegex = "\\w{2,}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,10}){1,2}"; System.out.println(email.matches(emailRegex)); } // public static void checkTime(String time){ /* 时间: yyyy-MM-dd HH:mm:ss - 不考虑闰年,公元前 */ // 年 大月十位为0 十位为1 天十位为0 十位为1、2 十位为3 小月十位为0 1 天十位为0 十位为1、2 十位为3 天十位为0 十位为1 2 String regex = "\\d{4}-((((0[13578])|(1[02]))-((0[1-9])|([12]\\d)|(3[01])))|(((0[469])|(11))-((0[1-9])|([12]\\d)|(30)))|(02-((0[1-9])|(1\\d)|(2[0-8]))))" + "\\s(([0-1]\\d)|(2[0-4]))(:([0-5]\\d)){2}"; System.out.println(time.matches(timeRegex)); } }
2.4 查找
Pattern中的方法 说明 public static Pattern compile(String regex) 将正则表达式封装为Pattern对象 public Matcher matcher(CharSequence input) 过pattern对象去获取查找内容的匹配器对象。
Matcher中的方法 说明 public boolean find() 查找一次,找到了返回true,没找到返回false public String group() 获取这一次找到的内容 /** * 目标:掌握使用正则表达式查找内容。 */ public class Demo { 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,4006184000,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 替换,切割
Pattern中的方法 说明 public static Pattern compile(String regex) 将正则表达式封装为Pattern对象 public Matcher matcher(CharSequence input) 过pattern对象去获取查找内容的匹配器对象。
Matcher中的方法 说明 public boolean find() 查找一次,找到了返回true,没找到返回false public String group() 获取这一次找到的内容 /** * 目标:掌握使用正则表达式查找内容。 */ public class Demo { 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,4006184000,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); } } }
3.目标总结
- 使用今天总结
JDK8
技巧,做一下作业题- Arrays工具重点掌握排序: Comparable,Comparator
- 正则表达式
- 能做什么: 校验,查找,替换,切割
- 规则: 熟悉
预习内容
- 异常
- 集合(
JavaSE
重点)