文章目录
9.1 字符串相关的类:String
String
:字符串,使用一对“ ”
引起来表示。
1.String
声明为final
的,不可被继承
2.String
实现了Serializable
接口:表示字符串是支持序列化的;
实现了Comparable
接口:表示String
可以比较大小;
3.String
内部定义了final char[] value
用于存储字符串数据
4.String
:代表不可变的字符序列。简称:不可变性。
体现:1.当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
2.当对现有的字符串进行连接操作时,也需要重写指定内存区域赋值,不能使用原有的value进行赋值。
3.当调用String
的replace()
方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
String s1="abc"; //字面量的定义方式
String s2="abc";
System.out.println(s1==s2); //比较s1和s2的地址值:true
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s3==s4); //false
String s5="abc";
s5+="def";
System.out.println(s5);//要明确不是在原有位置后加abc;
String s6="abc";
String s7=s6.replace('a','m');
System.out.println(s6);//abc
System.out.println(s7);//mbc,不在原有位置修改,新造一个
5.通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
6.字符串常量池中是不会存储相同内容的字符串的。
String
的实例化方式:
方式一:通过字面量定义的方式
方式二:通过new
+ 构造器的方式
//通过字面量定义的方式:此时的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(s3==s4);//false
System.out.println(s1==s4);//false
System.out.println(s2==s4);//false
面试题:String s=new String("abc");方式创建对象,在内存中创建了几个对象?
两个:一个是堆空间中new结构,另一个是char[]型数据对应的常量池中的数据:“abc”。
结论:
1.常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
2.只要其中有一个是变量,结果就在堆中。
3.如果拼接的结果调用intern()
方法,返回值就在常量池中。
String s1 = "JavaEE";
String s2 = "hadoop";
String s3 = "JavaEEhadoop";
String s4 = "JavaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "JavaEE" + s2;
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//false
System.out.println(s5 == s6);//false
String s7=s5.intern();//返回值得到的s7使用的常量池中已经存在的“JavaEEhadoop”;
System.out.println(s3 == s7);//true
String常用方法1:
String s1="helloworld";
//1.int length():返回字符串的长度。
System.out.println(s1.length()); //10
//2.char charAt(int index):返回某索引处的字符。
System.out.println(s1.charAt(0)); //h
//3.boolean isEmpty():判断是否是空字符串。
System.out.println(s1.isEmpty()); //false
//4.String toLowerCase():将String中的所有字符都转换为小写;
System.out.println(s1.toLowerCase(Locale.ROOT));
//5.String toUpperCase():将String中的所有字符都转换为大写;
System.out.println(s1.toUpperCase(Locale.ROOT));
//6.String trim():返回字符串的副本,忽略前导空白和尾部空白(去除字符串首尾空格);
String s2=" hello world ";
String s3=s2.trim();
System.out.println("-----"+s2+"-----");
System.out.println("-----"+s3+"-----");
//7.boolean equals(Object obj):比较字符串内容是否相同;
//8.boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
String s4="ABC";
String s5="abc";
System.out.println(s4.equalsIgnoreCase(s5));
//9.String concat(String str):将指定字符串连接到此字符串的结尾。等价于用“+”。
String s6=s5.concat("def");
System.out.println(s6); //abcdef
//10.int compareTo(String anotherString):比较两个字符串的大小
String s7="abc";
String s8 = new String("abe");
System.out.println(s7.compareTo(s8)); //-2(涉及到字符串排序)
//11.String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
String s9="北京尚硅谷教育";
System.out.println(s9.substring(2)); //尚硅谷教育
//12.String substring(int beginIndex,int endIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到endIndex(不包含)的一个子字符串。
System.out.println(s9.substring(2,5)); //尚硅谷
String常用方法2:
String s1="helloworld";
//1.boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
System.out.println(s1.endsWith("ld")); //true
//2.boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
System.out.println(s1.startsWith("he")); //true
//3.boolean startsWith(String prefix,int toffset):测试此字符串从指定索引开始的子字符串是否以指定的前缀开始
System.out.println(s1.startsWith("ll",2)); //true
//4.boolean contains(CharSequence s):当且仅当此字符串包含指定的char值序列时,返回true。
System.out.println(s1.contains("ll")); //true
//5.int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引
System.out.println(s1.indexOf("ll")); //2
//6.int indexOf(String str,int fromIndex):返回指定字符串在此字符串中第一次出现处的索引,从指定的索引开始
System.out.println(s1.indexOf("ll",0)); //2
//7.int lastIndexOf(String str):返回指定字符串在此字符串中最后一次出现处的索引
System.out.println(s1.lastIndexOf("l")); //8
//8.int lastIndexOf(String str,int fromIndex):返回指定字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
System.out.println(s1.lastIndexOf("l",7)); //3
//注:indexOf和lastIndexOf方法如果未找到都是返回-1。
//思考:什么情况下,indexOf()和lastIndexOf()返回值相同?
//情况一:存在唯一的str;
//情况二:不存在str;
String常用方法3:
/*
替换:
*/
// 1.String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用newChar替换此字符串中出现的所有oldChar得到的。
String str1="北京尚硅谷教育北京";
String str2=str1.replace('北','东');
System.out.println(str1); //北京尚硅谷教育北京
System.out.println(str2); //东京尚硅谷教育东京
//2.String replace(CharSequence target, CharSequence ):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
System.out.println(str1.replace("北京", "上海")); //上海尚硅谷教育上海
//3.String replaceAll(String regex, String replacement):使用给定的replacement替换此字符串所有匹配给定的正则表达式的子字符串。
String str = "12hello34world5java7891mysql456";//把字符串中的数字替换成,,如果结果中开头和结尾有,的话去掉
String string = str.replaceAll("\\d+", ",").replaceAll("^,|,$", "");
System.out.println(string); //hello,world,java,mysql
//4.String replaceFirst(String regex, String replacement):使用给定的replacement替换此字符串匹配给定的正则表达式的第一个子字符串。
/*
匹配
*/
//1.boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
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);
/*
切片
*/
//1.String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
str = "hello|world|java";
String[] strs = str.split("\\|");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
System.out.println();
String str3 = "hello.world.java";
String[] strs3 = str3.split("\\.");
for (int i = 0; i < strs3.length; i++) {
System.out.println(strs3[i]);
}
//2.String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
- 涉及到String类和其他结构之间的转换
/**复习:
String与基本数据类型、包装类之间的转换。
*/
@Test
public void test1(){
//1.String-->基本数据类型、包装类:调用包装类的静态方法:parseXxx(Str)
String str1="123";
//int num=(int)str1; //错误的
int num=Integer.parseInt(str1);
String str2="true";
boolean bool2=Boolean.parseBoolean(str2);
//2.基本数据类型、包装类-->String:方法1:调用String重载的valueOf(xxx)。
//方法2:连接符号+。
String str3=String.valueOf(num);//"123"
String str4=num+"";
/**
* String与char[]之间的转换
*/
@Test
public void test2(){
//String-->char[]:调用String的toCharArray()
String str1="abc123";
char[] charArray = str1.toCharArray();
for(int i=0;i<charArray.length;i++){
System.out.println(charArray[i]);
}
//char[]-->String:调用String的构造器
char[] arr=new char[]{'h','e','l','l','o'};
String str2=new String(arr);
System.out.println(str2);
/**
* String与byte[]之间的转换
*/
@Test
public void test3() throws UnsupportedEncodingException {
//编码:String-->byte[]:调用String的getBytes()
String str1="abc123中国";
byte[] bytes = str1.getBytes();//使用默认的字符集,进行转换
System.out.println(Arrays.toString(bytes));
//编码:字符串-->字节(看得懂-->看不懂的二进制数据)
//解码:编码的逆过程,字节-->字符串(看不懂的二进制数据-->看得懂)
//说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。
byte[] gbks = str1.getBytes("gbk");//使用gbk字符集进行编码
System.out.println(Arrays.toString(gbks));
//解码:byte[]-->String:调用String的构造器
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);//没有出现乱码
}
- 解决一个拼接问题:
final
@Test
//解决一个拼接的问题
public void test4(){
String s1="javaEEhadoop";
String s2="javaEE";
String s3=s2+"hadoop";
System.out.println(s1==s3);//false
final String s4="javaEE";//s4:常量
String s5=s4+"hadoop";
System.out.println(s1==s5);//true
}
关于StringBuffer
和StringBuilder
的使用
/**
* String、StringBuffer、StringBuilder三者的异同?
* 不同点:
* String:不可变的字符序列;
* StringBuffer:可变的字符序列;线程安全的,但是效率偏低。
* StringBuilder:可变的字符序列;线程不安全的,但是效率高。---JDK 5.0新增。
* 相同点:
* 底层都使用char[]存储。(注意了解底层源码数据结构)
*
*/
StringBuffer
和StringBuilder
的常用方法:
@Test
public void test2(){
StringBuffer s1 = new StringBuffer("abc");
//StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
s1.append(1);
s1.append('1');
System.out.println(s1);
//StringBuffer delete(int start,int end):删除指定位置的内容
s1.delete(2, 4);
//StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
s1.replace(2,4,"hello");
//StringBuffer insert(int offset, xxx):在指定位置插入xxx
s1.insert(2,false);
//StringBuffer reverse() :把当前字符序列逆转
s1.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)
System.out.println(s1);
System.out.println(s1.toString());
}
/**
*总结:
* 增: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(){
//初始设置
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));
}
9.2 JDK 8之前的日期、时间API
/**
* JDK 8之前的日期时间的API测试
* 1.System类中的currentTimeMillis();
* 2.java.util.Date和子类java.sql.Date
* 3.SimpleDateFormat
* 4.Calendar
*/
1.System
类中的currentTimeMillis()
@Test
public void test1(){
long time =System.currentTimeMillis();
System.out.println(time);//返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。---通常称为时间戳
}
2.java.util.Date
类和java.sql.Date
类
/*
java.util.Date类
|---java.sql.Date类
1.两个构造器的使用
2.两个方法的使用
>toString():显示当前的年、月、日、时、分、秒
>getTime():获取当前Date对象对应的毫秒数。(时间戳)
3.java.sql.Date类:对应着数据库中的日期类型的变量。
>如何实例化
>如何将java.sql.Date对象转化为java.util.Date对象---直接赋值(多态)
>如何将java.util.Date对象转化为java.sql.Date对象---
*/
@Test
public void test2() {
//构造器一:Date() :创建一个对应当前时间的Date对象
Date date1 = new Date();
System.out.println(date1.toString());
System.out.println(date1.getTime());
System.out.println(date1);
//构造器二://创建指定毫秒数的Date对象
Date date2 = new Date(1624241308366L);
System.out.println(date2.toString());
java.sql.Date date3 = new java.sql.Date(1624241308366L);
System.out.println(date3);//2021-06-21:只返回年月日
//如何将java.util.Date对象转化为java.sql.Date对象
//情况一:
//Date date4 = new java.sql.Date(1624241308366L);
//java.sql.Date date5=(java.sql.Date)date4;
//情况二:正确
Date date6=new Date();
java.sql.Date date7=new java.sql.Date(date6.getTime());
}
3.SimpleDateFormat
类
/*
SimpleDateFormat的使用:SimpleDateFormat对日期Date类的格式化和解析
1.两个操作
1.1格式化:日期--->字符串
1.2解析:格式化的逆过程,字符串--->日期
2.SimpleDateFormat的实例化
*/
@Test
public void testSimpleDateFormat() throws ParseException {
//实例化SimpleDateFormat:使用默认的构造器
SimpleDateFormat sdf = new SimpleDateFormat();
//格式化:日期--->字符串
Date date = new Date();
System.out.println(date);
String format = sdf.format(date);
System.out.println(format);
//解析:格式化的逆过程,字符串--->日期
String str="21-6-21 下午10:17";
Date parse = sdf.parse(str);
System.out.println(parse);
//按照指定的方式格式化和解析:调用带参的构造器
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//格式化
String format1 = sdf1.format(date);
System.out.println(format1);//2021-06-21 10:29:16
//解析:要求字符串必须符合SimpleDateFormat识别的格式(通过构造器参数体现)
//否则:抛异常
//Date date2 = sdf1.parse("2021-06-21 10:29:16");
Date date2 = sdf1.parse(format1);
System.out.println(date2);
}
- 两个练习题:
/*
练习一:字符串“2020-09-08”转换为java.sql.Date
*/
@Test
public void testExer() throws ParseException {
String birth="2020-09-08";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(birth);
System.out.println(date);
java.sql.Date date1 = new java.sql.Date(date.getTime());
System.out.println(date1);
}
/*
练习二:“三天打鱼两天晒网” 1990-01-01 xxxx-xx-xx 打渔?晒网?
举例:2020-09-08 ? 总天数
总天数%5==1,2,3:打渔
总天数%5==4,0:晒网
总天数的计算?
方式一:(date2.getTime()-date1.getTime())/(1000*60*60*24)+1
方式二:1990-01-01 --->2019-12-13 + 2020-01-01--->2020-09-08(单独考虑闰年)
*/
4.java.util.Calendar
(日历)类
/*
Calendar日历类的使用
*/
@Test
public void testCalendar(){
//1.实例化
//方式一:创建其子类(GregorianCalendar)的对象
//方式二:调用其静态方法getInstance
Calendar calendar = Calendar.getInstance();
// System.out.println(calendar.getClass()); -- class java.util.GregorianCalendar
//2.常用方法
//get()
int days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
System.out.println(calendar.get(Calendar.DAY_OF_WEEK));
//set()
calendar.set(Calendar.DAY_OF_MONTH,24);
int day1 = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(day1);
//add()
calendar.add(Calendar.DAY_OF_MONTH,-2);
calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
//getTime():日历类--->Date
Date time = calendar.getTime();
System.out.println(time);
//setTime():Date--->日历类
Date date2 = new Date();
calendar.setTime(date2);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
}
//注意:获取月份时:一月是0,二月是1,以此类推,12月是11
//获取星期时:周日是1,周一是2,以此类推,周六是7
9.3 JDK 8中新的日期、时间API
LocalDate
、LocalTime
、LocalDateTime
的使用
/*
LocalDate、LocalTime、LocalDateTime的使用
说明:
1.LocalDateTime相较于LocalDate、LocalTime,使用评率高
*/
@Test
public void test1(){
//now():获取当前的日期、时间、日期+时间
LocalDate now = LocalDate.now();
LocalTime now1 = LocalTime.now();
LocalDateTime now2 = LocalDateTime.now();
System.out.println(now);
System.out.println(now1);
System.out.println(now2);
//of():设置指定的年、月、日、时、分、秒。没有偏移量。
LocalDateTime localdatetime1 = LocalDateTime.of(2021, 6, 22, 16, 49, 30);
System.out.println(localdatetime1);
//getXxx():获取相关的属性
System.out.println(localdatetime1.getDayOfMonth());
System.out.println(localdatetime1.getDayOfWeek());
System.out.println(localdatetime1.getMonth());
System.out.println(localdatetime1.getMonthValue());
System.out.println(localdatetime1.getMinute());
//withXxx:设置相关的属性
//三个类:体现不可变性
LocalDateTime localDateTime = localdatetime1.withDayOfMonth(30);
System.out.println(localdatetime1);//还是22号
System.out.println(localDateTime);//30号
LocalDateTime localDateTime1 = localdatetime1.withHour(4);
System.out.println(localdatetime1);//还是16点
System.out.println(localDateTime1);//4点
//plus:加
LocalDateTime localDateTime2 = localDateTime.plusMonths(3);
System.out.println(localDateTime);//还是6月
System.out.println(localDateTime2);//9月
//minus:减
LocalDateTime localDateTime3 = localDateTime.minusMonths(3);
System.out.println(localDateTime);//还是6月
System.out.println(localDateTime3);//3月
}
- 瞬时:
Instant
/*
Instant的使用
类似于java.util.Date类
*/
@Test
public void test2(){
//now():获取本初子午线对应的标准时间
Instant instant = Instant.now();
System.out.println(instant);//本初子午线上的时间
//添加时间的偏移量
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);
//获取自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(1624356949433L);
System.out.println(instant1);
}
java.time.format.DateTimeFormatter
类
/*
DateTimeFormatter:格式化或解析日期、时间
类似于SimpleDateFormat
*/
@Test
public void test3(){
//方式一:预定义的标准格式。
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//格式化:日期--->字符串
LocalDateTime now = LocalDateTime.now();
String str1 = formatter.format(now);
System.out.println(now);
System.out.println(str1);
//解析:字符串--->日期
TemporalAccessor parse = formatter.parse(str1);
System.out.println(parse);
//方式二:本地化相关的格式。如:ofLocalizedDateTime()、ofLocalizedDate()
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
//格式化
String str2=formatter1.format(now);
System.out.println(str2);
//方式三:自定义的格式。如:ofPattern("yyyy-MM-dd hh:mm:ss")
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
String str3 = formatter2.format(LocalDateTime.now());
System.out.println(str3);
//解析
TemporalAccessor parse1 = formatter2.parse("2021-06-22 06:59:59");
System.out.println(parse1);
}
9.4 Java比较器
/**
* 一.说明:Java中的对象,正常情况下,只能进行比较:==或!=。不能使用>或<。但是在开发
* 场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。
* 如何实现?使用两个接口中的任意一个:Comparable或Comparator
*
* 二.Comparable接口的使用
* Comparable与Comparator的使用对比:
* Comparable接口是排序接口。若一个类实现了Comparable接口,就意味着“该类支持排序”。实现
* Comparable接口需要重写内部的compareTo()方法,可以说是自然排序。
* Comparable接口的方式一旦一定,保证Comparable接口实现类的对象在任何位置都可以比较大小
* 而Comparator 是比较器接口,属于临时性的比较。当需要控制某个类的次序,而该类本身不支持排序
* (即没有实现Comparable接口)或实现了Comparable接口的排序规则不适合当前的操作,那么可以
* 考虑使用Comparator的对象来排序。实现Comparator接口需要重写内部的
* compare(Object o1,Object o2)方法。
* 实现定制排序。
*/
/*
Comparable接口的使用举例: 方式一:自然排序
1.像String、包装类等实现了Comparable接口,重写了compareTo()方法,给出了比较两个对象大小的方式。
2.像String、包装类重写compareTo()方法以后,进行了从小到大的排列
3.重写 compareTo()方法的规则:
如果当前对象this大于形参对象obj,则返回正整数,
如果当前对象this小于形参对象obj,则返回负整数,
如果当前对象this等于形参对象obj,则返回零。
4.对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法,在compareTo(obj)方法中指明如何排序。
*/
@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",43);
arr[2]=new Goods("MiMouse",12);
arr[3]=new Goods("HuaweiMouse",65);
arr[4]=new Goods("microsoftMouse",43);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
- 涉及重写
compareTo()
方法:(重要)
@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);
}
//return 0;
throw new RuntimeException("传入的数据类型不一致!");
}
/*
方式二:定制排序:java.util.Comparator
*/
/*
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 test3(){
String[] arr=new String[]{"AA","CC","KK","MM","GG","JJ","DD"};
Arrays.sort(arr, 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(arr));
}
@Test
public void test4(){
Goods[] arr = new Goods[6];
arr[0]=new Goods("lenovoMouse",34);
arr[1]=new Goods("dellMouse",43);
arr[2]=new Goods("miMouse",12);
arr[3]=new Goods("huaweiMouse",65);
arr[4]=new Goods("huaweiMouse",22);
arr[5]=new Goods("microsoftMouse",43);
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));
}
9.5 System类
System
类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。- 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是
static
的,所以也可以很方便的进行调用。 - 成员变量:
System
类内部包含in
、out
和err
三个成员变量,分别代表标准输入流(键盘输入)、标准输出流(显示器)和标准错误输出流(显示器)。 - 成员方法:
1.native long currentTimeMillis()
:该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
2.void exit(int status)
:该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表异常退出。使用该方法可以在图形界面编程中实现程序的退出功能等。
3.void gc()
:该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
4.String getProperty(String key)
:该方法的作用是获取系统中属性名为key的属性对应的值。系统中常见的属性名以及属性的作用如下表所示:
属性名 | 属性说明 |
---|---|
java.version | java运行时环境版本 |
java.home | java安装目录 |
os.name | 操作系统的名称 |
os.version | 操作系统的版本 |
user.name | 用户的账户名称 |
user.home | 用户的主目录 |
user.dir | 用户的当前工作目录 |
@Test
public void test1(){
String property = System.getProperty("java.version");
System.out.println(property);//1.8.0_281
String property1 = System.getProperty("java.home");
System.out.println(property1);//D:\Java\jdk1.8.0_281\jre
String property2 = System.getProperty("os.name");
System.out.println(property2);//Windows 10
String property3 = System.getProperty("os.version");
System.out.println(property3);//10.0
String property4 = System.getProperty("user.name");
System.out.println(property4);//Administrator
String property5 = System.getProperty("user.home");
System.out.println(property5);//C:\Users\Administrator
String property6 = System.getProperty("user.dir");
System.out.println(property6);//I:\IdeaTest\day04
}
9.6 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 角度——>弧度 |
9.7 BigInteger与BigDecimal
1.BigInteger
Integer
类作为int的包装类,能存储的最大整型值为 2 31 − 1 2^{31}-1 231−1,Long
类也是有限的,最大为 2 63 − 1 2^{63}-1 263−1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力。更不用说进行运算了。java.math
包的BigInteger
可以表示不可变的任意精度的整数。BigInteger
提供所有java的基本整数操作符的对应物,并提供java.lang.Math
的所有相关方法。另外。BigInteger
还提供一下运算:模运算、GCD计算、质数测试、素数生成、位操作以及一些其他操作。
2.BigDecimal
- 一般的
Float
类和Double
类可以用来做科学计算或工程计算,但在商业计算中,要求数字精度比较高,故用到java.math.BigDecimal
类。 BigDecimal
类支持不可变的、任意精度的有符号十进制定点数。