String:字符串,使用一对""引起来表示
String声明为final的,不可被继承
Sting实现了Serializable接口:表示字符串是支持序列化的
实现了Comparable接口:表示String可以比较大小
String内部定义了final char[] value用于存储字符串数据
String:代表不可变的字符序列。简称:不可变性
体现:
1.当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值
2.当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。字符串常量池中是不会存储相同内容的字符串的。
3.当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
public class StringTest {
@Test
public void test1() {
String s1 = "abc"; //字面量的定义方式
String s2 = "abc";
s1 = "hello";
System.out.println(s1 == s2); //比较s1和s2地址值是否相同,false
System.out.println(s1); //hello
System.out.println(s2); //abc
System.out.println("************");
String s3 = "abc";
s3 += "def";
System.out.println(s3); //abcdef
System.out.println(s2);
System.out.println("************");
String s4 = "abc";
String s5 = s4.replace('a', 'm');
System.out.println(s4); //abc
System.out.println(s5); //mbc
}
}
String 的实例化方式:
方式一:通过字面量定义的方式
方式二:通过new+构造器的方式
String str=“hello”;
String s1=new String(); //本质上 this.value=new char[0];
String s2=new String(String original); //本质上this.value=original.value;
String s3=new String(char[] a); //本质上this.value=Arrays.copyOf(value,value.length);
String s4=new String(char[] a,int startIndex,int count);
String不同实例化方式的对比
@Test
public void test2(){
//通过字面量定义的方式,此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。
String s1="javaEE";
String s2="javaEE";
//通过new+构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值
String s3=new String("javaEE");
String s4=new String("javaEE");
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不同拼接操作的对比
@Test
public void test3(){
String s1="javaEE";
String s2="haddoop";
String s3="javaEEhadoop";
String s4="javaEE"+"hadoop";
String s5=s1+"hadoop";
String s6="javaEE"+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(); //返回值得到的s8使用的是常量池中已经存在的“javaEEhadoop"
System.out.println(s8==s3);
}
常量与常量的拼接结果在常量池中,且常量池中不会存在相同内容的常量
只要其中有一个是常量,结果就在堆中
如果拼接的结果调用intern()方法,返回值就在常量池中
一、
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(不包含)的一个子字符串。
@Test
public void test1(){ //单元测试方法
String s1="HelloWorld";
System.out.println(s1.length()); //10
System.out.println(s1.charAt(0)); //H
System.out.println(s1.charAt(9)); //d
// System.out.println(s1.charAt(10)); //-1
// s1="";
System.out.println(s1.isEmpty());
String s2=s1.toLowerCase();
System.out.println(s1); //s1不可变的,仍然为原来的字符串
System.out.println(s2); //改成小写以后的字符串
String s3=" he llo world ";
String s4=s3.trim();
System.out.println("--------"+s3+"--------");
System.out.println("--------"+s4+"---------");
}
@Test
public void test2(){
String s1="HelloWorld";
String s2="helloworld";
System.out.println(s1.equals(s2)); //false
System.out.println(s1.equalsIgnoreCase(s2)); //true
String s3="abc";
String s4=s3.concat("defg");
System.out.println(s4); //abcdefg
String s5="abc";
String s6=new String("abg");
System.out.println(s5.compareTo(s6)); //涉及字符串排序,-4
String s7="北京尚硅谷教育";
String s8=s7.substring(2);
System.out.println(s7);
System.out.println(s8);//尚硅谷教育
String s9=s7.substring(2,5);
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 lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
注:indexOf和lastIndexOf方法如果未找到都是返回-1
@Test
public void test3(){
String str1="hellowworld";
boolean b1=str1.endsWith("rld");
System.out.println(b1); //true
boolean b2=str1.startsWith("He");
System.out.println(b2); //false
boolean b3=str1.startsWith("ll",2);
System.out.println(b3); //true
String str2="wor";
System.out.println(str1.contains(str2)); //true
System.out.println(str1.indexOf("lol")); //-1
System.out.println(str1.indexOf("lo",5));//-1
String str3="hellorworld";
System.out.println(str3.lastIndexOf("or")); //7 从最后开始往前找,索引还是从0开始
System.out.println(str3.lastIndexOf("or",6)); //4,从索引为6的字符开始从右往左找,索引还是从0开始
//什么情况下,indexOf(str)和lastIndexOf(str)返回值相同?
//情况一:存在唯一的一个str。情况二:不存在str
}
三、
替换:
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); //true
String tel="0571-4523113";
//判断这是否是一个杭州的固定电话
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(strs[i]);
}
}
String–>char[]:调用String的toCharArray()
char[]–>String:调用String的构造器
@Test
public void test2(){
String str1="abc";
char[] charArray=str1.toCharArray();
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);
}
String 与 byte[]之间的转换
编码:String --> byte[]:调用String的getBytes()
解码:byte[] --> String:调用String的构造器
编码:字符串 -->字节 (看得懂 —>看不懂的二进制数据)
解码:编码的逆过程,字节 --> 字符串 (看不懂的二进制数据 —> 看得懂)
说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。
@Test
public void test1(){
String str1="abc";
char[] charArray=str1.toCharArray();
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);
}
@Test
public void test2() throws UnsupportedEncodingException {
String str1="abc中国";
byte[] bytes=str1.getBytes(); //使用默认字符集,进行编码
System.out.println(Arrays.toString(bytes));
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的常用方法:
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):返回一个从start开始到end索引结束的左闭右开区间的子字符串
public int length()
public char charAt(int n )
public void setCharAt(int n ,char ch) //将指定位置的字符改成新的
StringBuilder常用的方法的区别是加了 synchronized同步。
总结:
增: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)
长度:length();
*遍历:for() + charAt() / toString()
@Test
public void test3(){
StringBuffer s1=new StringBuffer("abc");
s1.append(1);
s1.append('2');
System.out.println(s1);
// s1.delete(2,4);
// System.out.println(s1);
// s1.replace(2,4,"hello");
// System.out.println(s1);
// s1.insert(1,true);
// System.out.println(s1);
// s1.reverse();
// System.out.println(s1);
String s2=s1.substring(1,3);
System.out.println(s2);
System.out.println(s1.length());
}
String:不可变的字符序列;底层使用char[]存储
StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储
StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储
@Test
public void test1(){
StringBuffer sb1=new StringBuffer("abc");
sb1.setCharAt(1,'i');
System.out.println(sb1);
}
//源码分析:
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的数组。
System.out.println(sb1.length());//0
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)
String,StringBuffer,StringBuilder三者的效率对比:
从高到低:StringBuilder>StringBuffer>String
java.lang.System类
System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差
此方法适用于计算时间差
@Test
public void test1(){
long time=System.currentTimeMillis();
//返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差,称为时间戳
System.out.println(time);
}
计算世界时间的主要标准有:
UTC(Coordinated Universal Time) ,协调世界时,与世界时相差不超过0.9秒
GMT(Greenwich Mean Time) ,格林尼治标准时间,世界时
CST(Central Standard Time)
java.util.Date类
|—java.sql.Date类(sql.Date是util.Date的子类)
两个构造器的使用
>构造器一:Date():创建一个对应当前时间的Date对象
>构造器二:创建指定毫秒数的Date对象
两个方法的使用
toString():显示当前的年、月、日、时、分、秒
getTime():获取当前Date对象对应的毫秒数。(返回自1970年1月1日0时0分0秒 GMT 以来Date对象表示的毫秒数)
如何实例化
如何将java.util.Date对象转换为java.sql.Date对象
@Test
public void test2(){
//创建java.util.Date的对象
//构造器一:Date():创建一个对应当前时间的Date对象
Date date1=new Date();
System.out.println(date1.toString()); //Tue Apr 12 11:52:39 CST 2022
System.out.println(date1.getTime()); //1649735596294(从1970年1月1日0时0分0秒到执行程序那一刻的毫秒数)
//构造器二:创建指定毫秒数的Date对象
Date date2=new Date(313414123123L);
System.out.println(date2); //Fri Dec 07 19:28:43 CST 1979
//创建java.sql.Date的对象
java.sql.Date date3=new java.sql.Date(132233535532L);
System.out.println(date3); //1974-03-11
System.out.println("**********");
//如何将java.util.Date对象转换成java.sql.Date对象
//情况一:
Date date4=new java.sql.Date(134134343121L);
java.sql.Date date5=(java.sql.Date)date4;
System.out.println(date5); //1974-04-02
//情况二
Date date6=new Date();
java.sql.Date date7=new java.sql.Date(date6.getTime());
System.out.println(date7);
}
SimpleDateFormat的使用:SimpleDateFormat对日期Date类的格式化和解析
1.两个操作:
1.1 格式化:日期 —>字符串
1.2 解析:格式化的逆过程,字符串 —> 日期
2.SimpleDateFormat的实例化
@Test
public void testSimpleDateFormat() throws ParseException {
//实例化SimpleDateFormatTest:使用默认的构造器
SimpleDateFormat sdf=new SimpleDateFormat();
//格式化:日期——>字符串
Date date=new Date();
System.out.println(date);//Tue Apr 12 14:37:56 CST 2022
String format=sdf.format(date);
System.out.println(format); //22-4-12 下午2:38
//解析:格式化的逆过程,字符串——>日期
String str="22-1-3 下午3:35";
Date date1=sdf.parse(str);
System.out.println(date1);
//*********按照格式的方式格式化和解析:调用带参的构造器***********
SimpleDateFormat sdf1=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//表示月份的字母要大写,与分区别开
//格式化
String format1=sdf1.format(date);
System.out.println(format1);
//解析:要求字符串必须是符合SimpleFormat识别的格式(构造器中的格式),否则抛异常
Date date2=sdf1.parse("2022-06-04 02:32:42");
System.out.println(date2); //Sat Jun 04 02:32:42 CST 2022
}
//练习一:字符串"2020-09-08"转换为java.sql.Date
@Test
public void test() throws ParseException {
String Birth="2020-09-08";
SimpleDateFormat sdf1=new SimpleDateFormat("yyyy-MM-dd");
Date utildate=sdf1.parse(Birth);
System.out.println(utildate); //Tue Sep 08 00:00:00 CST 2020
java.sql.Date sqldate=new java.sql.Date(utildate.getTime());
System.out.println(sqldate); //2020-09-08
}
java.util.Calendar(日历)类
Calendar是一个抽象类
@Test
public void testCalendar(){
//1.实例化
//方式一:创建其子类(GregorianCalendar)的对象
//方式二:调用其静态方法getInstance()
Calendar calendar=Calendar.getInstance(); //父类调静态方法造对象,返回的是子类的对象,多态的体现
// System.out.println(calendar.getClass());
//2.常用方法
//get()
int days=calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
//set()
//calendar 可变性
calendar.set(Calendar.DAY_OF_MONTH,18);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
//add()
calendar.add(Calendar.DAY_OF_MONTH,3);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
//getTime():日历类——>Date
Date date=calendar.getTime();
System.out.println(date); //Thu Apr 21 16:17:59 CST 2022
//setTime():Date——>日历类
Date date1=new Date();
calendar.setTime(date1);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
}
注意:获取月份时:一月是0,二月是1,以此类推,12月是11
获取星期时:周日是1,周二是2,,,,,周六是7
新日期时间API出现的背景
Date类和Calendar类面临的问题
可变性:像日期和时间这样的类应该是不可变的
偏移性:Date中的年份是从1900开始的,而月份都从0开始
@Test
public void testDate(){
//偏移量
Date date1= new Date(2022 - 1900, 4 - 1, 12);
System.out.println(date1); //Tue Apr 12 00:00:00 CST 2022
}
格式化:格式化只对Date有用,Calendar则不行
Java8吸收了Joda-Time的精华,纠正了过去的缺陷,将来很长一段时间内它会为我们服务
@Test
public void test1(){
//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);
//of():设置指定的年,月,日,时,分,秒。没有偏移量
LocalDateTime localDateTime1=LocalDateTime.of(2022,6,4,01,02,32);
System.out.println(localDateTime1);
//getXxx():获取相关的属性
System.out.println(localDateTime.getDayOfMonth());
System.out.println(localDateTime.getDayOfWeek());
System.out.println(localDateTime.getMonth()); //APRIL
System.out.println(localDateTime.getMonthValue()); //4
//体现不可变性
//withXxx():设置相关的属性
LocalDate localDate1=localDate.withDayOfMonth(23);
System.out.println(localDate);
System.out.println(localDate1);
LocalDateTime localDateTime2=localDateTime.withHour(2);
System.out.println(localDateTime);
System.out.println(localDateTime2);
//不变性
LocalDateTime localDateTime3 = localDateTime.plusMonths(2); //增加2个月
System.out.println(localDateTime);
System.out.println(localDateTime3);
LocalDateTime localDateTime4 = localDateTime.minusDays(10); //减少10天
System.out.println(localDateTime);
System.out.println(localDateTime4);
}
Instant:时间线上的一个瞬时点,概念上将它表示自1970年1月1日0时0分0秒开始的秒数。
/*
Instant的使用
类似于java.util.Date类
*/
@Test
public void test2(){
//now():获取本初子午线对应的标准时间,格林尼治标准时间
Instant instant=Instant.now();
System.out.println(instant); //2022-04-12T10:42:50.853Z
//添加时间的偏移量
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));//得到东八区所在时间
System.out.println(offsetDateTime);//2022-04-12T18:42:50.853+08:00
//toEpochMilli():获取自1970年1月1日0时0分0秒(UTC)开始的毫秒数————>和Date类的getTime()相似
long milli = instant.toEpochMilli();
System.out.println(milli);
//ofEpochMilli():通过给定的毫秒数,获取Instant实例——>和Date(long millis)相似
Instant instant1 = Instant.ofEpochMilli(3412132131231232L);
System.out.println(instant1);
}
DateTimeFormatter:格式化或解析日期,时间
类似于SimpleDateFormat
@Test
public void test3(){
//方式一:预定义的标准格式。如ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
DateTimeFormatter formatter= DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//格式化:日期——>字符串
LocalDateTime localDatetime = LocalDateTime.now();
String str1 = formatter.format(localDatetime);
System.out.println(localDatetime);
System.out.println(str1); //2022-04-12T21:59:03.355
//解析:字符串——>日期
TemporalAccessor parse = formatter.parse("2022-04-12T21:59:03.355");
System.out.println(parse); //{},ISO resolved to 2022-04-12T21:59:03.355
//方式二
//本地化相关的格式。如:ofLoclaizedDateTime()
// FormatStyle.LONG/FormatStyle.MEDIUM/FormatStyle.SHORT:适用于LocalDateTime
DateTimeFormatter formatter2=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
//格式化
String str3=formatter2.format(localDatetime.now());
System.out.println(str3); //2022-4-12 22:10:26
//重点:方式三:自定义的格式。如:ofPattern("yyyy-MM-dd hh:mm:ss")
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
// 格式化
String str4=formatter3.format(LocalDateTime.now());
System.out.println(str4);
//解析
TemporalAccessor accessor = formatter3.parse("2022-03-02 03:03:03");//TemporalAccessor接口,多态
System.out.println(accessor);
}
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 的实现。
//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);
一、说明:Java中的对象,正常情况下,只能进行比较:== 或 != 。不能使用 > 或 < 的
但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。
如何实现?使用两个接口中的任何一个:Comparable 或 Comparator
二、Comparable接口与Comparator的使用的对比:
Comparable接口的方式一旦一定,保证Comparable接口实现类的对象在任何位置都可以比较大小。
Comparable接口的使用举例: 自然排序
像String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式。
像String、包装类重写compareTo()方法以后,进行了从小到大的排列
重写compareTo(obj)的规则:
如果当前对象this大于形参对象obj,则返回正整数,
如果当前对象this小于形参对象obj,则返回负整数,
如果当前对象this等于形参对象obj,则返回零。
对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。
在compareTo(obj)方法中指明如何排序
public class CompareTest {
@Test
public void test1(){
String[] arr=new String[]{"AA","CC","KK","MM","GG","JJ","DD"};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
@Test
public void test2() {
Goods[] arr = new Goods[5];
arr[0] = new Goods("lenovoMOuse", 34);
arr[1] = new Goods("dellMouse", 55);
arr[2] = new Goods("xiaomi", 23);
arr[3] = new Goods("huawei", 56);
arr[4] = new Goods("microsoftMouse", 55);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
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 void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
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 this.name.compareTo(goods.name);
//价格相同,比较商品名的开头字母,按从小到大排
}
//方式二:
// return Double.compare(this.price,goods.price);
}
throw new RuntimeException("传入的数据类型不一致");
}
}
Comparator接口的使用:定制排序
1.背景:
当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,
或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,
那么可以考虑使用 Comparator 的对象来排序
2.重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
如果方法返回正整数,则表示o1大于o2;
如果返回0,表示相等;
返回负整数,表示o1小于o2。
@Test
public void test4(){
Goods[] arr=new Goods[6];
arr[0]=new Goods("lenovoMouse",42);
arr[1]=new Goods("dellMouse",32);
arr[2]=new Goods("xiaomiMouse",13);
arr[3]=new Goods("huaweiMouse",50);
arr[4]=new Goods("huaweiMouse",232);
arr[5]=new Goods("microsoftMouse",32);
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));
}
System类
其内部的成员变量和成员方法都是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的属性对应的值。系统中常见 的属性名以及属性的作用如下表所示:
@Test
public void test1(){
String javaVersion=System.getProperty("java.version");
System.out.println("java的version:"+javaVersion); //java的version:1.8.0_131
String javaHome=System.getProperty("java.home");
System.out.println("java的home:"+javaHome);//java的home:D:\Program Files\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:Lenovo
String userHome=System.getProperty("user.home");
System.out.println("user的home:"+userHome);//user的home:C:\Users\Lenovo
String userDir= System.getProperty("user.dir");
System.out.println("user的dir:"+userDir);//user的dir:F:\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型数据转换为long型(四舍五入)
toDegrees(double angrad) 弧度——>角度
toRadians(double angdeg) 角度——>弧度
BigInteger与BigDecimal类
BigInteger类
BigInteger可以表示任意精度的整数
构造器
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类
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);
@Test
public void test2(){
BigInteger bi=new BigInteger("1243324112234324324325235245346567657653");
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)); //默认保留3位小数 1130.486
System.out.println(bd.divide(bd2,25, BigDecimal.ROUND_HALF_UP)); //1130.4864545454545454545454545
// BigDecimal.ROUND_HALF_UP表示四舍五入
}
er val) :返回其值为 (this % val) 的 BigInteger。
BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟 (this % val) 的两个 BigInteger 的数组。
BigInteger pow(int exponent) :返回其值为 (thisexponent) 的 BigInteger。
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);
@Test
public void test2(){
BigInteger bi=new BigInteger("1243324112234324324325235245346567657653");
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)); //默认保留3位小数 1130.486
System.out.println(bd.divide(bd2,25, BigDecimal.ROUND_HALF_UP)); //1130.4864545454545454545454545
// BigDecimal.ROUND_HALF_UP表示四舍五入
}