字符串相关的类
String类及常用方法
String的特性
-
String类:代表字符串
-
String是一个 final类,代表不可变的字符序列
-
字符串是常量,使用双引号来表示;它们的值在创建后不能改变
-
String对象的字符串内容是存储在一个字符数组 value[]中的
String对象的创建
String str1 = "hello";
// 本质上:this.vallue = new char[0];
String s1 = new String();
String str11 = "abc";
String str22 = new String("abc");
// 以上两个变量的区别?
// 1.字符串常量存储在字符串常量池,目的是共享
// 2.字符串非常量对象存储在堆中
- 面试:String s = new String("asd"); 方式创建对象,在内存中共创建了 两个对象
- 一个是 堆空间中 new结构
- 另一个是 char[] 对应的常量池中的数据 "asd"
String常用方法
一、
- int length():返回字符串长度;return value.length
- char charAt(int index):返回某索引处的字符;return value[index]
- boolean isEmpty():判断是否为空字符串;return value.length == 0
- String toLowerCase():使用默认语言环境,将 String中的所有字符转为小写
- String toUpperCase():使用默认语言环境,将 String中的所有字符转为大写
- String trim():返回字符串的副本忽略前部空白和尾部空白
- boolean equals(Object obj):比较字符串的内容是否相同
- boolean equalsIgnoreCase(String anotherString):与 equals方法类似,忽略大小写
- String concat(String str):将指定字符串连接到此字符串的结尾;等价于用 ‘+’
- int compareTo(String anotherString):比较两个字符串的大小
- String substring(int beginIndex[, int endIndex] ):返回一个新字符串,它是此字符串从 beginIndex到 endIndex(不包含)的一个子字符串
package com.atguigu.java;
import org.junit.Test;
/**
*
* @author lv
* @create 2020-12-06 17:10
*/
public class StringMethodTest {
@Test
public void test1() {
String s1 = "Hello World";
System.out.println(s1.length()); // 11
char ch = s1.charAt(1);
System.out.println(ch); // e
boolean isEmpty = s1.isEmpty();
System.out.println(isEmpty); // false
boolean isEmpty1 = "".isEmpty();
System.out.println(isEmpty1); // true
String s2 = s1.toLowerCase();
System.out.println(s2); // hello world
String s3 = s1.toUpperCase();
System.out.println(s3); // HELLO WORLD
String s4 = " sdf g13 13 ".trim();
System.out.println(s4); // sdf g13 13
boolean isEquals = "Hello world".equalsIgnoreCase(s1);
System.out.println(isEquals); // true
String s5 = "akvnla ".concat("agafv");
System.out.println(s5); // akvnla agafv
String s6 = "asd";
String s7 = new String("asf");
System.out.println(s6.compareTo(s7)); // -2
String s8 = "北京尚硅谷教育".substring(3);
System.out.println(s8); // 硅谷教育
String s9 = "北京尚硅谷教育".substring(3, 4);
System.out.println(s9); // 硅
}
}
二、
- boolean endsWith(String suffix):测试此字符串是否以指定后缀结束
- boolean startsWith(String prefix):测试此字符串是否以指定前缀开始
- boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
- boolean contains(CharSequence s):当且仅当此字符串包含指定的 char值序列时,返回 true
- int indexOf(String str):返回指定子字符串在此字符串中第一次出现的索引
- int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引
- int lastIndex(String str):返回指定子字符串在此字符串中最右边出现处的索引
- int lastIndex(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现的索引,从指定的索引处反向搜索
package com.atguigu.java;
import org.junit.Test;
/**
*
* @author lv
* @create 2020-12-06 17:10
*/
public class StringMethodTest {
@Test
public void test2() {
String s1 = "456";
System.out.println(s1.endsWith("56")); // true
String s2 = "sgdfbsdgbsd";
System.out.println(s2.startsWith("sg")); // true
String s3 = "4561315646513";
System.out.println(s3.startsWith("13", 3)); // true
String s4 = "sdfvhknkfv";
System.out.println(s4.contains("fv")); // true
System.out.println(s4.contains("fsv")); // false
String s5 = "HelloWorld";
System.out.println(s5.indexOf("ll")); // 2
System.out.println(s5.indexOf("l", 4)); // 8
System.out.println(s5.lastIndexOf("or")); // 6
System.out.println(s5.lastIndexOf("l", 7)); // 3
}
}
三、
替换
- String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar替换此字符串中出现的所有 oldChar得到的
- String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串
- String replaceAll(String regex, String replacement):使用给定的 replacement替换此字符串所有匹配给定的正则表达式的子字符串
- String replaceFirst(String regex, String replacement):使用给定的 replacement替换此字符串匹配给定的正则表达式的第一个字符串
匹配
- boolean matches(String regex):告知此字符串是否匹配给定的正则表达式
切片
- String[] split(String regex):根据给定的正则表达式的匹配拆分此字符串
- String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过 limit个,如果超过,剩下的全部都放到最后一个元素中
package com.atguigu.java;
import org.junit.Test;
/**
*
* @author lv
* @create 2020-12-06 17:10
*/
public class StringMethodTest {
@Test
public void test3() {
// 替换
String s1 = "helloword".replace('o', '0');
System.out.println(s1); // hell0w0rd
String s2 = "helloworld".replace("he", "He");
System.out.println(s2); // Helloworld
// 匹配
String str = "12345";
boolean matches = str.matches("\\d+");
System.out.println(matches); // true
String tel = "0571-6131654";
boolean result = tel.matches("0571-\\d{7,8}");
System.out.println(result); // true
// 切片
String[] strArr = "s4d4f2v".split("\\d+");
for (int i = 0; i < strArr.length; i++) {
System.out.println(strArr[i]);
}
}
}
String与基本数据类型转换
字符串 -> 基本数据类型、包装类
- Integer 包装类的 public static int parseInt(String s):可以将由“数字”字符组成的字符串转换为整数
- 类似的还有,使用 java.lang包中的 Byte、Long、Float、Double类调用相应的类方法可以将由 “数字”字符组成的字符串,转化为相应的基本数据类型
基本数据类型、包装类 -> 字符串
- 调用 String类的 public String valueOf(int n) 可将 int型转换为字符串
- 相应的 valueOf(byte b)、valueOf(float f)、valueOf(double d)、valueOf(boolean b)可由参数的相应类型到字符串的转换
String 与 字符数组转换
字符数组 -> 字符串
- String 类的构造器:String(char[]) 和 String(char[], int offset, int length) 分别用字符数组中的全部字符和部分字符创建字符串对象
字符串 -> 字符数组
- public char[] toCharArray():将字符串中的全部字符存放在一个字符数组中的方法
- public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):提供了将指定索引范围内的字符串存放到数组中的方法
package com.atguigu.java;
import org.junit.Test;
/**
* String类与其它结构的转换
* @author lv
* @create 2020-12-07 20:09
*/
public class StringTransfer {
/**
* 1.String 与 char[]之间的转换
* str.toCharArray()
*
* 2.char[] 与 String之间的转换
* 调用 String的构造器
*
*/
@Test
public void test2() {
String s1 = "asafv633";
char[] ch1 = s1.toCharArray();
for (int i = 0; i < ch1.length; i++) {
System.out.println(ch1[i]);
}
char[] arr = new char[]{'h', 'e', 'l', 'l', 'o'};
String str1 = new String(arr);
System.out.println(str1); // hello
}
/**
* 1.String与 基本数据类型、包装类间的转换
* parseXxx()
*
* 2.基本数据类型、包装类间与 String的转换
* String重载的 valueOf(xxx)
*/
@Test
public void test1() {
String s1 = "456";
int strNum = Integer.parseInt(s1);
System.out.println(strNum); // 456
String s2 = String.valueOf(123);
System.out.println(s2); // "123"
String s3 = strNum + "";
System.out.println(s3); // "456"
System.out.println(s1.equals(s3) + " : " + (s1 == s3)); // true : false
}
}
String 与 字节数组转换
字节数组 -> 字符串
- String(byte[]):通过使用平台的默认字符集解码指定的 byte数组,构造一个新的 String
- String(byte[], int offset, int length):用指定的字节数组的一部分,即从数组起始位置 offset开始取 length个字节构造一个字符串对象
字符串 -> 字节数组
- public byte[] getBytes():使用平台的默认字符集将此 String编码为 byte序列,并将结果存储到一个新的 byte数组中
- public byte[] getBytes(String charsetName):使用指定的字符集将此 String编码到 byte序列,并将结果存储到新的 byte数组
package com.atguigu.java;
import org.junit.Test;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/**
* String类与其它结构的转换
* @author lv
* @create 2020-12-07 20:09
*/
public class StringTransfer {
/**
* String 与 byte[] 之间的转换
*
* 1.String -> byte[]:调用 String的 getBytes()
*
* 2.byte[] -> String:调用 String的构造器
*
* 编码:字符串 -> 字节 (看得懂 -> 看不懂的二进制数据)
* 解码:编码的逆过程
*/
@Test
public void test3() throws UnsupportedEncodingException {
String str1 = "123abc中国";
byte[] bytes = str1.getBytes();
// for (int i = 0, len = bytes.length; i < len; i++) {
// System.out.println("bytes[i]: " + bytes[i]);
// }
// utf-8:一个汉字占 三位
System.out.println(Arrays.toString(bytes)); // [49, 50, 51, 97, 98, 99, -28, -72, -83, -27, -101, -67]
// // 使用 gbk字符集进行编码
byte[] bytes1 = str1.getBytes("gbk");
System.out.println(Arrays.toString(bytes1)); // [49, 50, 51, 97, 98, 99, -42, -48, -71, -6]
String s1 = new String(bytes);
System.out.println(s1); // 123abc中国
String s2 = new String(bytes1, "gbk"); // 指定解码器
System.out.println(s2); // 123abc中国
}
}
StringBuffer、StringBuilder
- java.lang.StringBuffer 代表可变的字符序列,JDK1.0中声明,可以对字符串内容进行增删,此时不会产生新的对象
- 很多方法与 String相同 -作为参数传递时,方法内部可以改变值
String、StringBuffer、StringBuilder 三者的异同
在日常使用中,优先使用 StringBuilder、StringBuffer,最后考虑使用 String
效率:StringBuilder > StringBuffer > String
- String:
- 不可变的字符序列;
- 底层使用 char[]存储
- StringBuffer:
- 可变的字符序列;
- 线程安全的,效率低
- 底层使用 char[]存储
- StringBuilder:
- 可变的字符序列;
- JDK5.0新增,线程不安全,效率高
- 底层使用 char[]存储
问题:
- 扩容问题:如果添加的数据底层数组长度不够,那就需要扩容底层的数组,默认情况下,扩容为原来容量的 2倍+2,同时将原有数组中的元素复制到新的数组中,如此循环的扩容;在实际开发中建议使用 StringBuffer(int capacity)、StringBuilder(int capacity) 尽量避免数组扩容
// 源码分析
String str = new String(); // char[] value = new char[0];
String str1= new String("abc"); // char[] value = new char[]{'a', 'b', 'c'};
StringBuffer sb1 = new StringBuffer(); // char[] value = new char[16]; 默认创建长度为 16的 char数组
sb1.append('a'); // value[0] = 'a';
sb2.append('b'); // value[1] = 'b';
StirngBuilder sb2 = new StringBuffer("abc"); // char[] value = new char["abc".length + 16]; // 额外增加 16长度
StringBuffer类的常用方法
-
StringBuffer append(xxx):提供了很多的 append()方法,用于进行字符串拼接
-
StringBuffer delete(int start, int end):删除指定位置的内容 [start, end)
-
StringBuffer replace(int start, int end, String str):把 [start, end)位置替换为 str
-
StringBuffer insert(int offset, xxx):在指定位置插入 xxx
-
StringBuffer reverse():将当前字符序列逆转
-
public int indexOf(String str)
-
public String substring(int start, int end):返回一个 [start, end)的子字符串
-
public int length()
-
public char charAt(int n)
-
public void setCharAt(int n, char ch)
- 当 append和 insert时,如果原来 value数组长度不够,可扩容
- 如上这些方法支持方法链操作
- 方法链原理:
public StringBuffer append(String str) { super.append(str); return this; }
总结:
- 增:append(xxx)
- 删:delete(nt start, int end);
- 改:setCharAt(int n, char ch),replace(int start, int end, String str)
- 查:charAt(int n)
- 插:insert(int offset, xxx)
- 长度:length()
- 遍历:for + charAt(int n)
package com.atguigu.java;
import org.junit.Test;
/**
* 关于 StringBuffer 和 StringBuilder的使用
*
* @author lv
* @create 2020-12-08 20:35
*/
public class StringBufferBuilderTest {
@Test
public void test2() {
StringBuffer s1 = new StringBuffer("abc");
s1.append(1);
s1.append('1');
System.out.println(s1); // abc11
s1.delete(0, 2);
System.out.println(s1); // c11
s1.replace(0, 2, "world");
System.out.println(s1); // world1
s1.insert(0, "Hello ");
System.out.println(s1); // Hello world1
System.out.println(s1.length()); // 12
s1.reverse();
System.out.println(s1); // 1dlrow olleH
System.out.println(s1.indexOf("w")); // 5
String sub1 = s1.substring(1, 5);
System.out.println(sub1 + " :" + s1); // dlro :1dlrow olleH
for (int i = 0; i < s1.length(); i++) {
System.out.println("s1[i]: " + s1.charAt(i)); // s1[i]: 1, ...
}
System.out.println(s1.toString()); // 1dlrow olleH
}
@Test
public void test1() {
StringBuffer sb1 = new StringBuffer("abc");
sb1.setCharAt(0, 'A');
System.out.println(sb1); // Abc
}
}
日期时间 API的迭代
第一代:jdk 1.0 Date类
第二代:jdk 1.1 Calendar类,一定程度上替换 Date类
第三代:jdk 1.8 提出了新的一套 API,java.time
JDK8 之前的日期时间 API
System静态方法
System类提供的 public static long currentTimeMillis()用来返回当前时间与 1970-01-01 00:00:00之间以毫秒为单位的时间差
-
此方法适用于计算时间差
-
计算世界时间的主要标准有:
- UTC(Coordinated Universal Time)
- GMT(Greenwich Mean Time)
- CST(Central Standard Time)
Date类
java.util.Date类,表示特定的瞬间,精确到毫秒
构造器
- Date():使用无参构造器创建的对象可以获取本地当前时间
- Date(long date)
常用方法
- getTime():返回自 1970-01-01 00:00:00 GMT 以来此 Date对象表示的毫秒数
- toString():将此 Date对象转换为以下形势的 String:dow mon dd hh:mm:ss zzz yyyy 其中:dow是一周中的某一天(Sun、Mon、Tue、Wed、Thu、Fri、Sat),zzz是时间标准
- 其它方法以过时
java.sql.Date
- 如何实例化
- 如何将 java.util.Date对象转换为 java.sql.Date对象
package com.atguigu.java;
import org.junit.Test;
import java.util.Date;
/**
* JDK 8 之前日期和时间API
* java.util.Date
* |--java.sql.Date
*
* @author lv
* @create 2020-12-09 20:22
*/
public class DateTimeTest {
/**
* java.util.Date
*
* 1.两个构造器的使用
*
* 2.两个方法的使用
*
* 3.java.sql.Date用于数据库中的日期
* > 如何实例化
* > 如何将 java.util.Date对象转换为 java.sql.Date对象
*
*/
@Test
public void test2() {
// 创建一个对应当前时间的 Date对象
Date date1 = new Date();
System.out.println(date1 + " - " + date1.toString()); // Wed Dec 09 20:41:45 CST 2020 - Wed Dec 09 20:41:45 CST 2020
System.out.println(date1.getTime()); // 1607517835664
// 指定时间
Date date2 = new Date(1607517835664L);
System.out.println(date2); // Wed Dec 09 20:43:55 CST 2020
// java.util.Date对象
java.sql.Date date3 = new java.sql.Date(1607517835664L);
System.out.println(date3); // 2020-12-09
// 如何将 java.util.Date对象转换为 java.sql.Date对象
// 方式一:
Date date4 = new java.sql.Date(1607517835664L);
java.sql.Date date5 = (java.sql.Date) date4;
// 方式二:
Date date6 = new Date();
java.sql.Date date7 = new java.sql.Date(date6.getTime());
System.out.println(date7); // 2020-12-09
}
/**
* 1.System类中 currentTimeMillis()
*/
@Test
public void test1() {
long disTime = System.currentTimeMillis();
System.out.println(disTime); // 1607516744120
}
}
问题:
-
如何理解 String的不可变性 凡是对于字符串值修改的操作,都会新建一个字符串,而不去改变原有的字符串
-
String、StringBuffer、StringBuilder的对比
三者底层存储的结构都是 char[] 数组
- String 是不可变的字符序列,效率最低
- StringBuffer 可变字符序列,线程安全的,效率稍低
- StringBuilder 可变字符序列,线程不安全的,效率高
-
String的常用方法
- length()、charAt()、setCharAt()、equals()
- compareTo()、startsWidth()、endsWidth()
- containts()、indexOf()、lastIndexOf()
- getBytes()、toCharArray()
- valueOf() ...
-
String 与 StringBuffer、StringBuilder的转换
- String -> StringBuffer、StringBuilder:调用 StringBuffer、StringBuilder 构造器
- StringBuffer、StringBuilder -> String:调用 String构造器,StringBuffer、StringBuilder的 toString()
-
JVM 中字符串常量池存放位置:
- jdk 1.6:字符串常量池存储在方法区(永久区)
- jdk 1.7:字符串常量池存储在堆空间
- jdk 1.8:字符串常量池存储在方法区(元空间)
-
StringBuffer、StringBuilder中的常用方法
- 增:append(xxx)
- 删:delete(int start, int end)
- 改:setCharAt(int n, char ch)、replace(int start, int end, String str)
- 查:charAt(int n)
- 插:insert(int offset, xxx)
- 遍历:for() + charAt()、toString()
Calendar类(抽象类)
java.util.Calendar (日历)类
- Calendar 是一个抽象基类,主要用于完成日期字段之间互相操作的功能
- 获取 Calendar实例的方法
- 使用 Calendar.getInstance()方法
- 调用它的子类 GregorianCalendar的构造器
- 一个 Calendar的实例是系统时间的抽象表示,通过 get(int field)方法来区的想要的时间信息。比如 YEAR、MONTH DAY_OF_WEEK、HOUR_OF_DAY、MINUTE、SECOND
- public void set(int field, int value)
- public void add(int field, int amount)
- public final Date getTime()
- public final void setTime(Date date)
- 注意:
- 月份:一月是0,二月是1,...12月是11
- 星期:周日是1,周二是2,...周六是7
package com.atguigu.java;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* @author lv
* @create 2020-12-13 11:13
*/
public class DateTimeTest {
/**
* Calendar 日历类
*
*/
@Test
public void test3() {
// 1.实例化
// 方式一:创建子类 GregorianCalendar 对象
// 方式二:调用其静态方法:Calendar.getInstance()
Calendar c = Calendar.getInstance();
System.out.println(c.getClass()); // class java.util.GregorianCalendar
// 2.常用方法:
// get()
int day = c.get(Calendar.DAY_OF_MONTH);
System.out.println(day); // 13
System.out.println(c.get(Calendar.DAY_OF_YEAR)); // 348
// set(), calendar可变性,不合适
c.set(Calendar.DAY_OF_MONTH, 22);
day = c.get(Calendar.DAY_OF_MONTH);
System.out.println(day); // 22
// add()
c.add(Calendar.DAY_OF_MONTH, -3);
day = c.get(Calendar.DAY_OF_MONTH);
System.out.println(day); // 19
// getTime():Calendar -> Date
Date d1 = c.getTime();
System.out.println(d1.getTime()); // 1608366492210
// setTime():Date -> Calendar
Date date1 = new Date();
c.setTime(date1);
day = c.get(Calendar.DAY_OF_MONTH);
System.out.println(day); // 13
}
}
SimpleDateFormat类 *****
java.text.SimpleDateFormat
主要是对日期 Date类的 格式化和解析
-
Date类的API不易于国际化,大部分被废弃,java.text.SimpleDateFormat类,是一个不与语言环境有关的方式来格式化和解析日期的具体类
-
它允许进行 格式化:日期 -> 文本;解析:文本 -> 日期
-
格式化:formate(Date date)
- SimpleDateFormate():默认的模式和语言环境创建对象
- public SimpleDateFormat(String pattern):该构造方法可以用参数 parttern指定的格式创建一个对象,该对象调用:
- public String format(Date date):方法格式化时间对象 date
-
解析:parse(String str)
- public Date parse(String source):从给定字符串的开始解析文本,以生成一个日期
package com.atguigu.java;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author lv
* @create 2020-12-13 11:13
*/
public class DateTimeTest {
/**
* 三天打鱼两天晒网
*/
@Test
public void test2() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dateStart = null;
Date dateEnd = null;
try {
dateStart = sdf.parse("1990-01-01");
dateEnd = sdf.parse("2020-09-08");
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(dateEnd.getTime());
Long disDate = ((dateEnd.getTime() - dateStart.getTime()) / (1000 * 60 * 60 * 24)) + 1;
double result = disDate / 5;
float result1 = disDate % 5;
System.out.println(result + " : " + result1); // 2241.0 : 3.0
float f1 = 8 / 7;
System.out.println(f1); // 1.0
}
/**
* SimpleDateFormat 的使用:SimpleDateFormat 对日期 Date类的格式解析
* 1.两个操作:
* 1.1 格式化:日期 -> 字符串
* 1.2 解析:字符串 -> 日期
*
* 2.SimpleDateFormat实例化
*
*/
@Test
public void test1() {
// 实例化 -> 默认构造器
SimpleDateFormat sdf = new SimpleDateFormat();
Date date = new Date();
System.out.println(date); // Sun Dec 13 11:19:44 CST 2020
// 格式化
String format = sdf.format(date);
System.out.println(format); // 20-12-13 上午11:22
// 解析
Date parse = null;
try {
parse = sdf.parse("20-12-13 上午11:22");
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(parse); // Sun Dec 13 11:22:00 CST 2020
// ***********************************
// SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyy.MMMM.dd GGG hh.mm aa");
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date1 = new Date();
// 格式化
String format1 = sdf1.format(date1);
System.out.println(format1); // 2020-12-13 11:37:50
// 解析
try {
Date parse1 = sdf1.parse("2020-12-14 14:12:59");
System.out.println(parse1); // Mon Dec 14 14:12:59 CST 2020
} catch (ParseException e) {
e.printStackTrace();
}
}
// 字符串 "2020-12-14" 转为 java.sql.Date
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
Date parse2 = null;
try {
parse2 = sdf2.parse("2020-12-14");
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(parse2 + " : " + parse2.getTime());
java.sql.Date jDate = new java.sql.Date(parse2.getTime());
System.out.println("sql.Date: " + jDate);
}
JDK8 中新日期时间 API
-
java.time - 包含值对象的基础包
-
java.time.chrono - 提供对不同的日历系统的访问
-
java.time.format - 格式化和解析时间和日期
-
java.time.temporal - 包括底层框架和扩展特性
-
java.time-zone - 包含时区支持的类
LocalDate、LocalTime、LocalDateTime *****
以上三个类非常重要,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间;它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含于时区相关的信息。
- LocalDate 代表 IOS格式(yyyy-MM-dd)的日期,可以存储生日、纪念日等日期
- LocalTime 表示一个时间,而不是日期
- LocalDateTime 用来表示日期和时间,这是一个最常用的类之一
package com.atguigu.java;
import org.junit.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* @author lv
* @create 2020-12-13 22:32
*/
public class J8DateTimeTest {
/**
* LocalDate、LocalTime、LocalDateTime 的使用
*/
@Test
public void test1() {
// now() 获取当前的日期、时间
LocalDate date1 = LocalDate.now();
LocalTime time1 = LocalTime.now();
System.out.println(date1 + " " + time1); // 2020-12-13 22:39:37.722
LocalDateTime dt1 = LocalDateTime.now();
System.out.println(dt1); // 2020-12-13T22:40:44.730
// of() 设置指定的 年月日时分秒,没有偏移量
LocalDateTime dt2 = LocalDateTime.of(2020, 12, 14, 22, 56, 55);
System.out.println(dt2); // 2020-12-14T22:56:55
// getXxx() 获取
System.out.println(dt1.getDayOfMonth()); // 13
System.out.println(dt1.getDayOfWeek()); // SUNDAY
System.out.println(dt1.getMonth()); // DECEMBER
System.out.println(dt1.getMonthValue()); //12
System.out.println(dt1.getMinute()); // 54
// withXxx() 设置
LocalDateTime dt21 = dt2.withDayOfMonth(22);
// 体现不可变性
System.out.println(dt21 + " " + dt2); // 2020-12-22T22:56:55 2020-12-14T22:56:55
LocalDateTime dt22 = dt2.withHour(23);
System.out.println(dt22 + " " + dt2); // 2020-12-14T23:56:55 2020-12-14T22:56:55
// plusXxx() 添加
LocalDateTime dt23 = dt2.plusHours(2);
System.out.println(dt23 + " " + dt2); // 2020-12-15T00:56:55 2020-12-14T22:56:55
// minusXxx() 减
LocalDateTime dt24 = dt2.minusDays(5);
System.out.println(dt24 + " " + dt2); // 2020-12-09T22:56:55 2020-12-14T22:56:55
}
}
Instant 瞬时
- Instant:时间线上的一个瞬时点;这可以被用来记录应用程序中的事件时间戳
- 在处理时间和日期时,我们通常会想到年、月、日、时、分、秒;然而这只是时间的一个模型,是面向人类的。第二种通用模型是面向机器的,或者说是连续的;在此模型中,时间线中的一个点表示为一个很大的数,这有利于计算机处理。
- java.time 包通过值类型 Instant提供机器视图,不提供处理人类意义上的时间单位;Instant 表示时间线上的一点,而不需要任何上下文信息,例如,时区;概念上讲,它只是简单的表示自 1970-01-01 00:00:00(UTC)开始的秒数;因为 java.time 包是基于纳秒计算的,所以 Instant的精度可以达到纳秒级。
- (1 ns = 10^-9 s) 1秒 = 1000 毫秒 = 10^6 微秒 = 10^9 纳秒
方法
/**
* Instant 类似于 java.util.Date
*/
@Test
public void test3() {
// 实例化
// 方式一:now()
Instant in1 = Instant.now();
System.out.println(in1); // 本初子午线时间 2020-12-14T11:01:30.895Z
// 根据时区添加偏移量,获取当地时间
OffsetDateTime offsetDateTime = in1.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime); // 2020-12-14T19:07:57.946+08:00
// 获取瞬时点对应的毫秒数 date.getTime()
// toEpochMilli()
long il1 = in1.toEpochMilli();
System.out.println(il1); // 1607944310231
// 方式二:同过毫秒数获取实例 -> Date(L)
Instant instant1 = Instant.ofEpochMilli(il1);
System.out.println(instant1); // 2020-12-14T11:11:50.231Z
}
DateTimeFormatter
java.time.format.DateTimeFormatter类:该类提供了 三种格式化方法:
- 预定义的标准格式;如:ISO_LOCAL_DATE_TIME、ISO_LOCAL_DATE、ISO_LOCAL_TIME
- 本地化相关的格式;如:ofLocalizedDateTime(FormatStyle.LONG)
- 自定义格式;如:ofPattern("yyyy-MM-dd hh:mm:ss E")
/**
* DateTimeFormatter:格式化或解析 日期、时间 类似于 SimpleDateFormat
*
*/
@Test
public void test4() {
// 方式一:ISO_LOCAL_DATE_TIME、...
DateTimeFormatter f1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
// 格式化:日期 -> 字符串
LocalDateTime ldt1 = LocalDateTime.now();
String f11 = f1.format(ldt1);
System.out.println(f11); // 2020-12-14T19:40:51.077
// 解析:字符串 -> 日期
TemporalAccessor parse1 = f1.parse(f11);
System.out.println(parse1); // {},ISO resolved to 2020-12-14T19:43:52.480
// 方式二:本地化相关格式 ofLocalizedDateTime(FormateStyle.Long)
// FormatStyle.LONG、FormatStyle.SHORT、FormatStyle.MEDIUM
DateTimeFormatter dtf1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
// 格式化
String format1 = dtf1.format(ldt1);
// System.out.println(format1); // 20-12-14 下午7:52
System.out.println(format1); // 2020年12月14日 下午07时53分43秒
// 本地化相关格式 ofLocalizedDate()
// FormatStyle.LONG、FormatStyle.FULL、FormatStyle.MEDIUM、FormatStyle.SHORT
// DateTimeFormatter dtf2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
DateTimeFormatter dtf2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
String format2 = dtf2.format(LocalDate.now());
// System.out.println(format2); // 2020年12月14日 星期一
System.out.println(format2); // 2020-12-14
// 重点 方式三:自定义格式 ofPattern("yyyy-MM-dd hh:mm:ss E")
DateTimeFormatter dtf3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
// 格式化
String f3 = dtf3.format(LocalDateTime.now());
System.out.println(f3); // 2020-12-14 08:07:22
// 解析
TemporalAccessor p3 = dtf3.parse(f3);
System.out.println(p3);
// {NanoOfSecond=0, MicroOfSecond=0, HourOfAmPm=8, MinuteOfHour=10, MilliOfSecond=0, SecondOfMinute=0},ISO resolved to 2020-12-14
}
其它类
Java比较器 *****
在后续编码中,只要涉及到对象比较大小,就后使用到以下两个接口,Comparable、Comparator
- 在 Java中经常会涉及到对象数组的排序问题,那么就会涉及到对象之间的比较问题
- Java 实现对象排序的方式有两种:
- 自然排序:java.lang.Comparable
- 定制排序:java.lang.Comparator
Comparable 接口,自然排序
java.util.Comparable
package com.atguigu.java;
/**
* 商品类
*
* @author lv
* @create 2020-12-15 18:47
*/
public class Goods implements Comparable {
private String name;
private double price;
public Goods() {
}
public Goods(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
// 指明排序规则:价格 从低到高,再按照产品名称 从高到低
public int compareTo(Object obj) {
if (obj instanceof Goods) {
Goods goods = (Goods)obj;
// 方式一:
if (this.price > goods.price) {
return 1;
} else if (this.price < goods.price) {
return -1;
} else {
// return 0;
return -this.name.compareTo(goods.name);
}
// 方式二:
// return Double.compare(this.price, goods.price);
}
// 运行时异常可以不用处理
throw new RuntimeException("传入的数据类型有误!");
}
}
package com.atguigu.java;
import org.junit.Test;
import java.util.Arrays;
/**
* 一、说明:Java 中的对象,正常情况下,只能进行比较:== 或 !=,不能进行 < 或 > 操作
* 但是在实际开发中,需要对多个对象进行排序,进而需要比较对象的大小
* 如何实现:使用两个接口中的任何一个:Comparable、Comparator
*
* 二、Comparable 接口的使用
*
*
* @author lv
* @create 2020-12-14 20:48
*/
public class CompareTest {
/**
* Comparable 接口的使用,自然排序
*/
@Test
public void test2() {
Goods[] arrs = new Goods[5];
arrs[0] = new Goods("lenovoMouse", 34);
arrs[1] = new Goods("dellMouse", 43);
arrs[2] = new Goods("xiaomiMouse", 12);
arrs[3] = new Goods("huaweiMouse", 65);
arrs[4] = new Goods("laMouse", 34);
Arrays.sort(arrs); // error
// Goods cannot be cast to java.lang.Comparable
System.out.println(Arrays.toString(arrs));
}
/**
* Comparable 接口的使用
* compareTo()
* 1.像 String、包装类等 实现了 Comparable接口,重写了 compareTo(obj)方法
* 给出了比较两个对象大小的方式
*
* 2.像 String、包装类等 重写 compareTo()方法后,进行了从小到大排序
*
* 3.重写 compareTo(obj) 的规则:
* - 如果当前对象 this大于 形参对象 obj,则返回正整数
* - 如果当前对象 this小于 形参对象 obj,则返回负整数
* - 如果当前对象 this等于 形参对象 obj,则返回零
*
*/
@Test
public void test1() {
String[] strArr = new String[]{"AA", "CC", "MM", "KK", "GG", "JJ", "DD"};
Arrays.sort(strArr);
System.out.println(Arrays.toString(strArr)); // [AA, CC, DD, GG, JJ, KK, MM]
}
}
Comparator 接口,定制排序
java.util.Comparator
- 当元素的类型没有实现 java.util.Comparable接口而又不方便修改代码,或者实现了 java.util.Comparable接口的排序不适合当前的操作,此时可以考虑使用 Comparator的对象来排序
- 重写比较 compare(Object o1, Object o2)方法, o1和o2的大小;返回正整数,表示 01 > 02;返回 0,表示相等;返回负整数,表示 o1 < o2。
package com.atguigu.java;
/**
* 商品类
*
* @author lv
* @create 2020-12-15 18:47
*/
public class Goods implements Comparable {
private String name;
private double price;
public Goods() {
}
public Goods(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
// 指明排序规则:价格 从低到高,再按照产品名称 从高到低
public int compareTo(Object obj) {
if (obj instanceof Goods) {
Goods goods = (Goods)obj;
// 方式一:
if (this.price > goods.price) {
return 1;
} else if (this.price < goods.price) {
return -1;
} else {
// return 0;
return -this.name.compareTo(goods.name);
}
// 方式二:
// return Double.compare(this.price, goods.price);
}
// 运行时异常可以不用处理
throw new RuntimeException("传入的数据类型有误!");
}
}
package com.atguigu.java;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
/**
* 一、说明:Java 中的对象,正常情况下,只能进行比较:== 或 !=,不能进行 < 或 > 操作
* 但是在实际开发中,需要对多个对象进行排序,进而需要比较对象的大小
* 如何实现:使用两个接口中的任何一个:Comparable、Comparator
*
* 二、Comparable 接口的使用
*
*
* @author lv
* @create 2020-12-14 20:48
*/
public class CompareTest {
/**
* Comparator 接口的使用,定制排序
*/
@Test
public void test4() {
Goods[] arrs = new Goods[6];
arrs[0] = new Goods("lenovoMouse", 34);
arrs[1] = new Goods("dellMouse", 43);
arrs[2] = new Goods("xiaomiMouse", 12);
arrs[3] = new Goods("huaweiMouse", 65);
arrs[4] = new Goods("laMouse", 34);
arrs[5] = new Goods("laMouse", 44);
Arrays.sort(arrs, new Comparator() {
// 指明排序规则:产品名称 从低到高,再按照价格 从高到低
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Goods && o2 instanceof Goods) {
Goods g1 = (Goods) o1;
Goods g2 = (Goods) o2;
if (g1.getName().equals(g2.getName())) {
return -Double.compare(g1.getPrice(), g2.getPrice());
} else {
return (g1.getName().compareTo(g2.getName()));
}
}
// return 0;
throw new RuntimeException("输入的数据类型有误!");
}
}); // error
// Goods cannot be cast to java.lang.Comparable
System.out.println(Arrays.toString(arrs));
}
@Test
public void test3() {
String[] strArr = new String[]{"AA", "CC", "MM", "KK", "GG", "JJ", "DD"};
// 使用 Comparator 排序
Arrays.sort(strArr, new Comparator<String>() {
// 按照字符串 从大到小的顺序排列
@Override
public int compare(String o1, String o2) {
if (o1 instanceof String && o2 instanceof String) {
String s1 = (String) o1;
String s2 = (String) o2;
// 从大到小排列
return -s1.compareTo(s2);
}
// return 0;
throw new RuntimeException("输入数据类型有误!");
}
});
System.out.println(Arrays.toString(strArr)); // [MM, KK, JJ, GG, DD, CC, AA]
}
}
Comparable 接口与 Comparator 接口的使用对比:
- Comparable 接口的方式一旦在实现类中编写,保证 Comparable接口实现类的对象在任何位置都可以使用(可重复使用)
- Comparator 接口的方式属于临时性的比较,需要时根据需求临时编写(一次性使用)
System 类
简介:
- System 类代表系统,系统级的很多属性和控制方法都放置在该类的内部
- 由于该类的构造器是 private的,所以无法创建该类的对象,也就是无法实例化该类;其内部的成员变量和成员方法都是 static的,所以也可以方便调用
成员变量:
- System 类内部包含 in、out和 err三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)
成员方法:
-
native long currentTimeMillis():该方法的作用是返回当前的计算机时间,时间戳
-
void exit(int status):该方法的作用是退出程序;其中 status的值为 0代表正常退出,非零代表异常退出;
使用该方法可以在图形界面编程中实现程序的退出功能等 -
void gc():该方法的作用是请求系统进行垃圾回收;至于系统是否进行垃圾回收,取决于垃圾回收算法
-
String getProperty(String key):该方法的作用是获取系统中属性名为 key的属性对应的值;系统中常见的属性名如下:
- java.version:java运行时环境版本
- java.home:java安装目录
- os.name:操作系统名称
- os.version:操作系统版本
- user.name:用户的账户名称
- user.home:用户的主目录
- user.dir:用户的当前工作目录
package com.atguigu.java;
import org.junit.Test;
/**
* 其它常用类的使用:
* 1.System
* 2.Math
* 3.BigInteger 和 BigDecimal
*
* @author lv
* @create 2020-12-15 21:10
*/
public class OtherClassTest {
@Test
public void test1() {
String jv = System.getProperty("java.version");
System.out.println("java.version: " + jv); // java.version: 1.8.0_131
String jh = System.getProperty("java.home");
System.out.println("java.home: " + jh); // java.home: D:\developer_tools\Java\jdk1.8.0_131\jre
String osName = System.getProperty("os.name");
System.out.println("os.name: " + osName); // os.name: Windows 10
String osVersion = System.getProperty("os.version");
System.out.println("os.version: " + osVersion); // os.version: 10.0
String userName = System.getProperty("user.name");
System.out.println("user.name: " + userName); // user.name: Weili
String userHome = System.getProperty("user.home");
System.out.println("user.home: " + userHome); // user.home: C:\Users\Weili
String userDir = System.getProperty("user.dir");
System.out.println("user.dir: " + userDir); // user.dir: E:\java_workspace\JavaSenior\day04
}
}
Math 类
java.lang.Math类 提供了一系列 静态方法用于科学计算;其方法的参数和返回值类型一般为 double型。
- abs:绝对值
- acos、asin、atan、cos、sin、tan:三角函数
- sqrt:平方根
- pow(double a, double b):a 的 b 次幂
- log:自然对数
- exp:e 为底指数
- max(double a, double b)
- min(double a, double b)
- random():返回 0.0到 1.0的随机数
- long round(double a):double型数据 a转换为 long型(四舍五入)
- toDegrees(double angrad):弧度 -> 角度
- toRadians(double angdeg):角度 -> 弧度
BigInteger 与 BigDecimal
BigInteger
- Integer 能存储的最大整数值为 (2^31)-1,Long能存储的最大为 (2^63)-1
- java.math 包和
BigInteger 可以表示不可变的任意精度的整数;BigInteger提供所有 Java的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。
构造器
- BigInteger(String val):根据字符串构建 BigInteger对象
BigDecimal
- 一般的 Float类 和 Double类 可以用来做科学计算或工程计算,但
在商业计算中,要求数字精度比较高,故而用到 java.math.GigDecimal类。 - BigDecimal 类支持不可变的、任意精度的有符号十进制定点数
构造器
- public BigDecimal(double val)
- public BigDecimal(String val)
常用方法
- public BigDecimal add(BigDecimal augend)
- public BigDecimal subtract(BigDecimal subtrahend)
- public BigDecimal multiply(BigDecimal multiplicand)
- public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
public class OtherClassTest {
@Test
public void test2() {
BigInteger bi = new BigInteger("6164635165465121986132612");
System.out.println(bi); // 6164635165465121986132612
BigDecimal bd = new BigDecimal("15888.466");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP)); // 1444.406
System.out.println(bd.divide(bd2, 15, BigDecimal.ROUND_HALF_UP)); // 1444.406000000000000
}
}