Java常用类
目录
- 常用类
- 字符串相关的类:String
- 创建字符串对象的2种方法
- String常见面试题
- String类常用API-字符串内容比较
- String类常用API-遍历、替换、截取、分割操作
- String案例操作
- ArrayList
- 集合
- ArrayList集合(泛型)
- ArrayList集合案例
- 1.遍历并删除元素值
- 2.存储自定义类型的对象
- 3.元素搜索
- Object
- Objects
- StringBuilder
- Math
- System
- BigDecimal
- 日期时间
- Date
- SimpleDateFormat类作用
- Calendar日历
- JDK8新增曰期类
- LocalDate、LocalTime、LocalDateTime
- Instant时间戳(时刻)
- DateTimeFormatter
- Duration/Period
- ChronoUnit
- 包装类
- 正则表达式
- Arrays类
- 常见算法
- 选择排序
- 二分查找(选择排序的改进)
- Lambda表达式
- Lambda
- Lambda简化常见函数式接口
- Lambda省略规则
- 字符串相关的类:String
常用类
字符串相关的类:String
-
String的特性
- String类:代表字符串。Java程序中的所有字符串字面值(如 "abc")都作为此类的实例实现。
- String是一个final类,代表不可变的字符序列。
- 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
- String对象的字符内容是存储在一个字符数组value[]中的。
/* string:字符串,使用一对""引起来表示。 1.String声明为finaL的,不可被继承 2.String实现了Serializable接口:表示字符串是支持序列化的。 实现了Comparable接口:表示String可以比较大小 3.String内部定义了final char[] value用于存储字符串数据 4.String:代表不可变的字符序列。简称:不可变性。 体现:1.当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。 2.当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值 3.当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值 5.通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。 6.字符串常量池中是不会存储相同内容的字符串的。 */ String s1="abc";//字面量的定义方式 String s2="abc"; //比较s1和s2的地址值 System.out.println(s1==s2);//true s1="hello"; System.out.println(s1);//hello System.out.println(s2);//abc System.out.println("*************************"); String s3="abc"; String s4 = s3.replace("a", "m");//replace替换 System.out.println(s3);//abc System.out.println(s4);//mbc System.out.println("*************************");
-
String对象的创建
public class Person { String name; int age; public Person(String name, int age) { this.name = name; this.age = age; } }
/* String的实例化方式: 方式一:通过字面量定义的方式 方式二:通过new +构造器的方式 面试题: String s = new String("abc");方式创建对象,在内存中创建了几个对象? 两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据: "abc" */ //通过字面量定义的方式:此时的s1和s2的数据javaSE声明在方法区中的字符串常量池中。 String s1="javaSE"; String s2="javaSE"; //通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。 String s3 = new String("javaSE"); String s4 = new String("javaSE"); System.out.println(s1==s2);//true System.out.println(s1==s3);//false System.out.println(s1==s4);//false System.out.println(s3==s4);//false System.out.println("*************************"); Person p1 = new Person("Tom",12); Person p2 = new Person("Tom",12); System.out.println(p1.name.equals(p2.name));//true System.out.println(p1.name==p2.name);//true System.out.println("*************************");
创建字符串对象的2种方法
-
方法一:直接使用“”定义。(推荐方式)
String name="javaSE";
-
方法二:通过String类的构造器创建对象。
//方式一:直接使用双引号得到字符串对象
String name="我爱中国";
System.out.println(name);
//方式二:
//1、public String():创建一个空白字符串对象,不含有任何内容﹑(几乎不用)
String s1=new String();//s1=""
System.out.println(s1);
//2、public String(String):根据传入的字符串内容,来创建字符串对象(几乎不用)
String s2=new String("我是中国人");
System.out.println(s2);
//3、public string(char[] c):根据字符数组的内容,来创建字符串对象
char[] chars={'a','b','中'};
String s3=new String(chars);
System.out.println(s3);
//4、public String(byte[] b):根据字节数组的内容,来创建字符串对象
byte[] bytes={97,98,99,65};
String s4=new String(bytes);
System.out.println(s4);
-
有什么区别吗?(面试常考)
- 以“”方式给出的字符串对象,在字符串常量池中存储,而且相同内容只会在其中存储一份。
- 通过构造器new对象,每new一次都会产生一个新对象,放在堆内存中。
String常见面试题
-
1.问题:下列代码的运行结果是,s1和s2各创建了几个对象?(答案:[1])
-
2.问题:下列代码的运行结果是?(答案:[2])
-
2.问题:下列代码的运行结果是?(答案:[3])
String类常用API-字符串内容比较
//1、正确登录名和密码
String okName="admin";
String okPassword="123";
//2、请您输入登录名称和密码
Scanner scanner = new Scanner(System.in);
System.out.println(" 登录名称:");
String name = scanner.next();
System.out.println("登录密码:");
String password = scanner.next();
//3、判断用户输入的登录名称和密码与正确的内容是否相等。
if (okName==name && okPassword==password){
System.out.println("登录成功");
}else {
System.out.println("用户名或密码错误");
}
结果:
登录名称:
admin
登录密码:
123
用户名或密码错误
结论:字符串的内容比较不适合用"==”比较。
- 字符串的内容比较:
- 推荐使用String类提供的“equals”比较:只关心内容一样即可
//4、忽略大小写比较内容的Api:一般用于比较验证码这样的业务逻辑
String sysCode="23AdFh";
String code1="23aDfH";
System.out.println(sysCode.equals(code1));//false
System.out.println(sysCode.equalsIgnoreCase(code1));//true忽略大小写
- 总结:
- 如果是字符串比较应该使用使用什么方式进行比较,为什么
- 使用String提供的equlas方法
- 只关心内容一样就返回true
- 开发中什么时候使用==比较数据
- 基本数据类型比较时使用
- 如果是字符串比较应该使用使用什么方式进行比较,为什么
String类常用API-遍历、替换、截取、分割操作
- String常用API
//1、public int length():获取字符串的长度
String name="我爱中国";
System.out.println(name.length());
//2、public char charAt(int index):获取某个索引位置处的字符
char c=name.charAt(1);
System.out.println(c);//爱
System.out.println("--------遍历字符串中的每个字符--------");
for (int i = 0; i < name.length(); i++) {
char c1 = name.charAt(i);
System.out.println(c1);
}
//3、public char[] toCharArray()::把字符串转换成字符数组
char[] chars=name.toCharArray();
System.out.println("--------遍历字符串中的每个字符--------");
for (int i = 0; i < name.length(); i++) {
char c2 = chars[i];
System.out.println(c2);
}
System.out.println("----------------");
//4、public String substring(int beginIndex, int endIndex) :包前不包后的
String name2="Java是最厉害的编程语言";
String rs1 = name2.substring(0, 9);
System.out.println(rs1);//Java是最厉害的
String rs2 = name2.substring(4, 9);
System.out.println(rs2);//是最厉害的
//5、public String substring(int beginIndex):从当前索引一直截取到末尾
String rs3 = name2.substring(4);
System.out.println(rs3);//是最厉害的编程语言
//6、public String replace(CharSequence target,CharSequence replacement):替换为
String name3 = "Java是最厉害的编程语言,Java无敌";
String rs4=name3.replace("Java","***");
System.out.println(rs4);//***是最厉害的编程语言,***无敌
//7、public boolean contains(CharSequence s):是否包含
System.out.println(name3.contains("Java"));//true
System.out.println(name3.contains("java"));//false
//8、public boolean startsWith ( string prefix):是否已它为开始
System.out.println(name3.startsWith("Java"));//true
System.out.println(name3.startsWith("Java是最厉害的"));//true
System.out.println(name3.startsWith("java是最厉害的2"));//false
//9、public String[] split(String s):按照某个内容把字符串分割成字符串数组返回。
String name4="Java,C#,C++";
String[] names=name4.split(",");
for (int i = 0; i < names.length; i++) {
System.out.println("选择了:"+names[i]);
//选择了:Java
//选择了:C#
//选择了:C++
}
String案例操作
String类开发验证码功能:
需求:
- 随机产生一个5位的验证码,每位可能是数字、大写字母、小写字母。
分析:
- 定义一个String类型的变量存储验a-zA-Z0-9之间的全部字符。
- 循环5次,随机一个范围内的索引,获取对应字符连接起来即可。
//1、定义可能出现的字符信息
String datas="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
//2、循环5次,每次生成一个随机的索引,提取对应的字符连接起来即可
String code="";
Random random=new Random();
for (int i = 0; i < 5; i++) {
//随机一个索引
int anInt = random.nextInt(datas.length());
char c = datas.charAt(anInt);
code+=c;
}
//3、输出字符串变量即可
System.out.println(code);
练习题1: (模拟用户登录)
//1、定义正确的登录名称和密码
String okLoginName="admin";
String okPassword="123";
//2、定义一个循环,循环3次,让用户登录
Scanner scanner = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.println("请您输入登录名称:");
String loginName = scanner.next();
System.out.println("请您输入登录密码:");
String password = scanner.next();
//3、判断登录是否成功!
if (okLoginName.equals(loginName)){
//4、判断密码是否正确
if (okPassword.equals(password)){
System.out.println("登录成功");
break;
}else {
System.out.println("登录密码错误"+",您还剩余"+(3-i)+"次机会");
}
}else {
System.out.println("登录名称错误"+",您还剩余"+(3-i)+"次机会");
}
}
练习题2: (手机号码屏蔽)
需求:
- 以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽,最终效果为:176****1111
分析:
- 键盘录入一个字符串,用Scanner 实现。
- 截取字符串前三位,截取字符串后四位。
//1、键盘录入一个手机号码
Scanner scanner = new Scanner(System.in);
System.out.println("请您输入您的手机号码:");
String tel = scanner.next();
//2、截取号码的前三位,后四位 17612341111
String before = tel.substring(0, 3);//0 1 2
String after = tel.substring(7);//从索引7开始截取到手机号码的末尾
String s=before+"****"+after;
System.out.println(s);
ArrayList
集合
- 集合是与数组类似,也是一种容器,用于装数据的。
- 数组定义完成并启动后,类型确定、长度固定。
- 特点:
- 集合的大小不固定,启动后可以动态变化,类型也可以选择不固定。
- 集合非常适合做元素个数不确定,且要进行增删操作的业务场景。
- 集合的提供了许多丰富、好用的功能,而数组的功能很单一。
总结:
- 数组和集合的元素存储的个数问题?
- 数组定义后类型确定,长度固定
- 集合类型可以不固定,大小是可变的。
- 数组和集合适合的场景
- 数组适合做数据个数和类型确定的场景
- 集合适合做数据个数不确定,且要做增删元素的场景
-
ArrayList集合
ArrayList是集合中的一种,它支持索引。
-
ArrayList集合的对象获取
- ArrayList集合添加元素的方法
//1、创建ArrayList集合的对象
ArrayList list = new ArrayList();
//2、添加数据
list.add("Java");
list.add("MySQL");
list.add(23);
list.add(false);
System.out.println(list.add("Java"));//true
System.out.println(list);//[Java, MySQL, 23, false, Java]
//3、给指定索引位置插入元素
list.add(1,"C++");
System.out.println(list);//[Java, C++, MySQL, 23, false, Java]
ArrayList集合(泛型)
泛型概述
- ArrayList
:其实就是一个泛型类,可以在编译阶段约束集合对象只能操作某种数据类型。
举例:
- ArrayList
:此集合只能操作字符串类型的元素 - ArrayList
:此集合只能操作整数类型的元素
ArrayList集合常用方法:
注意:集合中只能存储引用类型,不支持基本数据类型。
ArrayList list = new ArrayList<>();
list.add("Java");
list.add("MySQL");
list.add("HTML");
list.add("C++");
//1、public E get(int index):获取某个索引位置处的元素值
String e=list.get(3);
System.out.println(e);//C++
//2、public int size():获取集合的大小(元素个数)
System.out.println(list.size());//4
//3、完成集合的遍历
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//4、public E remove(int index):删除某个索引位置处的元素值,并返回被删除的元素值
System.out.println(list);//[Java, MySQL, HTML, C++]
String e2=list.remove(2);
System.out.println(e2);//HTML
System.out.println(list);//[Java, MySQL, C++]
//5、public boolean remove(Object o):直接删除元素值,删除成功返回true,删除失败返回false
//只会删除第一次出现的这个元素值,后面的不删除(元素有重复的情况)
System.out.println(list.remove("Java"));//true
System.out.println(list);//[MySQL, C++]
//6、public E set(int index,E element):修改某个索引位置处的元素值。
String e3=list.set(0,"C#");
System.out.println(e3);//MySQL
System.out.println(list);//[C#, C++]
ArrayList集合案例
1.遍历并删除元素值
需求:
- 某个班级的考试在系统上进行,成绩大致为:98,77,66,89,79,50,100
- 现在需要先把成绩低于80分以下的数据去掉。
分析:
- 定义ArrayList集合存储多名学员的成绩。
- 遍历集合每个元素,如果元素值低于80分,去掉它。
//目标:学习遍历并删除元素的正确方案。
//1、创建一个ArrayList集合存储一个班级学生的成绩
ArrayList scores = new ArrayList<>();
scores.add(98);
scores.add(77);
scores.add(66);
scores.add(89);
scores.add(79);
scores.add(50);
scores.add(100);
System.out.println(scores);
//2、把低于80分的成绩从集合中去掉。
//scores = [98,77,66,89,79,50,100]
// 0 1 2 3 4 5 6
/*
有毛病的代码!
*/
// for (int i = 0; i < scores.size(); i++) {
// int score=scores.get(i);
// if (score<80){
// //这个分数必须删除
// scores.remove(i);
// }
// }
// System.out.println(scores);//[98, 66, 89, 50, 100]
System.out.println("---------方法一------------");
for (int i = 0; i < scores.size(); i++) {
int score=scores.get(i);
if (score<80){
//这个分数必须删除
scores.remove(i);
i--;//删除成功后,必须退一步,这样可以保证下次回到这个位置,如此则不会跳过数据
}
}
System.out.println(scores);//[98, 89, 100]
System.out.println("-----------方法二-----------------");
for (int i = scores.size()-1; i >= 0; i--) {
int score=scores.get(i);
if (score<80){
//这个分数必须删除
scores.remove(i);
}
}
System.out.println(scores);//[98, 89, 100]
总结:
1、从集合中遍历元素,并筛选出元素删除它,应该怎么解决?
- 从集合后面遍历然后删除,可以避免漏掉元素。
2.存储自定义类型的对象
需求:
- 定义一个电影类,定义一个集合存储电影对象。
- 创建3个电影对象,封装相关数据,把3个对象存入到集合中去。
- 遍历集合中的3个对象,输出相关信息。
//目标:理解ArrayList集合存储自定义类型的对象。
//1、定义电影类。
//2、创建三个电影对象
//3、创建一个电影类型的ArrayList集合,存储三部电影对象
ArrayList movies = new ArrayList<>();
movies.add(new Movie("《肖生克的救赎》",9.7,"罗宾斯"));
movies.add(new Movie("《霸王别姬》",9.6,"张国荣、张丰毅"));
movies.add(new Movie("《阿甘正传》",9.5,"汤姆.汉克斯"));
System.out.println(movies);
//4、遍历电影类型的集合中的每个电影对象。访问它的信息即可。
for (int i = 0; i < movies.size(); i++) {
//i = 0 1 2
Movie m = movies.get(i);
System.out.println("电影名称:"+m.getName());
System.out.println("电影得分:"+m.getScore());
System.out.println("电影主演:"+m.getActor());
System.out.println("--------------------");
}
3.元素搜索
需求:
- 后台程序需要存储如上学生信息并展示,然后要提供按照学号搜索学生信息的功能。
分析:
- 定义Student类,定义ArrayList集合存储如上学生对象信息,并遍历展示出来。
- 提供一个方法,可以接收ArrayList集合,和要搜索的学号,返回搜索到的学生对象信息,并展示。
- 使用死循环,让用户可以不停的搜索。
//1、定义学生类。
//2、创建学生对象封装学生对象
//把学生对象添加到集合中去。
ArrayList students = new ArrayList<>();
students.add(new Student("20180302","叶孤城",23,"护理一班"));
students.add(new Student("20180303","东方不败",23,"推拿二班"));
students.add(new Student("20180304","西门吹雪",26,"中药学四班"));
students.add(new Student("20180305","梅超风",26,"神经科2班"));
//3、遍历这些学生信息展示。
System.out.println("学号\t名称\t年龄\t班级");
for (int i = 0; i < students.size(); i++) {
Student s = students.get(i);
System.out.println(s.getStudentNumber()+"\t"+s.getName()+"\t"+s.getAge()+"\t"+s.getClassName());
}
//4、定义方法完成按照学号的搜索功能。
Scanner scanner = new Scanner(System.in);
while (true){
System.out.println("请您输入学号查询学生对象:");
String studyNumber = scanner.next();
//5、调用方法查询
Student s = getStudentById(students, studyNumber);
//6、判断s中是否存在学生对象地址
if (s==null){
System.out.println("对不起,查无此人");
}else {
System.out.println("您查询的学生信息如下:");
System.out.println(s.getStudentNumber()+"\t"+s.getName()+"\t"+s.getAge()+"\t"+s.getClassName());
}
}
}
public static Student getStudentById(ArrayList students,String studentNumber){
//1、遍历全部学生对象
for (int i = 0; i < students.size(); i++) {
Student s = students.get(i);
//2、询问当前遍历的这个学生对象的学号,是否是我们要找的学号
if (s.getStudentNumber().equals(studentNumber)){
//这个s代表的学生对象,就是我们要找的:返回它
return s;
}
}
//查无此人
return null;
Object
- Object类的作用
- 一个类要么默认继承了Object类,要么间接继承了Object类,Object类是Java中的祖宗类。
- object类的方法是一切子类都可以直接使用的,所以我们要学习Object类的方法。
- Object类的常用方法
- toString存在的意义
- 默认是打印当前对象的地址。
- 让子类重写,以便返回子类对象的内容。
- 父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息!!
- equals存在的意义
- 默认是与另一个对象比较地址是否一样
- 让子类重写,以便比较2个子类对象的内容是否相同。
- 父类equals方法存在的意义就是为了被子类重写,以便子类自己来定制比较规则。
Objects
- Objects的常用方法
String name="Java";
String name1="Java";
System.out.println(Objects.equals(name,name1));//true
String name=null;
System.out.println(Objects.isNull(name));//true
- 总结(对象进行内容比较的时候建议使用什么?为什么?)
- 建议使用Objects提供的equals方法。
- 比较的结果是一样的,但是更安全。
StringBuilder
- StringBuilder概述
- StringBuilder是一个可变的字符串类,我们可以把它看成是一个对象容器。
- 作用:提高字符串的操作效率,如拼接、修改等。
- StringBuilder构造器
- StringBuilder常用方法
StringBuilder sb = new StringBuilder();
sb.append("a");
sb.append(1);
sb.append(false);
System.out.println(sb);//a1false
StringBuilder sb1 = new StringBuilder();
//支持链式编程
sb1.append("我").append(20).append(1314);
System.out.println(sb1);//我201314
//反转
sb1.reverse().append("反转");
System.out.println(sb1);//413102我反转
System.out.println(sb1.length());//9
// 注意: StringBuilder只是拼接字符串的手段:效率好。
// 最终的目的还是要恢复成String类型。
StringBuilder sb2 = new StringBuilder();
sb2.append("123");
// 恢复成String
String rs=sb2.toString();
System.out.println(rs);//123恢复成String类型
- 总结(为什么拼接、反转字符串建议使用StringBuilder?)
- String :内容是不可变的、拼接字符串性能差。
- StringBuilder:内容是可变的、拼接字符串性能好、代码优雅。
- 定义字符串使用String
- 拼接、修改等操作字符串使用StringBuilder
Math
- 包含执行基本数字运算的方法,Math类没有提供公开的构造器。
- Math类的常用方法
//1.取绝对值:返回正数
System.out.println(Math.abs(10));//10
System.out.println(Math.abs(-10.3));//10.3
//2.向上取整:5
System.out.println(Math.ceil(4.0000001));//5.0
System.out.println(Math.ceil(4.0));//4.0
//3.向下取整:4
System.out.println(Math.floor(4.99999));//4.0
System.out.println(Math.floor(4.0));//4.0
//4.求指数次方
System.out.println(Math.pow(2,3));//8.0
//5.四舍五入 10
System.out.println(Math.round(4.49999));//4
System.out.println(Math.round(4.50001));//5
//随机数0-1之间的随机数(包前不包后)
System.out.println(Math.random());//0.0-1.0之间
//拓展: 3 - 9之间的随机数(0 - 6)+ 3
//[0 - 6] +3
int data=(int) (Math.random()*7)+3;
System.out.println(data);//9
System
- System类概述
- System的功能是通用的,都是直接用类名调用即可,所以System不能被实例化。
- System类的常用方法
//计算机认为时间有起源:返回1970-1-1 00:00:00走到此刻的总的毫秒值:时间毫秒值。
long time=System.currentTimeMillis();
System.out.println(time);
long starTime=System.currentTimeMillis();
//进行时间的计算:性能分析
for (int i = 0; i < 100000; i++) {
System.out.println("输出:"+i);
}
long endTime=System.currentTimeMillis();
System.out.println((endTime-starTime)/1000.0+"s");
//做数组拷贝(了解)
/*
arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
int length);
参数一:被拷贝的数组
参数二:从哪个索引位置开始拷贝
参数三:复制的目标数组
参数四:粘贴位置
参数五:拷贝元素的个数
*/
int[] arr1={10,20,30,40,50,60,70};
int[] arr2=new int[6];//[0, 0, 0, 0, 0, 0]==>[0, 0, 40, 50, 60, 0]
System.arraycopy(arr1,3,arr2,2,3);
System.out.println(Arrays.toString(arr2));//[0, 0, 40, 50, 60, 0]
BigDecimal
- BigDecimal作用
- 用于解决浮点型运算精度失真的问题
- 使用步骤
- 创建对象BigDecimal封装浮点型数据(最好的方式是调用方法)
- BigDecima常用API
//浮点型运算的时候直接+ * / 可能会出现数据失真(精度问题)。
System.out.println(0.09+0.01);
System.out.println(1.0-0.32);
System.out.println(1.015*100);
System.out.println(1.301/100);
System.out.println("------------------");
double a=0.1;
double b=0.2;
double c=a+b;
System.out.println(c);
System.out.println("------------------");
//包装浮点型数据成为大数据对象 BigDecimal
BigDecimal a1=BigDecimal.valueOf(a);
BigDecimal b1=BigDecimal.valueOf(b);
//加
BigDecimal c1=a1.add(b1);
//减
BigDecimal c2=a1.subtract(b1);
//乘
BigDecimal c3=a1.multiply(b1);
//除
BigDecimal c4=a1.divide(b1);
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println("------------------");
//目的:double
double rs1=c1.doubleValue();
double rs2=c2.doubleValue();
double rs3=c3.doubleValue();
double rs4=c4.doubleValue();
System.out.println(rs1);
System.out.println(rs2);
System.out.println(rs3);
System.out.println(rs4);
System.out.println("------------------");
//注意事项:BigDecimal是一定要精度运算的
BigDecimal a11=BigDecimal.valueOf(10.0);
BigDecimal b11=BigDecimal.valueOf(3.0);
//BigDecimal c11=a11.divide(b11);//3.33333333 会报错
/*
参数一:除数 参数二:保留小数位数 参数三:舍入模式
*/
BigDecimal c11=a11.divide(b11,2, RoundingMode.HALF_UP);//保留两位小数
System.out.println(c11);
日期时间
Date
- Date类概述
- Date类的对象在Java中代表的是当前所在系统的此刻日期时间。
-
Date类记录时间的2种形式
- 形式1:日期对象
//1、创建一个Date类的对象:代表系统此刻日期时间对象 Date date = new Date(); System.out.println(date);
- 形式2:时间毫秒值
- 指的是从1970年1月1日00:00:00走到此刻的总的毫秒数,应该是很大的
//2、获取当前时间毫秒值 long time= date.getTime(); System.out.println(time);
-
时间毫秒值->日期对象
- 案例
/*
请计算出当前时间往后走1小时121秒之后的时间是多少。
*/
//1、得到当前时间毫秒值
Date date1 = new Date();
System.out.println(date1);
//2、当前时间往后走1小时 121s
long time2=System.currentTimeMillis();
time2+=(60*60+121)*1000;
//3、把时间毫秒值转换成对应的日期对象
//第一种
Date date2 = new Date(time2);
System.out.println(date2);
//第二种
Date date3 = new Date();
date3.setTime(time2);
System.out.println(date3);
SimpleDateFormat类作用
- 可以对Date对象或时间毫秒值格式化成我们喜欢的时间形式。
- 也可以把字符串的时间形式解析成日期对象。
- SimpleDateFormat的构造器
- SimpleDateFormat的格式化方法
- 格式化的时间形式的常用的模式对应关系如下:
//1、日期对象
Date date = new Date();
System.out.println(date);//Wed Mar 23 15:44:06 CST 2022
//2、格式化这个日期对象〔指定最终格式化的形式):EEE(星期几) a(上午或下午)yyyy年MM月dd日 HH:mm:ss EEE a
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE a");
//3、开始格式化日期对象成为喜欢的字符串形式
String rs=sdf.format(date);
System.out.println(rs);//2022-03-23 15:44:06 星期三 下午
System.out.println("------------------");
//4、格式化时间毫秒值
//需求:请问121秒后的时间是多少
long time=System.currentTimeMillis()+121*1000;
String rs1=sdf.format(time);
System.out.println(rs1);//2022-03-23 15:46:07 星期三 下午
- SimpleDateFormat解析字符串时间成为日期对象
System.out.println("---------解析字符串时间---------");
//目标:学会使用SimpleDateFormat解析字符串时间成为日期对象。
//请计算出2022年03月23日 11:11:11,往后走2天14小时49分06秒后的时间是多少。
//1、把字符串时间拿到程序中来
String dateStr="2022年03月23日 11:11:11";
//2、把字符串时间解析成日期对象:形式必须与被解析时间的形式完全一样,否则运行时解析报错!
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date d = sdf1.parse(dateStr);
//3、往后走2天14小时49分06秒
long time1=d.getTime()+(2L*24*60*60+14*60*60+49*60+6)*1000;
//4、格式化这个时间毫秒值就是结果
System.out.println(sdf1.format(time1));//2022年03月26日 02:00:17
案例:
- 秒杀开始时间:2020年11月11日 00:00:00
- 秒杀结束时间:2020年11月11日 00:10:00
- 需求:
- 小贾下单并付款的时间为:2020年11月11日 00:03:47
- 小皮下单并付款的时间为:2020年11月11日 00:10:17
- 用代码说明这两位同学有没有参加上秒杀活动?
- 分析:
- 判断下单时间是否在开始到结束的范围内。
- 把字符串形式的时间变成毫秒值。
//1、开始 和 结束时间
String startTime="2020年11月11日 00:00:00";
String endTime="2020年11月11日 00:10:00";
//2、小贾 小皮
String xiaoJia="2020年11月11日 0:03:47";
String xiaoPi="2020年11月11日 0:10:17";
//3、解析他们的时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date startDate=sdf.parse(startTime);
Date endDate=sdf.parse(endTime);
Date jiaDate=sdf.parse(xiaoJia);
Date piDate=sdf.parse(xiaoPi);
//after(在...之后) before(在...之前)
if (jiaDate.after(startDate) && jiaDate.before(endDate)){
System.out.println("小贾秒杀成功,可以发货了");
}else {
System.out.println("小贾秒杀失败");
}
if (piDate.after(startDate) && piDate.before(endDate)){
System.out.println("小皮秒杀成功,可以发货了");
}else {
System.out.println("小皮秒杀失败");
}
Calendar日历
- Calendar代表了系统此刻日期对应的日历对象。
- Calendar是一个抽象类,不能直接创建对象。
- Calendar日历类创建日历对象的方法:
- Calendar常用方法
- 注意:calendar是可变日期对象,一旦修改后其对象本身表示的时间将产生变化。
//1、拿到系统此刻日历对象
Calendar cal = Calendar.getInstance();
System.out.println(cal);
//2、获取日历的信息
int year=cal.get(Calendar.YEAR);
System.out.println(year+"年");
int month=cal.get(Calendar.MONTH)+1;
System.out.println(month+"月");
int days=cal.get(Calendar.DAY_OF_YEAR);
System.out.println(days+"天");
//3、public void set(int field,int value):修改日历的某个字段信息。
//cal.set(Calendar.HOUR,12);
//System.out.println(cal);//HOUR=12
//4、public void add(int field,int amount):为某个字段增加/减少指定的值
//请问64天后是什么时间
cal.add(Calendar.DAY_OF_YEAR,64);
System.out.println(cal);
//5、public final Date getTime():拿到此刻日期对象。
Date date = cal.getTime();
System.out.println(date);
//6、public long getTimeInMillis():拿到此刻时间毫秒值
long time=cal.getTimeInMillis();
System.out.println(time);
JDK8新增曰期类
- 从Java8开始,java.time包提供了新的日期和时间API,主要涉及的类型有:
- 新增的API严格区分了时刻、本地日期、本地时间,并且,对日期和时间进行运算更加方便。
- 其次,新API的类型几乎全部是不变类型(和String的使用类似),可以放心使用不必担心被修改。
LocalDate、LocalTime、LocalDateTime
- LocalDate、LocalTime、LocalDateTime
- 他们分别表示日期,时间,日期时间对象,他们的类的实例是不可变的对象。
- 他们三者构建对象和API都是通用的
- 构建对象的方式如下:
- LocalDate
//1、获取本地日期对象。
LocalDate nowDate =LocalDate.now();
System.out.println("今天的日期:"+nowDate);//今天的日期:2022-03-24
int year= nowDate.getYear();
System.out.println(year+"年");//2022年
int month= nowDate.getMonthValue();
System.out.println(month+"月");//3月
int day= nowDate.getDayOfMonth();
System.out.println(day+"日");//24日
//当年的第几天
int dayOfYear= nowDate.getDayOfYear();
System.out.println("当年的第"+dayOfYear+"天");//当年的第83天
//星期
System.out.println("星期"+nowDate.getDayOfWeek());//星期THURSDAY
System.out.println("星期"+nowDate.getDayOfWeek().getValue());//星期4
//月份
System.out.println(nowDate.getMonth()+"月份");//MARCH月份
System.out.println(nowDate.getMonth().getValue()+"月份");//3月份
System.out.println("--------------------");
LocalDate bt =LocalDate.of(1991,11,11);
System.out.println(bt);//直接传入对应的年月日 //1991-11-11
System.out.println(LocalDate.of(1991, Month.NOVEMBER,11));//1991-11-11
- LocalTime
//1、获取本地日期对象。
LocalTime nowTime = LocalTime.now();
System.out.println("今天的日期:"+nowTime);//今天的日期:16:58:35.979
int hour= nowTime.getHour();
System.out.println(hour+"时");//16时
int minute= nowTime.getMinute();
System.out.println(minute+"分");//58分
int second= nowTime.getSecond();
System.out.println(second+"秒");//35秒
int nano= nowTime.getNano();
System.out.println(nano+"纳秒");//979000000纳秒
System.out.println("----------------------");
System.out.println(LocalTime.of(8,20));//时分
System.out.println(LocalTime.of(8,20,30));//时分秒
System.out.println(LocalTime.of(8,20,30,150));//时分秒纳
LocalTime mTime = LocalTime.of(8,20,30,150);
System.out.println("--------------------");
System.out.println(LocalDateTime.of(1991,11,11,8,20));//年月日时分
System.out.println(LocalDateTime.of(1991, Month.NOVEMBER,11,8,20));//年月日时分
System.out.println(LocalDateTime.of(1991,11,11,8,20,30));//年月日时分秒
System.out.println(LocalDateTime.of(1991, Month.NOVEMBER,11,8,20,30));//年月日时分秒
System.out.println(LocalDateTime.of(1991,11,11,8,20,30,40));//年月日时分秒纳
System.out.println(LocalDateTime.of(1991, Month.NOVEMBER,11,8,20,30,40));//年月日时分秒纳
- LocalDateTime
//日期 时间
LocalDateTime nowDateTime = LocalDateTime.now();
System.out.println("今天是:"+nowDateTime);//今天是:2022-03-24T17:17:26.167
System.out.println(nowDateTime.getYear()+"年");//2022年
System.out.println(nowDateTime.getMonthValue()+"月");//3月
System.out.println(nowDateTime.getDayOfMonth()+"日");//24日
System.out.println(nowDateTime.getHour()+"时");//17时
System.out.println(nowDateTime.getMinute()+"分");//17分
System.out.println(nowDateTime.getSecond()+"秒");//26秒
System.out.println(nowDateTime.getNano()+"纳");//167000000纳
//日:当年的第几天
System.out.println("当年的第"+nowDateTime.getDayOfYear()+"天");//当年的第83天
//星期
System.out.println("星期"+nowDateTime.getDayOfWeek());//星期THURSDAY
System.out.println("星期"+nowDateTime.getDayOfWeek().getValue());//星期4
//月份
System.out.println(nowDateTime.getMonth()+"月份");//MARCH月份
System.out.println(nowDateTime.getMonth().getValue()+"月份");//3月份
- 转换
//转换LocalDate
LocalDate ld =nowDateTime.toLocalDate();
System.out.println(ld);//2022-03-24
//转换LocalTime
LocalTime lt =nowDateTime.toLocalTime();
System.out.println(lt.getHour());//17时
System.out.println(lt.getMinute());//17分
System.out.println(lt.getSecond());//26秒
- 修改相关的API
- LocalDateTime综合了LocalDate和LocalTime里面的方法,所以下面只用LocalDate和LocalTime来举例。
- 这些方法返回的是一个新的实例引用,因为LocalDateTime 、 LocalDate 、 LocalTime都是不可变的。
LocalTime nowTime = LocalTime.now();
System.out.println(nowTime);//当前时间 17:29:49.255
System.out.println(nowTime.minusHours(1));//一小时前 16:29:49.255
System.out.println(nowTime.minusMinutes(1));//一分钟前 17:28:49.255
System.out.println(nowTime.minusSeconds(1));//一秒前 17:29:48.255
System.out.println(nowTime.minusNanos(1));//一纳秒前 17:29:49.254999999
System.out.println("----------------------");
System.out.println(nowTime.plusHours(1));//一小时后 18:29:49.255
System.out.println(nowTime.plusMinutes(1));//一分钟后 17:30:49.255
System.out.println(nowTime.plusSeconds(1));//一秒后 17:29:50.255
System.out.println(nowTime.plusNanos(1));//一纳秒后 17:29:49.255000001
System.out.println("----------------------");
LocalDate myDate = LocalDate.of(2018, 9, 5);
LocalDate nowDate = LocalDate.now();
System.out.println("今天是2018-09-06吗?"+nowDate.equals(myDate));//今天是2018-09-06吗?false
System.out.println(myDate+"是否在"+nowDate+"之前?"+myDate.isBefore(nowDate));//2018-09-05是否在2022-03-24之前?true
System.out.println(myDate+"是否在"+nowDate+"之后?"+myDate.isAfter(nowDate));//2018-09-05是否在2022-03-24之后?false
System.out.println("-------------------------");
//判断今天是否是你的生日
LocalDate birDate = LocalDate.of(1999, 8, 21);//生日的时间
LocalDate nowDate1 = LocalDate.now();//当前的时间
MonthDay birMd = MonthDay.of(birDate.getMonthValue(), birDate.getDayOfMonth());//获取生日的:月和日
MonthDay nowMd = MonthDay.from(nowDate1);//获取现在的:月和日
System.out.println("今天是你的生日吗?"+birMd.equals(nowMd));//今天是你的生日吗?false
Instant时间戳(时刻)
- JDK8获取时间戳特别简单,且功能更丰富。Instant类由一个静态的工厂方法now()可以返回当前时间戳。
- 时间戳是包含日期和时间的,与java.util.Date很类似,事实上Instant就是类似JDK8以前的Date。
- Instant和Date这两个类可以进行转换。
//1、得到一个Instant时间戳对象
Instant instant = Instant.now();
System.out.println(instant);//2022-03-24T09:50:48.535Z
//2、系统此刻的时间戳怎么办?
Instant instant1 = Instant.now();
System.out.println(instant1.atZone(ZoneId.systemDefault()));//2022-03-24T17:50:48.594+08:00[Asia/Shanghai]
//3、如何去返回Date对象
Date date = Date.from(instant);
System.out.println(date);//Thu Mar 24 17:50:48 CST 2022
Instant i2 = date.toInstant();
System.out.println(i2);//2022-03-24T09:50:48.535Z
DateTimeFormatter
- 在JDK8中,引入了一个全新的日期与时间格式器DateTimeFormatter。
- 正反都能调用format方法。
//本地此刻 日期时间 对象
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);//2022-03-24T18:01:49.198
//解析/格式化器
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EEE a");
//正向格式化
String ldtStr = dtf.format(ldt);
System.out.println(ldtStr);//2022-03-24 18:01:49 星期四 下午
//逆向格式化
String ldtStr1 = ldt.format(dtf);
System.out.println(ldtStr1);//2022-03-24 18:01:49 星期四 下午
//解析字符串时间
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dateStr="2022-03-24 11:11:11";
//解析当前字符串时间成为本地日期时间对象
LocalDateTime ldt1 = LocalDateTime.parse(dateStr, dtf1);
System.out.println(ldt1);//2022-03-24T11:11:11
System.out.println(ldt1.getDayOfYear());//一年中第83天
Duration/Period
Period:
- 在Java8中,我们可以使用以下类来计算日期间隔差异: java.time.Period
- 主要是Period类方法getYears(),getMonths()和getDays()来计算,只能精确到年月日。
- 用于LocalDate 之间的比较。
//当前本地 年月日
LocalDate today = LocalDate.now();
System.out.println(today);//2022-03-24
//生日的 年月日
LocalDate birthDate = LocalDate.of(1999, 8, 21);
System.out.println(birthDate);//1999-08-21
Period period = Period.between(birthDate, today);//第二个参数减第一个参数
System.out.println(period.getYears());//22
System.out.println(period.getMonths());//7
System.out.println(period.getDays());//3
Duration:
- 在Java8中,我们可以使用以下类来计算时间间隔差异: java.time.Duratio
- 提供了使用基于时间的值测量时间量的方法。
- 用于LocalDateTime之间的比较。也可用于Instant 之间的比较。
//本地日期时同对家。
LocalDateTime today = LocalDateTime.now();
System.out.println(today);//2022-03-24T19:52:04.158
//出生的日期时间对象
LocalDateTime birthDate = LocalDateTime.of(1999, 8, 21, 20, 00, 00);
System.out.println(birthDate);//1999-08-21T20:00
Duration duration = Duration.between(birthDate, today);//第二个参数减第一个参数
System.out.println(duration.toDays());//两个时间差的天数 8250
System.out.println(duration.toHours());//两个时间差的小时数 198023
System.out.println(duration.toMinutes());//两个时间差的分钟数 11881432
System.out.println(duration.toMillis());//两个时间差的毫秒数 712885924158
System.out.println(duration.toNanos());//两个时间差的纳秒数 712885924158000000
ChronoUnit
java.time.temporal.ChronoUnit
- ChronoUnit类可用于在单个时间单位内测量一段时间,这个工具类是最全的了,可以用于比较所有的时间单位
//本地日期时间对象:此刻的
LocalDateTime today = LocalDateTime.now();
System.out.println(today);//2022-03-24T20:03:15.405
//生日时间
LocalDateTime birthDate = LocalDateTime.of(1999, 8, 21, 20, 00, 00);
System.out.println(birthDate);//1999-08-21T20:00
System.out.println("相差的年数:"+ ChronoUnit.YEARS.between(birthDate,today));//相差的年数:22
System.out.println("相差的月数:"+ ChronoUnit.MONTHS.between(birthDate,today));//相差的月数:271
System.out.println("相差的周数:"+ ChronoUnit.WEEKS.between(birthDate,today));//相差的周数:1178
System.out.println("相差的天数:"+ ChronoUnit.DAYS.between(birthDate,today));//相差的天数:8251
System.out.println("相差的时数:"+ ChronoUnit.HOURS.between(birthDate,today));//相差的时数:198024
System.out.println("相差的分数:"+ ChronoUnit.MINUTES.between(birthDate,today));//相差的分数:11881443
System.out.println("相差的秒数:"+ ChronoUnit.SECONDS.between(birthDate,today));//相差的秒数:712886595
System.out.println("相差的毫秒数:"+ ChronoUnit.MILLIS.between(birthDate,today));//相差的毫秒数:712886595405
System.out.println("相差的微秒数:"+ ChronoUnit.MICROS.between(birthDate,today));//相差的微秒数:712886595405000
System.out.println("相差的纳秒数:"+ ChronoUnit.NANOS.between(birthDate,today));//相差的纳秒数:712886595405000000
System.out.println("相差的半天数:"+ ChronoUnit.HALF_DAYS.between(birthDate,today));//相差的半天数:16502
System.out.println("相差的十年数:"+ ChronoUnit.DECADES.between(birthDate,today));//相差的十年数:2
System.out.println("相差的世纪(百年)数:"+ ChronoUnit.CENTURIES.between(birthDate,today));//相差的世纪(百年)数:0
System.out.println("相差的千年数:"+ ChronoUnit.MILLENNIA.between(birthDate,today));//相差的千年数:0
System.out.println("相差的纪元数:"+ ChronoUnit.ERAS.between(birthDate,today));//相差的纪元数:0
包装类
- 其实就是8种基本数据类型对应的引用类型。
-
Java为了实现一切皆对象,为8种基本类型提供了对应的引用类型。
-
后面的集合和泛型其实也只能支持包装类型,不支持基本数据类型。
-
自动装箱:基本类型的数据和变量可以直接赋值给包装类型的变量。
int a=10;
Integer a1=a;//自动装箱
System.out.println(a);
System.out.println(a1);
- 自动拆箱:包装类型的变量可以直接赋值给基本数据类型的变量。
Integer it=100;
int it1=it;//自动拆箱
System.out.println(it1);
double db=99.5;
Double db2=db;//自动装箱
double db3=db2;//自动拆箱
System.out.println(db3);
-
包装类的特有功能:
- 包装类的变量的默认值可以是null,容错率更高。
//int age=null;//报错了 Integer age1=null; Integer age2=0;
- 可以把基本类型的数据转换成字符串类型(用处不大)
- 调用toString()方法得到字符串结果。
- 调用Integer.toString(基本类型的数据)。
Integer i3=23; String rs=i3.toString(); System.out.println(rs+1); String rs1=Integer.toString(i3); System.out.println(rs1+1); //可以直接+字符串得到字符串类型 String rs2=i3+""; System.out.println(rs2+1);
- 可以把字符串类型的数值转换成真实的数据类型(真的很有用)
- lnteger.parselnt("字符串类型的整数")
- Double.parseDouble("字符串类型的小数")。
String number="23"; //转换成整数 //int ages=Integer.parseInt(number); int ages1=Integer.valueOf(number); System.out.println(ages1+1); String number1="99.9"; //转换成小数 //double score=Double.parseDouble(number1); double score1=Double.valueOf(number1); System.out.println(score1+0.1);
总结:
1、包装类是什么,目的是什么?
- 基本数据类型对应的引用类型。
- 实现了一切皆对象。
- 后期集合和泛型不支持基本类型,只能使用包装类。
2、包装类有哪些特殊功能?
- 可以把基本类型的数据转换成字符串类型(用处不大)
- 可以把字符串类型的数值转换成真实的数据类型(真的很有用)
正则表达式
- 正则表达式可以用一些规定的字符来制定规则,并用来校验数据格式的合法性。
//需求:校验qq号码,必须全部数字6 - 20位
Scanner scanner = new Scanner(System.in);
System.out.println("请输入6 - 20位QQ号:");
String QQ = scanner.next();
if (QQ!=null && QQ.matches("\\d{6,20}")){
System.out.println("输入成功");
}else {
System.out.println("输入错误");
}
scanner.close();
正则表达式的匹配规则(Pattern):
- 字符类(默认匹配一个字符)
- 预定义的字符类(默认匹配一个字符)
- 贪婪的量词(配合匹配多个字符)
- 字符串对象提供了匹配正则表达式规则的API
public boolean matches(String regex):判断是否匹配正则表达式,匹配返回true,不匹配返回false。
System.out.println("a".matches("[abc]"));//true
System.out.println("z".matches("[abc]"));//false
System.out.println("ab".matches("[abc]"));//false
System.out.println("ab".matches("[abc]+"));//true
- 全面、深入学习正则表达式的规则
//public boolean matches(String regex):判断是否匹配正则表达式,匹配返回true,不匹配返回false。
//只能是 a b c
System.out.println("a".matches("[abc]"));//true
System.out.println("z".matches("[abc]"));//false
//不能出现 a b c
System.out.println("a".matches("[^abc]"));//false
System.out.println("z".matches("[^abc]"));//true
System.out.println("a".matches("\\d"));//false
System.out.println("3".matches("\\d"));//true
System.out.println("333".matches("\\d"));//false
System.out.println("z".matches("\\w"));//true
System.out.println("2".matches("\\w"));//true
System.out.println("21".matches("\\w"));//false
System.out.println("你".matches("\\w"));//false
//以上正则匹配只能校验单个字符。
System.out.println("---------------------------");
//效验密码
//必须是数字 字母 下划线 至少6位
System.out.println("ssdsc3c".matches("[\\w{6,}]"));//false
System.out.println("ssdsc".matches("[\\w{6,}]"));//false
System.out.println("ssdsda232s牛c".matches("[\\w{6,}]"));//false
System.out.println("------------------------------");
//验证。必须是数字和字符 必须是4位
System.out.println("dsd2".matches("[a-zA-Z0-9]{4}"));//true
System.out.println("A3dy".matches("[a-zA-Z0-9]{4}"));//true
System.out.println("A3dy2".matches("[a-zA-Z0-9]{4}"));//false
System.out.println("A3_y".matches("[a-zA-Z0-9]{4}"));//false
System.out.println("dsd2".matches("[\\w&&[^_]]{4}"));//true
- 正则表达式的常见案例
需求:
- 请编写程序模拟用户输入手机号码、验证格式正确,并给出提示,直到格式输入正确为止。
- 请编写程序模拟用户输入邮箱号码、验证格式正确,并给出提示,直到格式输入正确为止。
- 请编写程序模拟用户输入电话号码、验证格式正确,并给出提示,直到格式输入正确为止。
分析:
- 定义方法,接收用户输入的数据,使用正则表达式完成检验,并给出提示。
public static void main(String[] args) {
//目标:校验 手机号码 邮箱 电话号码
checkPhone();
checkEmail();
checkTel();
}
//手机号码
public static void checkPhone(){
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("请输入您的手机号码:");
String phone = scanner.next();
//判断手机号码的格式是否正确
if (phone.matches("1[3-9]\\d{9}")){
System.out.println("手机号码格式正确,注册完成");
break;
}else {
System.out.println("格式有误");
}
}
}
//邮箱
public static void checkEmail(){
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("请输入您的邮箱:");
String email = scanner.next();
//判断邮箱的格式是否正确
//1111111@qq.com 1111111@163.com 1111111@pci.com.cn
if (email.matches("\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2}")){
System.out.println("邮箱格式正确,注册完成");
break;
}else {
System.out.println("格式有误");
}
}
}
//电话号码
public static void checkTel(){
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("请输入您的电话号码:");
String tel = scanner.next();
//判断电话号码的格式是否正确
//023-12345678 02312345678
if (tel.matches("0\\d{2,6}-?\\d{5,20}")){
System.out.println("电话号码格式正确,注册完成");
break;
}else {
System.out.println("格式有误");
}
}
}
- 正则表达式在方法中的应用
String names="蓉儿dasdad34小龙女fhftghf455过儿";
String[] arrs=names.split("\\w+");
for (int i = 0; i < arrs.length; i++) {
System.out.print(arrs[i]+" ");//蓉儿 小龙女 过儿
}
//替换
String names2=names.replaceAll("\\w+"," ");
System.out.println(names2);//蓉儿 小龙女 过儿
- 正则表达式支持爬取信息
String rs="一起学习Java,电话023-123456,或联系邮箱" +
"123456@qq.com,电话18712345678,023123457" +
"邮箱JavaNB@qq.com,400-100-1234,4002002314";
//需求:从上面的内容中爬取出电话号码和邮箱。
//1、定义爬取规则,字符串形式
String regex="(\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2})|(0\\d{2,6}-?\\d{5,20})|(1[3-9]\\d{9})|(400-?\\d{3,9}-?\\d{3,9})";
//2、把这个爬取规则编译成匹配对象。
Pattern pattern = Pattern.compile(regex);
//3、得到一个内容匹配器对象
Matcher matcher = pattern.matcher(rs);
//4、开始找了
while (matcher.find()){
String rs1 = matcher.group();
System.out.println(rs1);
}
/*
找到的结果:
023-123456
123456@qq.com
18712345678
023123457
JavaNB@qq.com
400-100-1234
4002002314
*/
Arrays类
- 数组操作工具类,专门用于操作数组元素的。
- Arrays类的常用API
//目标:学会使用Arrays类的常用AP工,并理解其原理
int[] arr={10,2,55,23,24,100};
//1、返回数组内容的tostring(数组)
System.out.println(Arrays.toString(arr));//[10, 2, 55, 23, 24, 100]
//2、排序的API(默认自动对数组元素进行升序排序)
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));//[2, 10, 23, 24, 55, 100]
//3、二分搜索技术(前提数组必须排好序才支持,否则出bug)
int index = Arrays.binarySearch(arr, 55);
System.out.println(index);//4
//返回不存在元素的规律: -(应该插入的位置索引 + 1)
int index1 = Arrays.binarySearch(arr, 551);
System.out.println(index1);//-7
//注意:数组如果么有排好序,可能会找不到存在的元素,从而出现bug ! !
int[] arr2={12,36,34,25,13,55,66,44};
System.out.println(Arrays.binarySearch(arr2, 36));//-6
- Arrays类对于Comparator比较器的支持
- Arrays类的排序方法:
- 自定义排序规则
- 设置Comparator接口对应的比较器对象,来定制比较规则。
//目标:自定义数组的排序规则: Comparator比较器对象。
//1、Arrays 的sort方法对于有值特性的数组是默认升序排序
int[] ages={34,12,42,23};
Arrays.sort(ages);
System.out.println(Arrays.toString(ages));
//2、需求:降序排序!(自定义比较器对象,只能支持引用类型的排序!! )
Integer[] age1={34,12,42,23};
/*
参数一:被排序的数组必须是引用类型的元素
参数二:匿名内部类对象,代表了一个比较器对象。
*/
Arrays.sort(age1, new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
//制定比较规则
// if (o1>o2){
// return 1;
// }else if (o1() {
@Override
public int compare(Student o1, Student o2) {
//return o1.getAge()- o2.getAge();//按照年龄升序排序!
//return o2.getAge()- o1.getAge();//按照年龄降序排序!
//return Double.compare(o1.getHeight(), o2.getHeight());//比较浮点型可以这样写 升序
return Double.compare(o2.getHeight(), o1.getHeight());//比较浮点型可以这样写 降序
}
});
System.out.println(Arrays.toString(students));
常见算法
选择排序
- 选择排序的思想
- 每轮选择当前位置,开始找出后面的较小值与该位置交换
- 选择排序的关键
- 确定总共需要选择几轮:数组的长度-1
- 控制每轮从以前位置为基准,与后面元素选择几次。
//1、定义数组
int[] arr={5,1,3,2};
// 0 1 2 3
//2、定义一个循环控制选择几轮: arr.length - 1
for (int i = 0; i < arr.length-1; i++) {
//i=0 j=1 2 3
//i=1 j=2 3
//i=2 j=3
//3、定义内部循环,控制选择几次
for (int j = i+1; j < arr.length; j++) {
//当前位: arr[i]
//如果有比当前位数据更小的,则交换
if (arr[i]>arr[j]){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
System.out.println(Arrays.toString(arr));
二分查找(选择排序的改进)
- 二分查询性能好,二分查找的前提是必须是排好序的数据
- 二分查找相当于每次去掉一半的查找范围
- 步骤:
- 定义变量记录左边和右边位置。
- 使用while循环控制查询(条件是左边位置<=右边位置)
- 循环内部获取中间元素索引
- 判断当前要找的元素如果大于中间元素,左边位置=中间索引+1
- 判断当前要找的元素如果小于中间元素,右边位置=中间索引-1
- 判断当前要找的元素如果等于中间元素,返回当前中间元素索引。
public static void main(String[] args) {
//1、定义数组
int[] arr={10,14,16,25,28,30,35,88,100};
System.out.println(binarySearch(arr,25));
}
/**
* 二分查找算法的实现
* @param arr 排序的数组
* @param data 要找的数据
* @return 索引,如果元素不存在,直接返回-1
*/
public static int binarySearch(int[] arr,int data){
//1、定义左边位置 和 右边位置
int left=0;
int right= arr.length-1;
//2、开始循环,折半查询。
while (left<=right){
//取中间索引
int middleIndex=(left+right)/2;
//3、判断当前中间位置的元素和要找的元素的大小情况
if (data>arr[middleIndex]){
//往右边找,左位置更新为=中间索引+1
left=middleIndex+1;
}else if (data
Lambda表达式
Lambda
- Lambda表达式是JDK 8开始后的一种新语法形式。
- 作用:简化匿名内部类的代码写法。
- Lambda表达式的简化格式:
(匿名内部类被重写方法的形参列表)->{
被重写方法的方法体代码。
}
注:->是语法形式,无实际含义
- 注意:Lambda表达式只能简化函数式接口的匿名内部类的写法形式
- 什么是函数式接口?
- 首先必须是接口、其次接口中有且仅有一个抽象方法的形式
- 通常我们会在接口上加上一个@FunctionalInterface注解,标记该接口必须是满足函数式接口。
public class LambdaDemo {
public static void main(String[] args) {
//目标:使用Lambda的标准格式简化匿名内部类的代码形式
//Lambda只能简化接口中只有一个抽象方法的匿名内部类形式
// Swimming s1 = new Swimming() {
// @Override
// public void swim() {
// System.out.println("老师游泳");
// }
// };
//简化
Swimming s1=() -> {
System.out.println("老师游泳");
};
go(s1);
System.out.println("---------------------");
//继续简化
go(new Swimming() {
@Override
public void swim() {
System.out.println("老师游泳很开心");
}
});
System.out.println("---------------------");
//继续继续简化
go(() ->{
System.out.println("老师游泳很开心2");
});
}
public static void go(Swimming s){
System.out.println("开始");
s.swim();
System.out.println("结束");
}
}
@FunctionalInterface //一但加上这个注解必须是函数式接口,里面只能有一个抽象方法
interface Swimming{
void swim();
}
总结:
- Lambda表达式的基本作用?
- 简化函数式接口的匿名内部类的写法。
- Lambda表达式有什么使用前提?
- 必须是接口的匿名内部类,接口中只能有一个抽象方法
- Lambda的好处?
- Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码,它可以写出更简洁、更灵活的代码,作为一种更紧凑的代码风格,使Java语言表达能力得到了提升。
Lambda简化常见函数式接口
- Lambda表达式简化Comparator接口的匿名形式
- Lambda表达式简化按钮监听器ActionListener的匿名内部类形式
Lambda省略规则
Lambda表达式的省略写法(进一步在Lambda表达式的基础上继续简化):
- 参数类型可以省略不写。
- 如果只有一个参数,参数类型可以省略,同时()也可以省略。
- 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写,同时要省略分号!
- 如果Lambda表达式的方法体代码只有一行代码。可以省略大括号不写。此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
//1、Lambda表达式简化Comparator接口的匿名形式
Integer[] age={34,12,42,23};
//源代码
Arrays.sort(age, new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o1-o2;//默认升序
}
});
//简化1
Arrays.sort(age, (Integer o1, Integer o2) ->{
return o1-o2;
});
//简化2
Arrays.sort(age, (o1, o2) ->{
return o1-o2;
});
//简化3
Arrays.sort(age, (o1, o2) -> o1-o2);
System.out.println(Arrays.toString(age));
//2、Lambda表达式简化按钮监听器ActionListener的匿名内部类形式
JFrame win=new JFrame("登陆界面");
JButton btn=new JButton("我是一个很大的按钮");
//源代码
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("有人点我,点我");
}
});
//简化1
btn.addActionListener((ActionEvent e) ->{
System.out.println("有人点我,点我");
});
//简化2
btn.addActionListener((e) ->{
System.out.println("有人点我,点我");
});
//简化3
btn.addActionListener(e ->{
System.out.println("有人点我,点我");
});
//简化4
btn.addActionListener(e ->System.out.println("有人点我,点我"));
win.add(btn);
win.setSize(400,300);
win.setVisible(true);
false,s2创建了两个对象,s1创建了一个对象 ??
false ??
true ??