1. String 特性
- String声明为final的,不可被继承。
- String实现Serializable接口:表示字符串是支持序列化的。实现了Comparable接口:表示String可以比较大小。
- String内部定义了final char[] value 用于存储字符串数据。
- String:代表不可变的字符序列。简称:不可变性。
(注意:上面的final,如果重新赋值,并且内容不同,就是重新获得新的地址,并不会在原来的地址上赋值!!!!)
面试题:== 和 equals的区别?
- 比较s1和s2的地址是否相同。
- 比较字符串内容值是否相同。
package com.holmes.java04;
import org.junit.Test;
public class StringTest {
@Test
public void test1(){
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
}
}
String字符串,什么情况下,重新指定内存区域进行赋值:
无论,重复赋值,还是拼接字符串,还是修改指定替换字符串等,都是要重新指定内存区域进行赋值!!!
2. String的字面量创建 和 new 对象形式
String对象创建的四种方式:
整体上,也就两种方式:一种字面量,一种new创建对象。
- 通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。
- 通过 new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对象的值。
package com.holmes.java04;
import org.junit.Test;
public class StringTest {
@Test
public void test1(){
String s1 = "javaEE";
String s2 = "javaEE";
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s3 == s4);
}
}
3. String 字符串 内存存储原理
字面形式和new + 对象的内存存储原理:
面试题:String s = new String(“abc”);方式创建对象,在内存中创建了几个对象?
两个,一个是堆空间中new的对象,另一个是char[]对应常量池中的数据:“abc”。
4. String 不同拼接对比 效果
下面的拼接效果必须牢记!!!!
package com.holmes.java04;
import org.junit.Test;
public class StringTest {
@Test
public void test1(){
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE"+"hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
String s8 = (s1 + s2).intern();
System.out.println(s3 == s4);
System.out.println(s3 == s5);
System.out.println(s3 == s6);
System.out.println(s5 == s6);
System.out.println(s3 == s7);
System.out.println(s5 == s7);
System.out.println(s6 == s7);
System.out.println(s3 == s8);
}
}
5. String 和 数组 常用的混合面试题
package com.holmes.java04;
public class StringTest2 {
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) {
StringTest2 ex = new StringTest2();
ex.change(ex.str,ex.ch);
System.out.println(ex.str);
System.out.println(ex.ch);
}
}
6. JVM涉及字符串 内存结构
JDK1.6版本,字符串常量池都在方法区中:
JDK除了1.7版本,字符串常量池在堆中:
JDK1.8以及以后的版本,字符串常量池都在方法区中:
7. String 常用方法
问题一:什么情况下,indexOf(str) 和 lastIndexOf(str)返回值相同?
答:情况一:存在唯一的一个str。情况二:不存在str时。 此外,indexOf 和 lastIndexOf方法如果未找到都是返回-1。
上面的replaceAll()函数方法,matches()函数方法,涉及到正则表达式内容,如下:
8. 涉及到String 类与其他结构之间的转换
8.1 常见的小错误
首先,纠正一个经常犯下的错误:
String str = "123";
int num = (int)str;
8.2 String 和 int 之间的转换
String 转 int:(调用包装类的静态方法,Integer.parseXxx())
String str = "123";
int num = Integer.parseInt(str)
int 转 String:(调用包装类的静态方法,Integer.toString() 和 String.valueOf())
String s2;
String s3;
int num2 = 123;
s2 = Integer.toString(num2);
s3 = String.valueOf(num2);
System.out.println(s2.getClass()+ "," +s3.getClass());
String s4 = 123 + "";
8.3 String 和 char[]字符组 之间的转换
牢记toCharArray()函数方法:
package com.holmes.java04;
import org.junit.Test;
public class StringTest {
@Test
public void test1(){
String str1 = "abc123";
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);
}
}
8.4 String字符串 和 byte[]字节数组 之间的转换
这里就会出现一个编码和解码的一个效果:
String 转为 byte[]: (调用String的getBytes()方法)
package com.holmes.java04;
import org.junit.Test;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.util.Arrays;
public class StringTest {
@Test
public void test1() throws UnsupportedEncodingException {
String str1 = "abc123中国";
byte[] bytes = str1.getBytes();
System.out.println(Arrays.toString(bytes));
byte[] gbks = str1.getBytes("gbk");
System.out.println(Arrays.toString(gbks));
}
}
byte[]字节数组 转 String字符串: (new对象参数传入,来转换)
package com.holmes.java04;
import org.junit.Test;
import java.io.UnsupportedEncodingException;
public class StringTest {
@Test
public void test1() throws UnsupportedEncodingException {
String str1 = "abc123中国";
byte[] bytes = str1.getBytes();
byte[] gbks = str1.getBytes("gbk");
String str2 = new String(bytes);
System.out.println(str2);
String str3 = new String(gbks);
System.out.println(str3);
}
}
9. String 拼接 小面试题
因为一个final,就导致结果不同,牢记常量与常量拼接的结果是存储在常量池中,且常量池不会存在相同内容的常量。final声明后变量就变成了常量!
package com.holmes.java04;
import org.junit.Test;
public class StringTest {
@Test
public void test1(){
String s1 = "javaEEhadoop";
String s2 = "javaEE";
String s3 = s2 + "hadoop";
System.out.println(s1 == s3);
final String s4 = "javaEE";
String s5 = s4 + "hadoop";
System.out.println(s1 == s5);
}
}
10. StringBuffer 和 StringBuilder 介绍
本质上字符串存储规则,其实就是个char[]数组,String不可变,StringBuffer和StringBuilder可变。
String , StringBuffer , StringBuilder三者的异同?
String:不可变的字符序列。 StringBuffer:可变的字符序列:线程安全的,效率偏低。 StringBuilder:可变的字符序列:jdk5.0新增,线程不安全的,效率高。
上面三者底层使用char[]存储。(StringBuffer和StringBuilder因为继承AbstractStringBuilder,因此也是char[] value存储。)
11. String ,StringBuffer,StringBuilder 源码分析
String源码分析:
String str = new String();
String str1 = new String("abc");
StringBuffer源码分析:(StringBuilder源码差不多,就是安不安全的问题)
StringBuffer sb1 = new StringBuffer();
sb1.append('a');
sb1.append('b');
StringBuffer sb2 = new StringBuffer("abc");
开发中建议大家使用:StringBuffer(int capacity) 或 StringBuilder(int capacity)。可以直接定义容量大小,区别就是安全不安全。
12. StringBuffer 和 StringBuilder类常用的方法
StringBuffer和StringBuilder的常用方法差不多,都是一样:
当append和insert时,如果原来value数组长度不够,可扩容。
package com.holmes.java04;
import org.junit.Test;
public class StringBufferBuilderTest {
@Test
public void test1(){
StringBuffer sb1 = new StringBuffer("abc");
sb1.append(1);
sb1.append('1');
System.out.println(sb1);
sb1.delete(2,4);
System.out.println(sb1);
sb1.replace(2,4,"hello");
System.out.println(sb1);
sb1.insert(2,"c");
System.out.println(sb1);
sb1.reverse();
System.out.println(sb1);
System.out.println( sb1.indexOf("c"));
System.out.println(sb1.substring(2,4));
System.out.println(sb1.charAt(5));
sb1.setCharAt(0,'m');
System.out.println(sb1);
}
}
方法链是一个很重要的形式,方法链的原理:
13. 对比String ,StringBuffer,StringBuilder的效率
package com.holmes.java04;
import org.junit.Test;
public class StringBufferBuilderTest {
@Test
public void test1(){
long startTime = 0;
long endTime = 0;
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 += i;
}
endTime = System.currentTimeMillis();
System.out.println("String的执行时间:" + (endTime - startTime));
}
}
14. Java 时间日期 的相关API
计算世界时间的主要标准有:
方法一: java.lang.System类的日期时间:(计算时间差)
- System.currentTimeMillis()返回当前时间于1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
- 此方法经常用来计算时间差。
方法二: java.util.Date类表示特定的瞬间,精确到毫秒:
package com.holmes.java04;
import org.junit.Test;
import java.util.Date;
public class DateTimeTest {
@Test
public void test2(){
Date date1 = new Date();
System.out.println(date1.toString());
System.out.println(date1.getTime());
Date date2 = new Date(1636181996537L);
System.out.println(date2.toString());
}
}
在sql也有一个,java.sql.Date类,对应着数据库中的日期类型的变量。
package com.holmes.java04;
import org.junit.Test;
import java.sql.Date;
public class DateTimeTest {
@Test
public void test2(){
Date date1 = new Date(23453456342L);
System.out.println(date1.toString());
System.out.println(date1.getTime());
}
}
怎么将sql.Date 转为 util.Date对象?
因为多态性,直接赋值就可。
package com.holmes.java04;
import org.junit.Test;
public class DateTimeTest {
@Test
public void test2(){
java.sql.Date date1 = new java.sql.Date(23453456342L);
java.util.Date date2 = new java.util.Date();
date2 = date1;
System.out.println(date2);
}
}
怎么将util.Date 转为 sql.Date对象?
因为参数都有毫秒(时间戳),所以我们可以通过getTime()的方式来解决这种问题!!
package com.holmes.java04;
import org.junit.Test;
public class DateTimeTest {
@Test
public void test2(){
java.sql.Date date1 = new java.sql.Date(23453456342L);
java.util.Date date2 = new java.sql.Date(32453476342L);
java.sql.Date date3 = (java.sql.Date)date2;
System.out.println(date3);
java.util.Date date4 = new java.util.Date(32453476342L);
java.sql.Date date6 = new java.sql.Date(date4.getTime());
System.out.println(date6);
}
}
15. IDEA 的 debug调试
16. JDK8之前日期时间API SimpleDateFormat类
16.1 SimpleDateFormat默认无参数情况
SimpleDateFormat是对日期Date类的格式化和解析。
- 使用format()方法,格式化:日期 转为 字符串。
- 使用parse()方法,解析:格式化的逆过程,字符串 转为 日期
package com.holmes.java05;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTimeTest {
@Test
public void testSimpleDateFormat() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat();
Date date = new Date();
String formatStr = sdf.format(date);
System.out.println(formatStr);
String str = "21-11-7 下午3:04";
Date date1 = sdf.parse(str);
System.out.println(date1);
}
}
16.2 SimpleDateFormat有参数情况
SimpleDateFormat的参数,不同格式的参数对应不同返回的结果。可以查看java参考手册这对SimpleDateFormat有参数的构造器这一节。
jdk参考手册
package com.holmes.java05;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTimeTest {
@Test
public void testSimpleDateFormat() throws ParseException {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
System.out.println(sdf.format(date));
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println(sdf1.format(date));
System.out.println(sdf1.parse("1999-11-07 04:07:55"));;
}
}
很多页面传字符串"2020-09-08" 转为java.sql.Date(以方便存储数据库中)。
package com.holmes.java05;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class DateTimeTest {
@Test
public void testExer() throws ParseException {
String str = "2020-09-08";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date dateUtil = sdf.parse(str);
java.sql.Date dateSql = new java.sql.Date(dateUtil.getTime());
System.out.println(dateSql);
}
}
总天数差的一些计算,可以用到方法类和getTime类方法。
17. JDK8之前日期时间API Calendar(日历类)
首先,Calendar是一个抽象类,抽象类不能声明对象。
Calendar因为有set()方法可以随意改变日期,便有了可变性,一旦set()设置了指定日期,calendar就会设定。
虽然他不能声明对象,但它有个子类GregorianCalendar,该子类可以创建构造器。
Calendar(日历类)实例化方式:
- 方式一:创建其子类(GregorianCalendar)的对象。
- 方式二:调用其静态方法getInstance()来创建对象。
package com.holmes.java05;
import org.junit.Test;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class DateTimeTest {
@Test
public void testExer(){
GregorianCalendar gregorianCalendar = new GregorianCalendar();
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getClass());
}
}
Calendar类的常用方法:
package com.holmes.java05;
import org.junit.Test;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class DateTimeTest {
@Test
public void testExer(){
Calendar calendar = Calendar.getInstance();
int days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println("查看这个月的第几天:" + days);
System.out.println("查看今年的第几天:" + calendar.get(Calendar.DAY_OF_YEAR));
calendar.set(Calendar.DAY_OF_MONTH,22);
System.out.println("重新设置本月天数:"+ calendar.get(Calendar.DAY_OF_MONTH));
calendar.add(Calendar.DAY_OF_MONTH,3);
System.out.println("在当前的日期基础上,增加相应日期:"+ calendar.get(Calendar.DAY_OF_MONTH));
Date date = calendar.getTime();
System.out.println(date);
Date date1 = new Date();
calendar.setTime(date1);
System.out.println(calendar.get(Calendar.YEAR)+ "年" + (calendar.get(Calendar.MONTH) + 1) + "月" + calendar.get(Calendar.DAY_OF_MONTH) + "号");
System.out.println("星期:" + (calendar.get(Calendar.DAY_OF_WEEK) - 1));
System.out.println("今年的第几个周:" + calendar.get(Calendar.WEEK_OF_YEAR));
}
}
注意获取月份和星期时很重要!!
日期偏移量的问题:
package com.holmes.java05;
import org.junit.Test;
import java.util.Date;
public class JDKDateTimeTest {
@Test
public void testDate(){
Date date1 = new Date(2020 - 1900,9 - 1,8);
System.out.println(date1);
}
}
18. JDK8 新时间日期的 API (java.time)
18.1 JDK8 的 java.time的介绍
JDK8中的新的java.time中包含了所有关于本地日期(LocalDate),本地时间(LocalTime),本地日期时间(LocalDateTime),时区(ZonedDateTime)和持续时间(Duration)的类。
18.2 LocalDate , LocalTime , LocalDateTime的使用
- now()方法:用来创建对,获取当前的日期,时间。使用频率最高的是LocalDateTime。
- of()方法:设置指定的年,月,日,时,分,秒。该方法设置没有偏移量的!!
创建了对象,那必须有方法对应,见下:
package com.holmes.java05;
import org.junit.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class JDKDateTimeTest {
@Test
public void testDate(){
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDate);
System.out.println(localTime);
System.out.println(localDateTime);
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23, 13);
System.out.println(localDateTime1);
System.out.println("获取当月的第几天" + localDateTime.getDayOfMonth());
System.out.println("获取这周的第几天" + localDateTime.getDayOfWeek());
System.out.println("获取英文的当前月份" + localDateTime.getMonth());
System.out.println("获取数字的当前月份" + localDateTime.getMonthValue());
System.out.println("获取当前分钟:" + localDateTime.getMinute());
LocalDateTime localDateTime2 = localDateTime.withDayOfMonth(22);
System.out.println(localDateTime);
System.out.println(localDateTime2);
LocalDateTime localDateTime3 = localDateTime.withHour(4);
System.out.println(localDateTime);
System.out.println(localDateTime3);
LocalDateTime localDateTime4 = localDateTime.plusMonths(3);
System.out.println(localDateTime);
System.out.println(localDateTime4);
LocalDateTime localDateTime5 = localDateTime.minusDays(4);
System.out.println(localDateTime);
System.out.println(localDateTime5);
}
}
18.3 Instant 瞬时
java.time.Instant也是基于1970年1月1日0时0分0秒(UTC)开始。
首先,要确定一个时区问题,UTC是按照本初子午线来开始的。
两种创建Instant实例方式:
- now()方法:获取本初子午线对应的标准时间(UTC)
- ofEpochMilli()方法:也是实例化的方式,它可以接受long型的参数,从而获取时间。
instant实例化对应的方法:
- atOffset()方法:定义时区偏移量的。
- toEpochMilli()方法:获取从1970年1月1日0时0分0秒(UTC)开始到现在对应的毫秒数
package com.holmes.java05;
import org.junit.Test;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class InstantTest {
@Test
public void test(){
Instant instant = Instant.now();
System.out.println(instant);
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);
long l = instant.toEpochMilli();
System.out.println(l);
Instant instant1 = Instant.ofEpochMilli(1636621675611L);
System.out.println(instant1);
}
}
总结: 本质上,Date类和Instant类差不多,功能和方法都差不多。
18.4 JDK8 新日期时间API java.time.format.DateTimeFormatter
这里DateTimeFormatter就与上面的SimpleDateFormat差不多。
方式一:预定义的标准格式,ISO_LOCAL_DATE_TIME,ISO_LOCAL_DATE,ISO_LOCAL_TIME
- format()方法格式化:日期 --》 字符串。
- parse()方法解析:字符串 --》 日期
package com.holmes.java05;
import org.junit.Test;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
public class DateTimeFormatterTest {
@Test
public void test(){
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
LocalDateTime localDateTime = LocalDateTime.now();
String str1 = formatter.format(localDateTime);
System.out.println(str1);
TemporalAccessor parse = formatter.parse("2021-11-11T17:45:51.145");
System.out.println(parse);
}
}
方式二:本地化相关的格式
- 1.ofLocalizedDateTime()方法:(ofLocalizeDateTime对应的就是DateTime的格式类)
参数:FormatStyle.SHORT, FormatStyle.MEDIUM, FormatStyle.LONG - 2.ofLocalizedDate()方法:(ofLocalizeDate对应的就是Date的格式类)
参数:相比较上面多了一个FormatStyle.FULL,FormatStyle.SHORT, FormatStyle.MEDIUM, FormatStyle.LONG
package com.holmes.java05;
import org.junit.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
public class DateTimeFormatterTest {
@Test
public void test2(){
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
LocalDateTime localDateTime = LocalDateTime.now();
String str = formatter.format(localDateTime);
System.out.println(str);
TemporalAccessor parse = formatter.parse("21-11-11 下午6:20");
System.out.println(parse);
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
String str2 = formatter1.format(LocalDate.now());
System.out.println(str2);
}
}
方式三:自定义的格式,这种方式是重点!!
- ofPattern()方法:来自定义
ofPattern(“yyyy-MM-dd hh:mm:ss”)。
package com.holmes.java05;
import org.junit.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
public class DateTimeFormatterTest {
@Test
public void test3(){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh");
String str = formatter.format(LocalDateTime.now());
System.out.println(str);
TemporalAccessor parse = formatter.parse("2021-11-11 06");
System.out.println(parse);
}
}
18.5 其他API
19. Java比较器
19. 为什么要用Java比较器?
Java中的对象(引用数据类型),正常情况下,只能进行比较使用 == ,=!来比较地址值,像 >,< ,>= ,<=等没办法对引用数据类型对象进行比较的。
但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。
这就用到了Comparable 或 Comparator接口了。
19.2 Comparable接口使用
像实现Comparable接口调用sort方法也叫做自然排序。
Comparable接口的使用举例:
- 像String,包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式。
- 重写compareTo(obj)的规则:
如果当前对象this大于形参对象obj,则返回正整数; 如果当前对象this小于形参对象obj,则返回负数; 如果当前对象this等于形参对象obj,则返回零。
像String这种系统类排序处理:
实现Comparable接口的对象列表(和数组)可以通过 Collection.sort(针对集合排序) 或 Arrays.sort(针对数组排序) 进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无序指定比较器。
package com.holmes.java05;
import org.junit.Test;
import java.util.Arrays;
public class CompareTest {
@Test
public void test(){
String[] arr = new String[]{"AA","CC","MM","BB","OO","FF"};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
对于自定义类来说:
如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。
在compareTo(obj)方法中指明如何排序。
同时,可能排序遇到相同的会存在二级排序的情况。
自定义类实例:
goods类:
package com.holmes.java05;
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 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 this.name.compareTo(goods.name);
}
}
throw new ClassCastException("传入的数据类型不匹配");
}
}
测试类:通过sort()方法来调用实现Comparable的compareTo()方法
package com.holmes.java05;
import org.junit.Test;
import java.util.Arrays;
public class CompareTest {
@Test
public void test2(){
Goods[] arr = new Goods[4];
arr[0] = new Goods("lenovoMouse",34);
arr[1] = new Goods("dellMouse",56);
arr[2] = new Goods("xiaomiMouse",12);
arr[3] = new Goods("huaweiMouse",99);
Arrays.sort(arr);
System.out.println(arr[0].getPrice());
System.out.println(arr[1].getPrice());
System.out.println(arr[2].getPrice());
System.out.println(arr[3].getPrice());
}
}
19.3 定制排序:java.util.Comparator
什么时候用定制排序:java.util.Comparator?
从写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
Arrays.sort()方法中,除了可以添加数组进行比较,还可以添加Comparator对象来定义如何比较。
如定制排序String从大到小排序的sort()方法:
package com.holmes.java05;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
public class CompareTest {
@Test
public void test(){
String[] arr = new String[]{"AA","CC","MM","BB","OO","FF"};
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);
}
throw new RuntimeException("输出的数据类型不一致");
}
});
System.out.println(Arrays.toString(arr));
}
}
接着上面的自定义类Goods,使用定制排序Comparator和sort方法进行修改:
package com.holmes.java05;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
public class CompareTest {
@Test
public void test3(){
Goods[] arr = new Goods[4];
arr[0] = new Goods("lenovoMouse",34);
arr[1] = new Goods("dellMouse",56);
arr[2] = new Goods("xiaomiMouse",12);
arr[3] = new Goods("huaweiMouse",99);
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(arr[0].getName());
System.out.println(arr[1].getName());
System.out.println(arr[2].getName());
System.out.println(arr[3].getName());
}
}
19.4 Comparable接口 与 Comparator的使用的对比
20. System类,Math类,BigInteger 与BigDecimal类
20.1 System类
System.getProperty()方法的使用:
package com.holmes.java05;
import org.junit.Test;
public class OtherClassTest {
@Test
public void test1(){
String javaVersion = System.getProperty("java.version");
System.out.println("java的版本:" + 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);
}
20.2 Math类
20.3 BigInteger 与BigDecimal类
了解Integer:
BigInteger类介绍:
BigDecimal类:
package com.holmes.java05;
import org.junit.Test;
import java.math.BigDecimal;
import java.math.BigInteger;
public class OtherClassTest {
@Test
public void test2(){
BigInteger bi = new BigInteger("124332411231231231231231231");
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bi);
System.out.println(bd.divide(bd2,BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2,15,BigDecimal.ROUND_HALF_UP));
}
}
|