字符串相关的类
String
String:字符串,使用一对""
引起来表示
- String声明为final的,不可被继承
- String实现了
- Serializable接口:表示字符串是支持序列化的
- Comparable接口:表示String可以比较大小
- String内部定义了final char[] value用于存储字符串数据
- String:代表不可变的字符序列,简称:不可变性
- 当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值
- 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
- 当调用String的replace() 方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
- 通过字面量的方式(区别与new)给一个字符串赋值,此时的字符串值声明在字符串常量池中
- 字符串常量池中不会存储相同内容的字符串的
String不同实例化方法的对比
String str = "hello";
//本质上 this.value = new char[0]; new了一个长度是0的char
String s1 = new String();
//this.value = original.value;
String s2 = new String(String original);
String s2 = new String("hello");
//this.value = Arrays.copyOf(value, value.length);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
String str1 = "hello";
和 String str2 = new String("hello");
的区别?
字符串常量存储在字符串常量池,目的是共享
字符串非常量对象存储在堆中
public class StringTest {
public static void main(String[] args) {
//通过字面量定义的方式:此时s1和s2的数据 hello 声明在方法区中的字符串常量池中
String s1 = "hello";
String s2 = "hello";
//通过new+构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s1 == s2); //true
System.out.println(s1 == s3); //false
System.out.println(s1 == s4); //false
System.out.println(s3 == s4); //false
}
}
面试题
String s = new String("abc");方式创建对象,在内存中创建了几个对象?
两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:"abc"
String的不同拼接操作
public class StringTest {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = "hello" + "world";
String s5 = s1 + "world";
String s6 = "hello" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4); //true
System.out.println(s3 == s5); //false
System.out.println(s3 == s6); //false
System.out.println(s3 == s7); //false
System.out.println(s5 == s6); //false
System.out.println(s5 == s7); //false
System.out.println(s6 == s7); //false
String s8 = s5.intern();
System.out.println(s3 == s8); //true
final String s9 = "hello";
String s10 = s9 + "world";
System.out.println(s3 == s10); //true 这里特别注意,加了final之后是常量
}
}
结论:
- 常量与常量的拼接结果在常量池中。且常量池中不会存在相同内容的常量。
- 只要其中有一个是变量,结果就在堆中
- 如果拼接的结果调用intern()方法,返回值就在常量池中
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)
:返回一个新的字符串,它是此字符串的从beginIndex
开始截取到最后的一个子字符串String substring(int beginIndex, int endIndex)
:返回一个新字符串,它是此字符串从beginIndex
开始截取到endIndex(不包含)
的一个子字符串
public class StringTest {
public static void main(String[] args) {
String s1 = "hellowoRld";
System.out.println(s1.length()); //10
System.out.println(s1.charAt(0)); //h
// System.out.println(s1.charAt(10)); //报错
System.out.println(s1.isEmpty()); //false
String s2 = s1.toLowerCase();
System.out.println(s1 + s2); //hellowoRldhelloworld,s1本身不变
String s3 = " he llo world ";
String s4 = s3.trim();
System.out.println(s3 + "|" + s4); // he llo world |he llo world
String s5 = "helloworld";
String s6 = "HELLOWORLD";
System.out.println(s5.equals(s6)); //false
System.out.println(s5.equalsIgnoreCase(s6)); //true
String s7 = "hello";
String s8 = s7.concat("world");
System.out.println(s8);
String s9 = "abc";
String s10 = new String("abe"); //-2
System.out.println(s9.compareTo(s10)); //涉及到字符串排序
String s11 = "helloworld";
String s12 = s11.substring(2);
System.out.println(s12); //lloworld
String s13 = s11.substring(2,5);
System.out.println(s13); //llo
}
}
boolean endsWith(String suffix)
:测试此字符串是否以指定的后缀结束boolean startsWith(String prefix)
:测试此字符串是否以指定的前缀开始boolean startsWith(String prefix, int toffset)
:测试此字符串从指定索引开始的 子字符串是否以指定前缀开始boolean contains(CharSequence s)
:当且仅当此字符串包含指定的 char 值序列 时,返回 trueint indexOf(String str)
:返回指定子字符串在此字符串中第一次出现处的索引int indexOf(String str, int fromIndex)
:返回指定子字符串在此字符串中第一次出 现处的索引,从指定的索引开始int lastIndexOf(String str)
:返回指定子字符串在此字符串中最右边出现处的索引int lastIndexOf(String str, int fromIndex)
:返回指定子字符串在此字符串中最后 一次出现处的索引,从指定的索引开始反向搜索
注:indexOf和lastIndexOf方法如果未找到都是返回-1
public class StringTest {
public static void main(String[] args) {
String s1 = "hellowoRld";
boolean b1 = s1.endsWith("ld");
System.out.println(b1); //true
boolean b2 = s1.startsWith("hee");
System.out.println(b2); //false
boolean b3 = s1.startsWith("ll",2);
System.out.println(b3); //true
System.out.println(s1.contains("wo")); //true
System.out.println(s1.indexOf("l")); //2,三个l取第一个的index
System.out.println(s1.indexOf("lol")); //-1
System.out.println(s1.indexOf("lo", 5)); //woRld 里面灭有 lo,-1
System.out.println(s1.lastIndexOf("l")); // 8,三个l取最后一个的index
System.out.println(s1.lastIndexOf("ow",3)); //-1,找到是hell里面有没有ow
System.out.println(s1.lastIndexOf("ow",6)); //4
}
}
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个,如果超过了,剩下的全部都放到最后一个元素中。
import org.junit.Test;
public class StringMethodTest {
/**
* 替换:
* 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个,如果超过了,剩下的全部都放到最后一个元素中。
*
*/
@Test
public void test4(){
String str1 = "西藏布达拉宫欢迎您";
String str2 = str1.replace('西','东');
System.out.println(str1);
System.out.println(str2);
String str3 = str1.replace("北京", "南京");
System.out.println(str3);
System.out.println("*************************");
String str = "12hello34world5java7891mysql456";
//把字符串中的数字替换成,,如果结果中开头和结尾有,的话去掉
String string = str.replaceAll("\\d+", ",").replaceAll("^,|,$", "");
System.out.println(string);
System.out.println("*************************");
str = "12345";
//判断str字符串中是否全部有数字组成,即有1-n个数字组成
boolean matches = str.matches("\\d+");
System.out.println(matches);
String tel = "0571-4534289";
//判断这是否是一个杭州的固定电话
boolean result = tel.matches("0571-\\d{7,8}");
System.out.println(result);
System.out.println("*************************");
str = "hello|world|java";
String[] strs = str.split("\\|");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
System.out.println();
str2 = "hello.world.java";
String[] strs2 = str2.split("\\.");
for (int i = 0; i < strs2.length; i++) {
System.out.println(strs2[i]);
}
}
}
String 的相互转换
String与基本数据类型转
String --> 基本数据类型、包装类:调用包装类的静态方法:parseXxx(str)
基本数据类型、包装类 --> String:调用String 重载的valueOf(xxx)
public class StringTest {
public static void main(String[] args) {
String str1 = "123";
// int num = (int)str1; //这样写是错误的。怀念python
int num = Integer.parseInt(str1);
String str2 = String.valueOf(num);
String str3 = num + "";
}
}
String 与 char[] 之间的转换
public class StringTest {
public static void main(String[] args) {
// String --> char[]:调用 String 的 toCharArray()
String str1 = "abc123";
char[] charArray = str1.toCharArray();
for (int i = 0; i < charArray.length; i++) {
// for (int i = 0; i < charArray.length; i++) {
System.out.println(charArray[i]);
}
char[] arr = new char[]{'h', 'e', 'l', 'l', 'o'};
String str2 = new String(arr);
System.out.println(str2); //hello
}
}
String 与 byte[] 之间的转换
编码:String --> byte[]:调用String的getBytes()
解码:byte[] --> String:调用String的构造器
public class StringTest {
public static void main(String[] args) throws UnsupportedEncodingException {
String str1 = "abc123中国";
byte[] bytes = str1.getBytes(); //使用默认的字符集,进行编码
System.out.println(Arrays.toString(bytes)); //[97, 98, 99, 49, 50, 51, -28, -72, -83, -27, -101, -67]
System.out.println(bytes); //[B@1b6d3586
//需要 throws UnsupportedEncodingException
byte[] gbks = str1.getBytes("gbk"); //使用gbk字符集进行编码
System.out.println(Arrays.toString(gbks));
System.out.println("-------------------------------------");
String str2 = new String(bytes); //使用默认的字符集,进行解码
System.out.println(str2);
String str3 = new String(gbks);
System.out.println(str3); //出现乱码。原因:编码集和解码集不一样
String str4 = new String(gbks,"gbk");
System.out.println(str4);
}
}
StringBuffer、StringBuilder
比较
String、StringBuffer、StringBuilder三者的异同?
String:不可变得字符序列;底层使用char[] 存储
StringBuffer:可变得字符序列;线程是安全的,效率低;底层使用char[]存储
StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储
- StringBuffer():初始容量为16的字符串缓冲区
- StringBuffer(int size):构造指定容量的字符串缓冲区
- StringBuffer(String str):将内容初始化为指定字符串内容
源码:
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的数组
sb1.append('a');//value[0] = 'a';
sb1.append('b');//value[1] = 'b';
StringBuffer sb2 = new StringBuffer("abc"); //char[] value = new char["abc".length() + 16];
问题1:System.out.println(sb2.length()); //3
问题2:扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组
默认情况下,扩容为原来容量的2倍 + 2,同时将原有数组中的元素复制到新的数组中
指导意义:开发中建议大家使用:StringBuffer(int capacity) 或 StringBuilder(int capacity)
StringBuffer常用方法
- StringBuffer
append(xxx)
:提供了很多的append()方法,用于进行字符串拼接 - StringBuffer
delete(int start,int 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)
- public int
length()
- public char
charAt(int n )
- public void
setCharAt(int n ,char ch)
:指定位置字符改成新的
public class StringTest {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("abc");
s1.append(1);
s1.append('1');
System.out.println(s1); //abc11
s1.delete(2,4); //前开后闭
System.out.println(s1); //ab1
StringBuffer s2 = new StringBuffer("abc11");
s2.replace(2,4,"hello");
System.out.println(s2); //abhello1
StringBuffer s3 = new StringBuffer("abc11");
s3.insert(2,false);
System.out.println(s3); //abfalsec11
System.out.println(s3.length()); //10
s3.reverse();
System.out.println(s3); //11ceslafba
}
}
对比String、StringBuffer、StringBuilder三者的效率
从高到低:StringBuilder > StringBuffer > String
public class StringTest {
public static void main(String[] args) {
long startTime = 0L;
long endTime = 0L;
String text = "";
StringBuffer buffer = new StringBuffer("");
StringBuilder builder = new StringBuilder("");
// 开始对比
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer的执行时间:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder的执行时间:" + (endTime - startTime));
startTime = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
text = text + i;
}
endTime = System.currentTimeMillis();
System.out.println("String的执行时间:" + (endTime - startTime));
}
}
时间日期
JDK8之前的日期时间API
java.lang.System类
public class StringTest {
public static void main(String[] args) {
long time = System.currentTimeMillis();
//返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差
//称为时间戳
System.out.println(time);
}
}
java.util.Date类
构造器
Date()
:使用无参构造器创建的对象可以获取本地当前时间。Date(long date)
:创建指定毫秒数的Date对象
方法
getTime()
:返回自 1970 年 1 月 1 日 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是时间标准。
public class StringTest {
public static void main(String[] args) {
// 构造器一:Date():创建一个对应当前时间的Date对象
Date date1 = new Date();
System.out.println(date1); //Sat Jan 15 12:58:45 CST 2022
// System.out.println(date1.toString()); //Sat Jan 15 12:58:45 CST 2022
System.out.println(date1.getTime()); //1642222725774
// 构造器二:创建指定毫秒数的Date对象
Date date2 = new Date(1642222725774L);
System.out.println(date2); //Sat Jan 15 12:58:45 CST 2022
// System.out.println(date2.toString()); //Sat Jan 15 12:58:45 CST 2022
}
}
java.sql.Date类
对应着数据库中的日期类型的变量
public class StringTest {
public static void main(String[] args) {
// 创建java.sql.Date对象
java.sql.Date date3 = new java.sql.Date(1642222725774L);
System.out.println(date3); //2022-01-15
// 如何将java.util.Date 对象转换为 java.sql.Date对象
// 情况一:
Date date4 = new java.sql.Date(1642222725774L);
java.sql.Date date5 = (java.sql.Date) date4;
// 情况二:
Date date6 = new Date();
java.sql.Date date7 = new java.sql.Date(date6.getTime());
}
}
java.text.SimpleDateFormat类
SimpleDateFormat 对日期 Date 类的格式化和解析
- SimpleDateFormat() :默认的模式和语言环境创建对象
- public SimpleDateFormat(String pattern):该构造方法可以用参数pattern 指定的格式创建一个对象,该对象调用:
格式化: 日期 -> 字符串
- public String
format(Date date)
:方法格式化时间对象date
解析:字符串 -> 日期
- public Date
parse(String source)
:从给定字符串的开始解析文本,以生成 一个日期。
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class StringTest {
public static void main(String[] args) {
//实例化 SimpleDateFormat:使用默认的构造器
SimpleDateFormat sdf = new SimpleDateFormat();
// 格式化:日期 ---> 字符串
Date date = new Date();
System.out.println(date);
String format = sdf.format(date);
System.out.println(format);
// 解析:格式化的逆过程,字符串 ---> 日期
String str = "22-1-15 下午1:50";
Date date1 = null;
try {
date1 = sdf.parse(str);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(date1);
//按照指定的方式格式化和解析:调用带参的构造器
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//格式化
String format1 = sdf1.format(date);
System.out.println(format1); //2022-01-15 01:56:15
//解析:要求字符串必须是符合SimpleDateFormat识别的格式(通过构造器参数体现),
//否则,抛异常
Date date2 = null;
try {
date2 = sdf1.parse("2022-01-15 01:56:15");
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println(date2);
}
}
java.util.Calendar(日历)类
Calendar是一个抽象基类,主用用于完成日期字段之间相互操作的功能。
实例化
- 使用
Calendar.getInstance()
方法 (用的比较多) - 调用它的子类
GregorianCalendar
的构造器。
方法
-
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
import java.util.Calendar;
import java.util.Date;
public class StringTest {
public static void main(String[] args) {
//1. 实例化
//方式一:创建其子类(GregorianCalendar)的对象
//方式二:调用其静态方法getInstance()
Calendar calendar = Calendar.getInstance();
// Calendar calendar = Calendar.getClass();
//2. 常用方法
//get()
int days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days); //比如执行代码的日期是15的话
int days2 = calendar.get(Calendar.DAY_OF_YEAR);
System.out.println(days2);
//set()
calendar.set(Calendar.DAY_OF_MONTH, 22);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days); //22
//add()
calendar.add(Calendar.DAY_OF_MONTH, 3);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days); //15+3,这里打印18
calendar.add(Calendar.DAY_OF_MONTH, -3);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days); //15-3,这里打印12
//getTime():日历类 --> Date
Date date = calendar.getTime();
System.out.println(date); //Sat Jan 22 14:25:41 CST 2022
//setTime():Date --> 日历类
Date date1 = new Date();
calendar.setTime(date1);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days); //15
}
}
JDK8的日期时间API
Local系列
LocalDate
、LocalTime
、LocalDateTime
类是其中较重要的几个类,它们的实例 是不可变的对象
,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。 它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区 相关的信息。
方法 | 描述 |
---|---|
now() / * now(ZoneId zone) | 静态方法,根据当前时间创建对象/指定时区的对象 |
of() | 静态方法,根据指定日期/时间创建对象 |
getDayOfMonth()/getDayOfYear() | 获得月份天数(1-31) /获得年份天数(1-366) |
getDayOfWeek() | 获得星期几(返回一个 DayOfWeek 枚举值) |
getMonth() | 获得月份, 返回一个 Month 枚举值 |
getMonthValue() / getYear() | 获得月份(1-12) /获得年份 |
getHour()/getMinute()/getSecond() | 获得当前对象对应的小时、分钟、秒 |
withDayOfMonth()/withDayOfYear()/ withMonth()/withYear() | 将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象 |
plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours() | 向当前对象添加几天、几周、几个月、几年、几小时 |
minusMonths() / minusWeeks()/ minusDays()/minusYears()/minusHours() | 从当前对象减去几月、几周、几天、几年、几小时 |
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class JDK8DateTimeTest {
public static void main(String[] args) {
//now():获取当前的日期、时间、日期+时间
LocalDate localdate = LocalDate.now();
LocalTime localtime = LocalTime.now();
LocalDateTime localdatetime = LocalDateTime.now();
System.out.println(localdate);
System.out.println(localtime);
System.out.println(localdatetime); //2022-01-15T14:42:28.932
//of():设置指定的年、月、日、时、分、秒。没有偏移量
LocalDateTime localDateTime1 = LocalDateTime.of(2022,10,15,14,42,22);
System.out.println(localDateTime1); //2022-10-15T14:42:22
//getXxx():获取相关的属性
System.out.println(localdatetime.getDayOfMonth()); //15 这个月的第几天
System.out.println(localdatetime.getDayOfWeek()); //SATURDAY
System.out.println(localdatetime.getDayOfYear()); // 这年的第几天
System.out.println(localdatetime.getMonth()); //JANUARY
System.out.println(localdatetime.getMonthValue()); //1 月
System.out.println(localdatetime.getMinute()); //45 分钟
//体现不可变性
//withXxx():设置相关的属性
LocalDate localdate1 = localdate.withDayOfMonth(22);
System.out.println(localdate); //2022-01-15 原来的值不变
System.out.println(localdate1); // 2022-01-22
LocalDateTime localdatetime2 = localdatetime.withHour(4);
System.out.println(localdatetime); //14 程序执行的时间,不改变
System.out.println(localdatetime2); //4
//不可变性
LocalDateTime localdatetime3 = localdatetime.plusMonths(4);
System.out.println(localdatetime); //2022-01-15T14:58:48.418 1月
System.out.println(localdatetime3); //2022-05-15T14:58:48.418 1+4=5月
LocalDateTime localdatetime4 = localdatetime.minusDays(4);
System.out.println(localdatetime); //2022-01-15T15:00:51.976
System.out.println(localdatetime4); //2022-01-11T15:00:51.976
}
}
瞬时:Instant
方法 | 描述 |
---|---|
now() | 静态方法,返回默认UTC时区的Instant类的对象 |
toEpochMilli(long epochMilli) | 静态方法,返回在1970-01-01 00:00:00基础上加上指定毫秒 数之后的Instant类的对象 |
atOffset(ZoneOffset offset) | 结合即时的偏移来创建一个 OffsetDateTime |
toEpochMilli() | 返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳 |
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class JDK8DateTimeTest {
public static void main(String[] args) {
//now():获取本初子午线对应的标准时间
Instant instant = Instant.now();
System.out.println(instant); //2022-01-15T07:09:14.801Z 这里会因为东8区的原有差8个小时
//添加时间的偏移量
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);
//toEpochMilli():获取自1970年1月1日0时0分0秒(UTC)开始的毫秒数(时间戳)
long milli = instant.toEpochMilli();
System.out.println(milli); //1642230984305
Instant instant1 = Instant.ofEpochMilli(1642230940760L);
System.out.println(instant1); //2022-01-15T07:15:40.760Z
}
}
java.time.format.DateTimeFormatter 类
格式化或解析日期、时间
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
public class JDK8DateTimeTest {
public static void main(String[] args) {
// 方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//格式化:日期 -->字符串
LocalDateTime localDateTime = LocalDateTime.now();
String s1 = formatter.format(localDateTime);
System.out.println(localDateTime); //2022-01-15T15:29:12.365
System.out.println(s1); //2022-01-15T15:29:12.365
//解析:字符串 --> 日期
TemporalAccessor parse = formatter.parse("2022-01-15T15:29:12");
System.out.println(parse); //{},ISO resolved to 2022-01-15T15:29:12
// 方式二:本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
// FormatStyle.LONG/FormatStyle.MEDIUM/FormatStyle.SHORT
// FormatStyle.SHORT
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
String s2 = formatter1.format(localDateTime);
System.out.println(localDateTime); //2022-01-15T15:36:19.999
System.out.println(s2); //22-1-15 下午3:36
// FormatStyle.LONG
DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
String s3 = formatter2.format(localDateTime);
System.out.println(localDateTime); //2022-01-15T15:36:19.999
System.out.println(s3); //2022年1月15日 下午03时38分06秒
// FormatStyle.MEDIUM
DateTimeFormatter formatter3 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
String s4 = formatter3.format(localDateTime);
System.out.println(localDateTime); //2022-01-15T15:36:19.999
System.out.println(s4); //2022-1-15 15:38:54
// 本地化相关的格式。如:ofLocalizedDate(),适用于LocalDate,但是LocalDateTime也可以
//FormatStyle.FULL/FormatStyle.LONG/FormatStyle.MEDIUM/FormatStyle.SHORT
// FormatStyle.FULL
DateTimeFormatter formatter4 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
String s5 = formatter4.format(LocalDate.now());
// String s5 = formatter4.format(LocalDateTime.now());
System.out.println(localDateTime); //2022-01-15T15:44:53.898
System.out.println(s5); //2022年1月15日 星期六
// FormatStyle.MEDIUM
DateTimeFormatter formatter5 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
String s6 = formatter5.format(LocalDate.now());
System.out.println(localDateTime); //2022-01-15T15:44:53.898
System.out.println(s6); //2022-1-15
// 方式三(重点):自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
DateTimeFormatter formatter6 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
// 格式化
String s7 = formatter6.format(LocalDateTime.now());
System.out.println(s7); //2022-01-15 03:53:36
// 解析
TemporalAccessor parse2 = formatter6.parse("2022-01-15 03:53:36");
System.out.println(parse2); //{MinuteOfHour=53, MicroOfSecond=0, HourOfAmPm=3, MilliOfSecond=0, SecondOfMinute=36, NanoOfSecond=0},ISO resolved to 2022-01-15
}
}
比较器
在java中的对象,正常情况下,只能进行比较:== 或 !=。不能使用 > 或 < 的。但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。
Java实现对象排序的方式有两种:
-
自然排序:java.lang.Comparable
-
定制排序:java.util.Comparator
Compatable接口的使用举例:自然排序
- 像String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象的方法
- 像String、包装类重写compateTo() 方法以后,进行了从小到大的排列
- 重写compareTo(obj)的规则:
- 如果当前对象this大 于形参对象obj,则返回正整数,
- 如果当前对象this小于形参对象obj,则返回 负整数,
- 如果当前对象this等于形参对象obj,则返回零。
- 对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。在compareTo(obj)方法中指明如何排序
- Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称 为类的自然排序。
- 实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即 通过 compareTo(Object obj) 方法的返回值来比较大小。
如果当前对象this大 于形参对象obj,则返回正整数,如果当前对象this小于形参对象obj,则返回 负整数,如果当前对象this等于形参对象obj,则返回零。
- 实现Comparable接口的对象列表(和数组)可以通过 Collections.sort 或 Arrays.sort进行自动排序。实现此接口的对象可以用作有序映射中的键或有 序集合中的元素,无需指定比较器。
- 对于类 C 的每一个 e1 和 e2 来说,当且仅当 e1.compareTo(e2) == 0 与 e1.equals(e2) 具有相同的 boolean 值时,类 C 的自然排序才叫做与 equals 一致。建议(虽然不是必需的)最好使自然排序与 equals 一致。
自定义类实现Comparable自然排序
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 +
'}';
}
//指明商品比较大小的方式:按照价格从低到高排序
@Override
public int compareTo(Object o) {
if (o instanceof Goods){
Goods goods = (Goods) o;
//方式一:自己写
if (this.price > goods.price){
return 1;
}else if (this.price < goods.price){
return -1;
}else {
//指明商品比较大小的方式:按照价格从低到高排序,这直接return 0
// return 0;
//指明商品比较大小的方式:按照价格从低到高排序,再按照产品名称从低到高排序
return this.name.compareTo(goods.name);
//指明商品比较大小的方式:按照价格从低到高排序,再按照产品名称从高到低排序
// return -this.name.compareTo(goods.name);
}
//方式二:调用 Double包装类
// return Double.compare(this.price, goods.price)
}
//return 0
throw new RuntimeException("传入的数据类型不一致!");
}
}
public class CompareTest {
public static void main(String[] args) {
Goods[] arr = new Goods[4];
arr[0] = new Goods("lenovoMouse",34);
arr[1] = new Goods("dellMouse",24);
arr[2] = new Goods("xiaomiMouse",14);
arr[3] = new Goods("huaweiMouse",44);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
定制排序:Comparator
当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码, 或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那 么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排 序的比较。
重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
-
如果方法返 回正整数,则表示o1大于o2;
-
如果返回0,表示相等;
-
返回负整数,表示 o1小于o2。
import java.util.Arrays;
import java.util.Comparator;
public class CompareTest {
public static void main(String[] args) {
String[] arr = new String[]{"AA","CC","MM","GG","JJ","DD"};
Arrays.sort(arr, new Comparator() {
//按照字符串从大到小的顺序排列
@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(arr));
}
}
在已经有Comparable的情况下
import java.util.Arrays;
import java.util.Comparator;
public class CompareTest {
public static void main(String[] args) {
Goods[] arr = new Goods[4];
arr[0] = new Goods("lenovoMouse",34);
arr[1] = new Goods("dellMouse",24);
arr[2] = new Goods("xiaomiMouse",14);
arr[3] = new Goods("huaweiMouse",44);
Arrays.sort(arr, 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());
}
}
throw new RuntimeException("输入的数据类型不一致");
}
});
System.out.println(Arrays.toString(arr));
}
}
Comparable 接口与Compatator 的使用的对比:
Comparable 接口的方式一旦确定,保证Comparable 接口实现类的对象在任何位置都可以比较大小
Comparator接口属于临时性的比较
System 类
-
System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。 该类位于java.lang包。
-
由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实 例化该类。其内部的成员变量和成员方法都是static的,所以也可以很方便 的进行调用。
-
成员变量
- System类内部包含in、out和err三个成员变量,分别代表标准输入流 (键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
-
成员方法
native long currentTimeMillis()
: 该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时 间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。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.hone | 用户的主目录 |
user.dir | 用户的当前工作目录 |
public class OtherClassTest {
public static void main(String[] args) {
String javaVersion = System.getProperty("java.version");
System.out.println("java的version:" + javaVersion);
String javaHome = System.getProperty("java.home");
System.out.println("java的home:" + javaHome);
String osName = System.getProperty("os.name");
System.out.println("os的name:" + osName);
String osVersion = System.getProperty("os.version");
System.out.println("os的version:" + osVersion);
String userName = System.getProperty("user.name");
System.out.println("user的name:" + userName);
String userHome = System.getProperty("user.home");
System.out.println("user的home:" + userHome);
String userDir = System.getProperty("user.dir");
System.out.println("user的dir:" + userDir);
}
}
>>>
java的version:1.8.0_311
java的home:C:\Program Files\Java\jdk1.8.0_311\jre
os的name:Windows 10
os的version:10.0
user的name:dongye
user的home:C:\Users\dongye
user的dir:E:\codeexercise\java\exec2
Math类
java.lang.Math提供了一系列静态方法用于科学计算。其方法的参数和返回 值类型一般为double型。
-
abs 绝对值
-
acos,asin,atan,cos,sin,tan 三角函数
-
sqrt 平方根
-
pow(double a,doble 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类
- Integer类作为int的包装类,能存储的最大整型值为2^31-1,Long类也是有限的, 最大为2 63-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类 都无能为力,更不用说进行运算了。
- java.math包的
BigInteger可以表示不可变的任意精度的整数
。BigInteger 提供 所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。 另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、 位操作以及一些其他操作。
常用方法
- public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger。
- BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger
- BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger
- BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。整数 相除只保留整数部分。
- BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的 BigInteger。
- BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟 (this % val) 的两个 BigInteger 的数组。
- BigInteger pow(int exponent) :返回其值为 (thisexponent) 的 BigInteger。
BigDecimal类
- 一般的Float类和Double类可以用来做科学计算或工程计算,但在
商业计算中, 要求数字精度比较高,故用到java.math.BigDecimal类。
- 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)
import java.math.BigDecimal;
import java.math.BigInteger;
public class OtherClassTest {
public static void main(String[] args) {
BigInteger bi = new BigInteger("12433241123");
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bi);
// System.out.println(bd.divide(bd2));
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2, 15, BigDecimal.ROUND_HALF_UP));
}
}
>>>
12433241123
1130.486
1130.486454545454545