常用类
String类
-
**String****类:代表字符串。**Java 程序中的所有字符串字面值(如 “abc” )都作
为此类的实例实现。
-
String是一个final类,代表不可变的字符序列。
-
字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
https://i.loli.net/2021/06/12/Ps7AnfxNqwKQc8h.png
-
String对象的字符内容是存储在一个字符数组value[]中的。
-
implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[];
-
以上可见,在String类里,我们实现里两个接口,Serializable:这表示字符串是可以序列化的,Comparable:表示字符串是可以比较的
字面量实例化
package com.hyb.usualClass;
import org.junit.Test;
/**
* @program: StringTest
* @description:常用类,String
*
*
* @author: Huang Yubin
* @create: 2021-06-08 12:35
**/
public class StringTest {
@Test
public void test1(){
// 字面量赋值
String s1="abc";
s1+="1";
System.out.println(s1);
/*可见我们可以给字符串更改值,但是从内存结构来讲,abc是没有被改变的,只是将abc1这个值赋值给了s1
* 但是abc1从哪来的呢?只是从常量池里找来的,并不是在原来的abc上加过来的*/
/*--------------------------------*/
String s2="abc";
String s3=s2.replace("a","c");
System.out.println(s3);
// cbc
/*在这里原理也是一样,我们将a用c代替,只是创造了一个新的常亮cbc,而不是将原来abc修改了*/
/*在这里我们便能总结出一个道理:
* 字符串本质上是不可变的 */
}
}
new关键字实例化
@Test
public void test2(){
String s1="abc";
String s2="abc";
String s3=new String("abc");
String s4=new String("abc");
System.out.println(s1==s2);//true,因为常量值是一定的,不可改变,当然,地址可能不一样
System.out.println(s1==s3);//false,对象存储在堆中,abc存在常量池中,地址可能改变
System.out.println(s3 == s4);//false,对象比较是地址
System.out.println(s1 == s4);//false
/*但是这里可说明一点,当我们用同一个类new两个对象比较两个相等的字符串时,==符号便可以比较的
* 因为我们new了两个对象在堆空间中造了两个地址,但是这两个相等的字符串是在常量池里的,不可改变*/
/*---------------*/
/*面试题里,一般都会问String s3=new String("abc");创建了几个对象?
* 可知,有两个。
* 一个是堆空间里的,一个是常量池里的*/
}
https://i.loli.net/2021/06/12/ONm7hq2HW1I6uAY.png
https://i.loli.net/2021/06/12/jreEBhJbDmH62lC.png
https://i.loli.net/2021/06/12/VQms7Nonctwhqpv.png
区别
@Test
public void test3(){
String s1="abc";
String s2="abc";
String s3=s1+s2;
String s4="abcabc";
String s5=s1+"abc";
System.out.println(s1 == s2);//true常量池的常量不可变
System.out.println(s1 == s3);//false内容都不等
System.out.println(s3 == s4);//false s4在常量池里,而s3在堆里创建了一个对象,让s1+s2
System.out.println(s4 == s5);//false 也一样
String s6=(s3).intern();
System.out.println(s6==s4);//ture,intern()返回常量池
/*我们就此可以总结出:
* 1.常亮与常亮的拼接是返回常亮池的,且常量池里没有相同的常亮
* 2.只要其中有一个是变量,结果就在堆中
* 3.如果用intern方法,结果会返回常量池*/
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yMdbNMLb-1647786099625)(C:\Users\黄渝斌\Desktop\5.png)]
面试题1
package com.hyb.usualClass;
/**
* @program: InterviewProblem
* @description:
* @author: Huang Yubin
* @create: 2021-06-08 13:43
**/
public class InterviewProblem1 {
String str = new String("good");
char[] ch = { 't', 'e', 's', 't' };
public void change(String str, char ch[]) {
str = "test ok";
ch[0] = 'b';
}
public static void main(String[] args) {
InterviewProblem1 ex = new InterviewProblem1();
ex.change(ex.str, ex.ch);
System.out.println(ex.str);//good
System.out.println(ex.ch);//best
}
/*good是一个字符串,字符串是无法改变的,所以输出good,也可以这样理解,java是值传递的,改变不了str
* ch是一个数组,数组是可变的,自然可以改变*/
}
常用方法
https://i.loli.net/2021/06/12/bS7ZalCqFNMjOnG.png
https://i.loli.net/2021/06/12/MnAPZ5Rgu3TbUla.png
https://i.loli.net/2021/06/12/AluWXjTYt7KLiI3.png
String与基本数据类型的转换
-
字符串 -> 基本数据类型、包装类
-
Integer包装类的public static int parseInt(String s):可以将由“数字”字
符组成的字符串转换为整型。
-
类似地,使用java.lang包中的Byte、Short、Long、Float、Double类调相应
的类方法可以将由“数字”字符组成的字符串,转化为相应的基本数据类型。
-
-
基本数据类型、包装类 -> 字符串
-
调用String类的public String **valueOf(int n)**可将int型转换为字符串
-
相应的valueOf(byte b)、valueOf(long l)、valueOf(float f)、valueOf(double
d)、valueOf(boolean b)可由参数的相应类型到字符串的转换
-
-
字符数组 -> 字符串
-
String 类的构造器:String(char[]) 和 String(char[],int offset,int
length) 分别用字符数组中的全部字符和部分字符创建字符串对象。
String s2=new String(Arry); System.out.println(s2);//abc
-
-
字符串->转为为字符数组
-
**public char[] toCharArray()**将字符串中的全部字符存放在一个字符数组
中的方法。
-
public void getChars(int srcBegin, int srcEnd, char[] dst,
**int dstBegin)**提供了将指定索引范围内的字符串存放到数组中的方法。
String s1="abc"; char[] Arry=s1.toCharArray(); for (int i = 0; i < s1.length(); i++) { System.out.println(Arry[i]); }
-
-
字符串->字符数组
-
public byte[] getBytes() **:**使用平台的默认字符集将此 String 编码为
byte 序列,并将结果存储到一个新的 byte 数组中。
-
public byte[] getBytes(String charsetName) **:**使用指定的字符集将
此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。
String s1="abc中国"; byte[] s2=s1.getBytes();
-
-
字节数组 -> 字符串
-
String(byte[],int offset,**int length) **用指定的字节数组的一部分,
即从数组起始位置offset开始取length个字节构造一个字符串对象。
-
String(byte[],int offset,int length) 用指定的字节数组的一部分,
即从数组起始位置offset开始取length个字节构造一个字符串对象。
String s = new String(s2);
-
@Test
public void test5() throws UnsupportedEncodingException {
// 编码
String s1="abc中国";
byte[] s2=s1.getBytes();
System.out.println(Arrays.toString(s2));
// [97, 98, 99, -28, -72, -83, -27, -101, -67]UTF_8
byte[] s3=s1.getBytes("gbk");
System.out.println(Arrays.toString(s3));
// [97, 98, 99, -42, -48, -71, -6]jbk
// 解码
String s = new String(s2);
System.out.println(s);
// abc中国
String gbk = new String(s3, "gbk");
System.out.println(gbk);
// abc中国
}
}
StringBuffer类
- 可变的字符序列
//API
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
String s = new String("我喜欢学习");
StringBuffer buffer = new StringBuffer("我喜欢学习");
buffer.append("数学");
//我喜欢学习数学
https://i.loli.net/2021/06/12/mT6SBo4LcyHfCFN.png
-
JDK1.0中声明,可以对字符
串内容进行增删,此时不会产生新的对象。
-
很多方法与String相同。
-
作为参数传递时,方法内部可以改变值。
-
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 String substring(int start,int end):把[start,end)位置替换为str
-
public void setCharAt(int n ,char ch):将指定位置字符改变
-
public char charAt(int n ):获取某一个位置字符
-
增:append(xxx)
-
删: delete(int start,int end)
-
改: replace(int start, int end, String str):把[start,end)位置替换为str。
substring(int start,int end):把[start,end)位置替换为str
setCharAt(int n ,char ch):将指定位置字符改变
-
查:charAt(int n ):获取某一个位置字符
-
插: insert(int offset, xxx):在指定位置插入xxx
-
长度:length()
-
遍历:for+查
StringBuilder类
-
StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且
提供相关功能的方法也一样
面试题2
对比String、StringBuffer、StringBuilder
-
String(JDK1.0):不可变字符序列
-
StringBuffer(JDK1.0):可变字符序列、效率低、线程安全
-
StringBuilder(JDK 5.0):可变字符序列、效率高、线程不安全
-
作为参数传递的话,方法内部String不会改变其值,StringBuffer和StringBuilder
会改变其值。
-
底层都使用char数组存储。
String S1=new String();//value =new char[0] String s1=new String("abc")//value new char[]{'a','b','c'} StringBuffer s1=new StringBuffer();//value =new char[16]底层创建了一个长度为16的数组 s1.append('a');//value[0]='a'; StringBuffer s1=new StringBuffer("abc")//value =new char["abc".length()+16]扩容
-
输出三者的长度时:
String:就是当前length
StringBuffer:也是当前length,虽然底层创建了16长度的数组,但是返回的length是根据当前length返回的
StingBuffer都一样。
-
扩容问题:
如果添加的数据底层装不下,那么需要将底层的数组扩容,默认下,每次扩容两倍,将原来的数组赋值到新的数组里
**StringBuffer(int)**可指定底层数组容量
-
关于三者执行时间的比较:StringBuilder<StringBuffer<String
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
点击图片链接:https://i.loli.net/2021/06/12/7kdIqz4jSFRX325.png
java.lang.System类
-
System类提供的public static long currentTimeMillis()用来返回当前时
间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差,俗称时间戳。
-
计算世界时间的主要标准有:
-
UTC(Coordinated Universal Time)
-
GMT(Greenwich Mean Time)
-
CST(Central Standard Time)
-
java.util.Date类
-
表示特定的瞬间,精确到毫秒
-
**Date()**使用无参构造器创建的对象可以获取本地当前时间。
-
Date(long 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是时间标准。
-
其它很多方法都过时了。
import java.util.Date;
Date date = new Date();
System.out.println(date);
System.out.println(System.currentTimeMillis());
System.out.println(date.getTime());
Date date1 = new Date(date.getTime());
System.out.println(date1.getTime());
System.out.println(date1.toString());
-
子类java.sql.Date,一般方法如父类一样。
-
其子类转化为父类,直接强转,多态便可以进行
但是父类转化为子类,要用到中间值,也就是时间戳(毫秒数)。
Date date=new Date(); java.sql.Date date1=new java.sql.Date(date.getTime());
java.text.SimpleDateFormat类(日期格式化)
-
Date类的API不易于国际化,大部分被废弃了,java.text.SimpleDateFormat
类是一个不与语言环境有关的方式来格式化和解析日期的具体类。
-
格式化:将一个日期转化为字符串
-
SimpleDateFormat() :默认的模式和语言环境创建对象
-
**public SimpleDateFormat(String pattern)**该构造方法可以用参数pattern
指定的格式创建一个对象,该对象调用:
-
**public String format(Date date)**方法格式化时间对象date
-
package com.hyb.usualClass;
import javafx.scene.input.DataFormat;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @program: StringBuffter
* @description:
* @author: Huang Yubin
* @create: 2021-06-08 14:46
**/
public class DateTest {
@Test
public void test1() throws ParseException {
Date date = new Date();
/*默认格式化*/
SimpleDateFormat sdf1 = new SimpleDateFormat();
System.out.println(sdf1.format(date));
// 21-6-8 下午4:27
/*解析*/
System.out.println(sdf1.parse("21-6-8 下午4:27"));
// Tue Jun 08 16:27:00 CST 2021
/*API自定义格式化*/
SimpleDateFormat syf2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println(syf2.format(date));
// 2021-06-08 04:32:57
/*解析*/
System.out.println(syf2.parse("2021-06-08 04:32:57"));
// Tue Jun 08 04:32:57 CST 2021
}
}
**java.util.Calendar(**日历类)
-
抽象类,无法直接实例化
-
使用子类GregorianCalendar实例化,或者调用方法用Calendar.getInstance()
-
常用方法
-
通过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)
-
package com.hyb.usualClass;
import javafx.scene.input.DataFormat;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* @program: StringBuffter
* @description:
* @author: Huang Yubin
* @create: 2021-06-08 14:46
**/
public class DateTest {
@Test
public void test2(){
GregorianCalendar date1 = new GregorianCalendar();
// get,获取日历信息
System.out.println(date1.get(Calendar.DAY_OF_MONTH));//六月份第八天
// set改变时间
date1.set(Calendar.DAY_OF_MONTH,9);
System.out.println(date1.get(Calendar.DAY_OF_MONTH));//变成六月份第九天
// getTime
System.out.println(date1.getTime());//Wed Jun 09 17:04:37 CST 2021
// setTime
Date date = new Date();
date1.setTime(date);
System.out.println(date1.get(Calendar.DAY_OF_MONTH));//这个月第八天
}
}
- 注意:
-
获取月份时:一月是0,二月是1,以此类推,12月是11
-
获取星期时:周日是1,周二是2 , 。。。。周六是7
JDK8中新日期时间API
问题引入
-
如果我们可以跟别人说:“我们在1502643933071见面,别晚了!”那么就再简单不
过了。但是我们希望时间与昼夜和四季有关,于是事情就变复杂了。JDK 1.0中包含了
一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用
了。而Calendar并不比Date好多少。它们面临的问题是:
可变性:像日期和时间这样的类应该是不可变的。
偏移性:Date中的年份是从1900开始的,而月份都从0开始。
格式化:格式化只对Date有用,Calendar则不行。
此外,它们也不是线程安全的;不能处理闰秒等。
总结:对日期和时间的操作一直是Java程序员最痛苦的地方之一。
-
java.time – 包含值对象的基础包
java.time.chrono – 提供对不同的日历系统的访问
java.time.format – 格式化和解析时间和日期
java.time.temporal – 包括底层框架和扩展特性
java.time.zone – 包含时区支持的类
说明:大多数开发者只会用到基础包和format包,也可能会用到temporal包。因此,尽
管有68个新的公开类型,大多数开发者,大概将只会用到其中的三分之一。
LocalDate、LocalTime、LocalDateTime 类
-
LocalDate、LocalTime、LocalDateTime 类是其中较重要的几个类,它们的实例
是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。
它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区
相关的信息。
-
LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。
-
LocalTime表示一个时间,而不是日期。
-
LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一。
-
-
now() / * now(ZoneId zone) 静态方法,根据当前时间创建对象/指定时区的对象
LocalDateTime now = LocalDateTime.now();//不可变
-
of() 静态方法,根据指定日期/时间创建对象,无偏移量
LocalDateTime of=LocalDateTime.of(2021,6,8,19,15); System.out.println(of); // 021-06-08T19:15
-
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()
向当前对象添加几天、几周、几个月、几年、几小时
instant
-
时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间
戳。
-
(1 ns = 10-9 s) 1秒 = 1000毫秒 =106微秒=109纳秒
-
now() 静态方法,返回默认UTC时区的Instant类的对象
Instant now = Instant.now(); System.out.println(now); // 2021-06-08T11:22:25.183Z伦敦时间
可见我们得到的是伦敦时间,那么就要转变为北京时间,得了解世界的时区分布。
https://i.loli.net/2021/06/12/FlLirNt8xk6n1Oh.png
我们在东八区,那么就要将偏移量算上去。
-
atOffset(ZoneOffset offset) 结合即时的偏移来创建一个 OffsetDateTime
OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.ofHours(8)); System.out.println(offsetDateTime); // 2021-06-08T11:28:57.438Z // 2021-06-08T19:28:57.438+08:00
-
ofEpochMilli(long epochMilli) 静态方法,返回在1970-01-01 00:00:00基础上加上指定毫秒数之后的Instant类的对象
Instant instant = now.ofEpochMilli(100002L); System.out.println(instant); // 1970-01-01T00:01:40.002Z
-
toEpochMilli() 返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳
System.out.println(now.toEpochMilli()); // 1623152010594
java.time.format.DateTimeFormatter
-
该类提供三种格式化:
-
预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
该定义不会改变原来LocalDate、LocalTime、LocalDateTime的格式,只是一个标准格式,改成了字符串类型而已。
DateTimeFormatter formater=DateTimeFormatter.ISO_DATE_TIME; LocalDateTime now = LocalDateTime.now(); // 格式化 System.out.println(now); System.out.println(formater.format(now)); // 2021-06-08T19:45:13.776 // 2021-06-08T19:45:13.776 // 解析 System.out.println(formater.parse("2021-06-08T19:45:13.776")); // {},ISO resolved to 2021-06-08T19:45:13.776
-
本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
-
自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)(重点)
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"); System.out.println(dateTimeFormatter.format(LocalDateTime.now())); // 2021-06-08 07:59:00
请点击链接查看图片:https://i.loli.net/2021/06/12/VyqMbuYwozEZspG.png
其他API
-
ZoneId**:**该类中包含了所有的时区信息,一个时区的ID,如 Europe/Paris
-
ZonedDateTime**:**一个在ISO-8601日历系统时区的日期时间,如 2007-12-03T10:15:30+01:00 Europe/Paris。 其中每个时区都对应着ID,地区ID都为“{区域}/{城市}”的格式,例如:Asia/Shanghai等
-
Clock**:**使用时区提供对当前即时、日期和时间的访问的时钟。
-
持续时间:Duration,用于计算两个“时间”间隔
-
日期间隔:Period,用于计算两个“日期”间隔
-
TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下一个工作日”等操作。
-
TemporalAdjusters : 该类通过静态方法(firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用TemporalAdjuster 的实现。
//ZoneId:类中包含了所有的时区信息
// ZoneId的getAvailableZoneIds():获取所有的ZoneId
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
for (String s : zoneIds) {
System.out.println(s);
}
// ZoneId的of():获取指定时区的时间
LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println(localDateTime);
//ZonedDateTime:带时区的日期时间
// ZonedDateTime的now():获取本时区的ZonedDateTime对象
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println(zonedDateTime);
// ZonedDateTime的now(ZoneId id):获取指定时区的ZonedDateTime对象
ZonedDateTime zonedDateTime1 = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println(zonedDateTime1);
//9.3 JDK8中新日期时间API
//Duration:用于计算两个“时间”间隔,以秒和纳秒为基准
LocalTime localTime = LocalTime.now();
LocalTime localTime1 = LocalTime.of(15, 23, 32);
//between():静态方法,返回Duration对象,表示两个时间的间隔
Duration duration = Duration.between(localTime1, localTime);
System.out.println(duration);
System.out.println(duration.getSeconds());
System.out.println(duration.getNano());
LocalDateTime localDateTime = LocalDateTime.of(2016, 6, 12, 15, 23, 32);
LocalDateTime localDateTime1 = LocalDateTime.of(2017, 6, 12, 15, 23, 32);
Duration duration1 = Duration.between(localDateTime1, localDateTime);
System.out.println(duration1.toDays());
//Period:用于计算两个“日期”间隔,以年、月、日衡量
LocalDate localDate = LocalDate.now();
LocalDate localDate1 = LocalDate.of(2028, 3, 18);
Period period = Period.between(localDate, localDate1);
System.out.println(period);
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());
Period period1 = period.withYears(2);
System.out.println(period1)
// TemporalAdjuster:时间校正器
// 获取当前日期的下一个周日是哪天?
TemporalAdjuster temporalAdjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);
LocalDateTime localDateTime = LocalDateTime.now().with(temporalAdjuster);
System.out.println(localDateTime);
// 获取下一个工作日是哪天?
LocalDate localDate = LocalDate.now().with(new TemporalAdjuster() {
@Override
public Temporal adjustInto(Temporal temporal) {
LocalDate date = (LocalDate) temporal;
if (date.getDayOfWeek().equals(DayOfWeek.FRIDAY)) {
return date.plusDays(3);
} else if (date.getDayOfWeek().equals(DayOfWeek.SATURDAY)) {
return date.plusDays(2);
} else {
return date.plusDays(1);
} }
});
System.out.println("下一个工作日是:" + localDate);
}
请点击链接:https://i.loli.net/2021/06/12/5FUdwORe1jMv7iY.png
JAVA比较器
自然排序
-
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 的典型实现:(默认都是从小到大排列的) :
-
String:按照字符串中字符的Unicode值进行比较
-
Character:按照字符的Unicode值来进行比较
-
数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值
大小进行比较
-
Boolean:true 对应的包装类实例大于 false 对应的包装类实例
-
Date、Time等:后面的日期时间比前面的日期时间大
-
class Goods implements Comparable {
private String name;
private double price;
//按照价格,比较商品的大小
@Override
public int compareTo(Object o) {
if(o instanceof Goods) {
Goods other = (Goods) o;
if (this.price > other.price) {
return 1;
} else if (this.price < other.price) {
return -1;
}
return 0;
}
throw new RuntimeException("输入的数据类型不一致");
}
//构造器、getter、setter、toString()方法略
}
public class ComparableTest{
public static void main(String[] args) {
Goods[] all = new Goods[4];
all[0] = new Goods("《红楼梦》", 100);
all[1] = new Goods("《西游记》", 80);
all[2] = new Goods("《三国演义》", 140);
all[3] = new Goods("《水浒传》", 120);
Arrays.sort(all);
System.out.println(Arrays.toString(all));
}
}
定制排序
-
当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,
或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那
么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排
序的比较。
-
重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返
回正整数,则表示o1大于o2**;如果返回0,表示相等;返回负整数,表示**
o1小于o2。
-
可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),
从而允许在排序顺序上实现精确控制。
-
还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的
顺序,或者为那些没有自然顺序的对象 collection 提供排序。
Goods[] all = new Goods[4];
all[0] = new Goods("War and Peace", 100);
all[1] = new Goods("Childhood", 80);
all[2] = new Goods("Scarlet and Black", 140);
all[3] = new Goods("Notre Dame de Paris", 120);
Arrays.sort(all, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Goods g1 = (Goods) o1;
Goods g2 = (Goods) o2;
return g1.getName().compareTo(g2.getName());
}
});
System.out.println(Arrays.toString(all));
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的属性对应的值。系统中常见
的属性名以及属性的作用如下表所示:
https://i.loli.net/2021/06/12/tHanPeMzOKCAoSd.png
-
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);
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与BigDecimal
-
Integer类作为int的包装类,能存储的最大整型值为2 31-1,Long类也是有限的,
最大为2 63-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类
都无能为力,更不用说进行运算了。
-
java.math包的BigInteger****可以表示不可变的任意精度的整数。BigInteger 提供
所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。
另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、
位操作以及一些其他操作。
-
构造器 BigInteger(String val):根据字符串构建BigInteger对象
-
常用方法:
-
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)
-
public void testBigInteger() {
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));
}