目录



字符串相关类

String

代表字符串,Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现。

  • ​String​​是一个​​final​​类,不可被继承。
  • ​String​​代表不可变的字符序列。
  • ​String​​内部定义了​​final char value[]​​用来存储字符串。
  • ​String​​类中:
  • 实现了​​Serializable​​接口,表示字符出支持序列化。
  • 实现了​​Comparable​​接口,表示字符串可以比大小。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];

/** Cache the hash code for the string */
private int hash; // Default to 0


String的不可变性

  • 一般我们通过字面量的方式(区别于​​new​​方式)给一个字符串赋值,此时字符串值声明在字符串常量池(位于方法区)中。
  • 字符串常量池中是不会存储相同内容的字符串的。
  • 当对字符串重新赋值时,需要重新指定内存区域内赋值,不能使用原有的​​value​​进行赋值。
String s1 = "abc";  // 字面量的定义方式
String s2 = "abc";

// s1与s2指向字符串常量池的相同位置
System.out.println(s1 == s2); // true

// s1指向字符串常量池中另一个新的有字符串"123"的地址,而不是修改原来"abc"所在地址的内容
s2 = "123";
System.out.println(s1 == s2); // false


  • 字符串拼接操作时,也要重新指定内存区域赋值。
String s3 = "abc";
s3 += "123";
System.out.println(s1 == s3); // false


  • 调用​​replace()​​方法修改字符串时,也要重新指定内存区域赋值。
String s4 = "abc";
String s5 = s4.replace('a', '1');
System.out.println(s1 == s4); // true
System.out.println(s1 == s5); // false


通过下面的例子进一步理解字符串的不可变性:

public class StringTest {
String s1 = new String("123");
String s2 = "abc";
char[] chars = {'t', 'e', 's', 't'};

public void exchange(String s1, String s2, char[] chars) {
s1 = "456";
s2 = "def";
chars[0] = 'b';
}

public static void main(String[] args) {
StringTest test1 = new StringTest();
test1.exchange(test1.s1, test1.s2, test1.chars);

System.out.println(test1.s1 + test1.s2); // 123abc
System.out.println(test1.chars); // best
}
}


String实例化方式

/* 通过字面量定义 */
String s = "abc";

/* 通过new定义 */
// this.value = new char[0]
String s1 = new String();

// this.vaule = original.value
String s2 = new String(String original);

// this.value = Arrays.copyOf(value, value.length)
String s3 = new String(char[] a);


字面量定义与​​new​​定义的区别如下:

4. Java常用类_字符串

举例说明:

String s1 = "12345";
String s2 = "12345";
String s3 = new String("12345");
String s4 = new String("12345");

System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s1 == s4); // false
System.out.println(s3 == s4); // false


另一个例子:

package learnstring;

public class StringTest {
@Test
public void test3() {
Person p1 = new Person("Tom", 12);
Person p2 = new Person("Tom", 24);

System.out.println(p1.name == p2.name); // true
}
}

class Person {
public Person(String name, int age) {
this.name = name;
this.age = age;
}

String name;
int age;
}


String不同的拼接方式

  • 常量与常量的拼接结果存储在常量池,且常量池中不会存在相同内容的变量。
  • 只要其中有一个是变量,就相当于用了​​new​​,结果就在堆中。
  • 如果拼接的结果调用了​​intern()​​方法,那么返回值就在常量池中。
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); // 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
System.out.println(s3 == s8); // true

// final也视为常量,所以结果也保存在常量池中
final String s9 = "JavaEE";
String s10 = s9 + "Hadoop";
System.out.println(s3 == s10); // true


String常用方法

  • ​int length()​​:返回字符串的长度,​​return value.length;​​。
  • ​char charAt(int index)​​:返回索引处的字符,​​return value[index];​​。
  • ​boolean isEmpty()​​:返回字符串是否为空,​​return value.length == 0;​​。
  • ​String toLowerCase()​​:使用默认语言环境,将字符串中的所有字符改为小写。
  • ​String toUpperCase()​​:使用默认语言环境,将字符串中的所有字符改为大写。
String s1 = "AVCdsBfdksEE";

System.out.println(s1.toLowerCase()); // avcdsbfdksee
System.out.println(s1.toUpperCase()); // AVCDSBFDKSEE
System.out.println(s1); // AVCdsBfdksEE


  • ​String trim()​​:返回字符串的副本,忽略前导空白和尾部空白。
String s1 = "   a bc  edd   ";

System.out.println(s1.trim()); // "a bc edd"
System.out.println(s1); // " a bc edd "


  • ​boolean equals(Object obj)​​:比较字符串内容是否相同。
  • ​boolean equalsIgnoreCase(Object obj)​​:忽略大小写比较字符串内容是否相同。
  • ​String concat(String str)​​:将制定字符串连接到此字符串的结尾,等价于​​+​​。
  • ​int compareTo(String anotherString)​​:由于​​String​​实现了​​Comparable​​接口,所以​​String​​之间可以比大小。
  • ​String subString(int beginIndex)​​:返回子字符串,从​​beginIndex​​截取到最后。
  • ​String subString(int beginIndex, int endIndex)​​:返回子字符串,从​​beginIndex​​截取到​​endIndex​​(不包含)。
  • ​boolean endsWith(String suffix)​​:测试此字符串是否以指定后缀结尾。
  • ​boolean startsWith(String prefix)​​:测试此字符串是否以指定前缀开始。
  • ​boolean startsWith(String prefix, int offset)​​:测试此字符串是否在指定位置以指定前缀开始。
  • ​boolean contains(CharSequence s)​​:当前字符串是否包含指定字符序列。
String s = "Hello world";

System.out.println(s.endsWith("rld")); // true
System.out.println(s.startsWith("Hel")); // true
System.out.println(s.startsWith("ll", 2)); // true

System.out.println(s.contains("o w")); // true


  • ​int indexOf(String str)​​:返回指定子字符串在字符串中第一次出现的索引,未找到返回​​-1​​。
  • ​int indexOf(String str, int fromIndex)​​:返回指定子字符串在字符串中第一次出现的索引。
  • ​int lastIndexOf(String str)​​:返回指定子字符串在字符串中最右边出现的索引,未找到返回​​-1​​。
  • ​int lastIndexOf(String str, int fromIndex)​​:返回指定子字符串在字符串中最右边出现的索引。
  • ​String replace(char oldChar, char newChar)​​:返回一个新的字符串,它是由​​newChar​​替换原字符串中所有的​​oldChar​​得到的。
  • ​String replace(charSequence target, charSequence replacement)​​:使用指定字面值​​replacement​​替换原字符串所有匹配​​target​​的子字符串。
String str = "北京成都上海天津北京";
System.out.println(str.replace('北', '南')); // 南京成都上海天津南京
System.out.println(str.replace("北京", "郑州")); // 郑州成都上海天津郑州


  • ​String replaceAll(String regex, String replacement)​​:使用字符串​​replacement​​替换原字符串所有匹配正则表达式​​regex​​的子字符串。
  • ​String replaceFirst(String regex, String replacement)​​:使用字符串​​replacement​​替换原字符串第一个匹配正则表达式​​regex​​的子字符串。
String str = "123hello445java124world990mysql8475test";

// 把字符串中所有数字替换成,
System.out.println(str.replaceAll("\\d+", ",")); // ,hello,java,world,mysql,test

// 把字符串中第一串数字替换成,
System.out.println(str.replaceFirst("\\d+", ",")); // ,hello445java124world990mysql8475test


  • ​boolean matches(String regex)​​:返回该字符串是否匹配给定的正则表达式。
String tel = "0571-82359847";

// 是否以0571-开头,后面跟着8个数字
System.out.println(tel.matches("0571-\\d{8}")); // true


  • ​String[] split(String regex)​​:根据正则表达式的匹配拆分此字符串。
  • ​String[] split(String regex, int limit)​​:根据正则表达式的匹配拆分此字符串,最多不超过​​limit​​个,如果到达​​limit​​个,则剩余部分全部放在数组的最后一个元素中。
String str1 = "hello-world-java";
System.out.println(Arrays.toString(str1.split("-"))); // [hello, world, java]

String str2 = "hello.world.java";
System.out.println(Arrays.toString(str2.split("\\."))); // [hello, world, java]
System.out.println((Arrays.toString(str2.split("\\.", 2)))); // [hello, world.java]


String与基本数据类型、包装类之间的转换

  • String转基本数据类、包装类:使用parseInt()等方法。
  • 基本数据类、包装类转String:使用String重载的valueOf()方法。
String str1 = "12345";
int i = Integer.parseInt(str1);
System.out.println(i); // 12345

String str2 = String.valueOf(i);
System.out.println(str2); // 12345


String与char数组之间的转换

  • Stringchar[]:使用toCharArray()方法。
  • char[]String:使用String的构造器。
String str1 = "1s2e3sa45";
char[] chars = str1.toCharArray();
System.out.println(Arrays.toString(chars)); // [1, s, 2, e, 3, s, a, 4, 5]

String str2 = new String(chars);
System.out.println(str2); // 1s2e3sa45


String与byte数组转换

@Test
public void test() throws UnsupportedEncodingException {
String str1 = "123abc中国";

byte[] bytes = str1.getBytes(); // 使用默认字符集
System.out.println(Arrays.toString(bytes)); // [49, 50, 51, 97, 98, 99, -28, -72, -83, -27, -101, -67]

byte[] gbk = str1.getBytes("gbk"); // 使用gbk字符集进行编码
System.out.println(Arrays.toString(gbk)); // [49, 50, 51, 97, 98, 99, -42, -48, -71, -6]

System.out.println(new String(bytes)); // 使用默认字符集进行解码
System.out.println(new String(gbk, "gbk")); // 使用gbk字符集进行解码
}


StringBuffer与StringBuilder

  • ​java.lang.StringBuffer​​代表可变的字符序列,可以对字符串内容进行增删,不会产生新的对象。
  • 扩容问题:如果要添加的数据底层数组放不下了,需要扩容,默认情况下扩容为原来的2倍+2,同时将原数组的元素复制到新数组中。所以开发中建议使用​​StringBuffer(int capacity)​​或​​StringBuilder(int capacity)​​的构造方法。
  • 如下所示,​​char[] value​​不再声明为​​final​​。
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;

/**
* The count is the number of characters used.
*/
int count;


  • ​StringBuilder​​与​​StringBuffer​​非常类似,均代表可变的字符序列,而且提供相关功能的方法也一样。效率从高到低:​​StringBuilder​​>​​StringBuffer​​>​​String​​。
  • ​String​​:JDK1.0,不可变字符序列。
  • ​StringBuffer​​:JDK1.0,可变字符序列、效率低、线程安全
  • ​StringBuilder​​:JDK5.0,可变字符序列、效率高、线程不安全
  • 作为参数传递的话,方法内部​​String​​不会改变其值,而​​StringBuffer​​与​​StringBuilder​​则会。

StringBuffer常用方法

  • ​StringBuffer append(xxx)​​:字符串后拼接各种数据类型。
StringBuffer s = new StringBuffer();
s.append(12);
s.append('b');
s.append(3.666);
System.out.println(s); // 12b3.666


  • ​StringBuffer delete(int start, int end)​​:删除指定位置内容。
s.delete(1, 4);
System.out.println(s); // 1.666


  • ​StringBuffer replace(int start, int end, String str)​​:把​​[start,end)​​位置替换为​​str​​。
s.replace(1, 4, "hello");
System.out.println(s); // 1hello6


  • ​StringBuffer insert(int offset, xxx)​​:在指定位置插入​​xxx​​。
s.insert(3, false);
System.out.println(s); // 1hefalsello6


  • ​StringBuffer reverse()​​:反转当前字符序列。
s.reverse();
System.out.println(s); // 6olleslafeh1


  • 一些与​​String​​类似的方法:
  • ​public int indexOf(String str)​​。
  • ​public String subString(int start, int end)​​。
  • ​public int length()​​。
  • ​public char charAt(int index)​​。
  • ​public void setCharAt(int n, char ch)​​。
JDK8之前的日期时间API

System类中获取时间戳

  • ​java.lang.System​​类提供的​​public static long currentTimeMillis()​​方法用来获取当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
long timeStamp = System.currentTimeMillis();
System.out.println(timeStamp); // 1635752270506


Java中的两个Date类

  • ​java.util.Date​​类是​​java.sql.Date​​类的父类。
public class Date extends java.util.Date {
@Deprecated
public Date(int year, int month, int day) {
super(year, month, day);
}

public Date(long date) {
// If the millisecond date value contains time info, mask it out.
super(date);

}


对于​​java.util.Date​​类,需要注意:

  • 两种常用的构造器:
  • ​Date()​​:。
  • ​Date(long date)​​:。
  • 两种常用的方法:
  • ​toString()​​:显示当前的星期、日期、时间、年份。
  • ​getTime()​​:获取当前​​Date​​对象对应的时间戳。
// 构造器1:创建一个对应当前时间戳的Date对象
Date date = new Date();
System.out.println(date); // Mon Nov 01 15:57:59 CST 2021
System.out.println(date.toString()); // Mon Nov 01 15:57:59 CST 2021
System.out.println(date.getTime()); // 1635753479317

// 构造器2:创建指定时间戳的Date对象
Date date2 = new Date(1635752270506L);
System.out.println(date2); // Mon Nov 01 15:37:50 CST 2021


对于​​java.sql.Date​​类,用法如下:

// 创建java.sql.Date对象
java.sql.Date sqlDate = new java.sql.Date(1635752270506L);
System.out.println(sqlDate); // 2021-11-01

// 将java.util.Date对象转为java.sql.Date对象
java.sql.Date sqlDate2 = new java.sql.Date(date2.getTime());
System.out.println(sqlDate2); // 2021-11-01


SimpleDateFormat类

​Date​​类的API不易于国际化,大部分被废弃了,​​java.text.SimpleDateFormat​​类是一个不与语言环境有关的方式来格式化和解析日期的具体类。

格式化与解析

格式化为将日期转换为字符串;而解析是格式化的逆过程,将字符串转换为日期:

// 实例化SimpleDateFormat(默认参数)
SimpleDateFormat sdf = new SimpleDateFormat();

Date date = new Date();
System.out.println(date); // Mon Nov 01 17:07:02 CST 2021

// 格式化:日期 => 字符串
String format = sdf.format(date);
System.out.println(format); // 21-11-1 下午5:07

Date date1 = sdf.parse("21-11-1 下午5:00");
System.out.println(date1); // Mon Nov 01 17:00:00 CST 2021

// 实例化SimpleDateFormat(指定格式)
// HH表示24小时制
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf1.format(date)); // 2021-11-01 17:08:34

// 解析:字符串 => 日期
// 解析时要求字符串必须是符合SimpleDateFormat识别的格式,即"yyyy-MM-dd HH:mm:ss"
Date date2 = sdf1.parse("2021-11-01 17:00:04");
System.out.println(date2); // Mon Nov 01 17:00:04 CST 2021


Calendar类

Calendar的实例化

​java.util.Calendar​​类是一个抽象基类,主要用于完成日期之间相互操作的功能。获取​​Calender​​实例的方法:

  • 使用​​Calendar.getInstance()​​方法。
  • 调用它的子类​​GregorianCalendar​​的构造器。
// 方式一:调用静态方法Calendar.getInstance()
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getClass()); // class java.util.GregorianCalendar

// 方式二:创建子类GregorianCalendar的对象
Calendar calendar1 = new GregorianCalendar();


Calendar常用方法

  • ​get()​​:获取当前日期的属性。
  • 获取月份​​Calendar.MONTH​​时,一月是0,二月是1。
  • 获取星期几​​Calendar.DAY_OF_WEEK​​时,周日是1,周一是2。
int days = calendar.get(Calendar.DAY_OF_MONTH);  // 当前日期是这个月的第几天
System.out.println(days); // 1

int hours = calendar.get(Calendar.HOUR_OF_DAY); // 几点
System.out.println(hours); // 20

// 获取月份时,一月是0,二月是1
// 获取星期几时,周日是1,周一是2
System.out.println(calendar.get(Calendar.MONTH)); // 10
System.out.println(calendar.get(Calendar.DAY_OF_WEEK)); // 2


  • ​set()​​:修改日期属性。
calendar.set(Calendar.DAY_OF_MONTH, 10);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 10


  • ​add()​​:在当前日期的属性上增加/减少。
calendar.add(Calendar.DAY_OF_MONTH, -11);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 30


  • ​getTime()​​:返回当前日期的​​Date​​对象。
// getTime(): Calendar => Date
Date date = calendar.getTime();
System.out.println(date); // Sat Oct 30 20:47:33 CST 2021


  • ​setTime()​​:将​​Date​​对象对应的日期赋给当前​​Calendar​​对象。
// setTime(): Date => Calendar
Date date1 = new Date();
calendar.setTime(date1);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH)); // 1


JDK8中新的日期时间API

为什么需要新的日期时间类

旧版的​​Date​​与​​Calendar​​类面临的问题有:

  • 可变性:像日期和时间这样的类应该是不可变的。
  • 偏移性:​​Date​​中的年份是从1900开始的,而月份都从0开始。
  • 格式化:格式化只对​​Date​​有用,​​Calendar​​则不行。
  • 此外,它们也不是线程安全的,不能处理闰秒等。

LocalDate类、LocalTime类与LocalDateTime类

  • ​now()​​: 获取当前的日期/时间/日期+时间。
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();

System.out.println(localDate); // 2021-11-01
System.out.println(localTime); // 21:56:20.414
System.out.println(localDateTime); // 2021-11-01T21:56:20.414


  • ​of()​​: 指定日期时间,没有偏移量。
// of(): 指定日期时间,没有偏移量
LocalDateTime localDateTime1 = LocalDateTime.of(2021, 12, 30, 13, 0, 30);
System.out.println(localDateTime1); // 2021-12-30T13:00:30


  • 获取属性值。
System.out.println(localDateTime.getDayOfMonth());  // 1
System.out.println(localDateTime.getDayOfWeek()); // MONDAY
System.out.println(localDateTime.getMonth()); // NOVEMBER
System.out.println(localDateTime.getMonthValue()); // 11
System.out.println(localDateTime.getMinute()); // 7


  • 不可变性。
LocalDateTime localDateTime2 = localDateTime.withDayOfMonth(30);
System.out.println(localDateTime2); // 2021-11-30T22:09:50.212

LocalDateTime localDateTime3 = localDateTime.minusMonths(10);
System.out.println(localDateTime3); // 2021-01-01T22:11:41.539

System.out.println(localDateTime); // 2021-11-01T22:09:50.212


Instant类

时间线上的一个瞬时点。

  • ​now()​​:静态方法,返回默认UTC时区的​​Instant​​类对象。
// UTC时区比北京时间慢8小时
Instant instant = Instant.now();
System.out.println(instant); // 2021-11-01T14:17:22.693Z


  • ​atOffset(ZoneOffset offset)​​:结合即时的偏移来创建一个​​OffsetDateTime​​。
// 北京时间
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime); // 2021-11-01T22:21:20.719+08:00


  • ​toEpochMilli()​​:返回时间戳(格林威治时间1970-01-01 00:00:00到现在的时间)。
long milli = instant.toEpochMilli();
System.out.println(milli); // 1635776679648


  • ​ofEpochMilli(long epochMilli)​​:在格林威治时间1970-01-01 00:00:00加上指定毫秒后的时间。
Instant instant1 = Instant.ofEpochMilli(1635776648110L);
System.out.println(instant1); // 2021-11-01T14:24:08.110Z
System.out.println(instant1.atOffset(ZoneOffset.ofHours(8))); // 2021-11-01T22:24:08.110+08:00


DateTimeFormatter

LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime); // 2021-11-01T22:43:19.991

// 方式一:预定义的标准格式
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
String str = formatter.format(localDateTime);
System.out.println(str); // 2021-11-01T22:43:19.991

// 解析
TemporalAccessor parse = formatter.parse("2021-11-01T22:32:51.141");
System.out.println(parse); // {},ISO resolved to 2021-11-01T22:32:51.141


// 方式二:本地化相关的格式
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
System.out.println(formatter1.format(localDateTime)); // 21-11-1 下午10:43
System.out.println(formatter2.format(localDateTime)); // 2021年11月1日 下午10时43分19秒

// 解析方式类似


// 方式三:自定义的格式
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(formatter3.format(localDateTime)); // 2021-11-01 22:43:19


Java比较器

Comparable接口

  • String、包装类等实现了Comparable接口,重写了compareTo(obj)方法。
  • 重写compareTo(obj)方法规则:
  • 如果当前对象​​this​​大于形参​​obj​​,则返回正整数。
  • 如果当前对象​​this​​小于形参​​obj​​,则返回负整数。
  • 如果当前对象​​this​​等于形参​​obj​​,则返回0。
import org.junit.Test;
import java.util.Arrays;

public class ComparableTest {
@Test
public void test() {
Goods[] arr = new Goods[4];
arr[0] = new Goods("lenovo", 34);
arr[1] = new Goods("dell", 34);
arr[2] = new Goods("mi", 12);
arr[3] = new Goods("huawei", 500);

System.out.println(Arrays.toString(arr));
// [Goods{name='lenovo', price=34.0}, Goods{name='dell', price=34.0}, Goods{name='mi', price=12.0}, Goods{name='huawei', price=500.0}]

Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
// [Goods{name='mi', price=12.0}, Goods{name='dell', price=34.0}, Goods{name='lenovo', price=34.0}, Goods{name='huawei', price=500.0}]
}
}


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;

// 根据价格排序
// return Double.compare(this.price, goods.price);

// 根据价格排序,价格相同时根据名称排序
if (this.price > goods.price) {
return 1;
}
else if (this.price < goods.price) {
return -1;
}
else {
// return 0;
return this.name.compareTo(goods.name);
}
}
throw new RuntimeException("传入数据类型不一致");
}
}


Comparator接口

背景:

  • 类没有实现​​java.lang.Comparable​​接口而又不方便修改代码。
  • 或者实现了​​java.lang.Comparable​​接口,但排序规则不适合当前的操作。

用法

  • 重写​​compare(Object o1,Object o2)​​方法,比较​​o1​​和​​o2​​的大小:如果方法返回正整数,则表示​​o1​​大于​​o2​​;如果返回0,表示相等;返回负整数,表示​​o1​​小于​​o2​​。
  • 可以将​​Comparator​​传递给​​sort​​方法(如​​Collections.sort​​或​​Arrays.sort​​),从而允许在排序顺序上实现精确控制。
  • 还可以使用​​Comparator​​来控制某些数据结构(如有序​​set​​或有序映射)的顺序,或者为那些没有自然顺序的对象​​collection​​提供排序。
Arrays.sort(arr, new Comparator<Goods>() {
@Override
public int compare(Goods o1, Goods o2) {
// 根据价格排序,价格相同时根据名称排序
if (o1.getName().compareTo(o2.getName()) > 0) {
return 1;
}
else if (o1.getName().compareTo(o2.getName()) < 0) {
return -1;
}
else {
// return 0;
return Double.compare(o1.getPrice(), o2.getPrice());
}
}
});
System.out.println(Arrays.toString(arr));
// [Goods{name='dell', price=34.0}, Goods{name='huawei', price=500.0}, Goods{name='lenovo', price=34.0}, Goods{name='mi', price=12.0}]


  • 从上面可以看出,​​Comparator​​接口属于临时性的比较,较为灵活。
System类
  • ​System​​类代表系统,系统级的很多属性和控制方法都放置在该类的内部,该类位于​​java.lang​​包。
  • 由于该类的构造器是​​private​​的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是​​static​​的,所以也可以很方便的进行调用。
  • ​System​​类内部包含​​in​​、​​out​​和​​err​​三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。

常用方法

  • ​native long currentTimeMillis()​​:该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
  • ​void exit(intstatus)​​:该方法的作用是退出程序。其中​​status​​的值为0代表正常退出,非零代表异常退出,使用该方法可以在图形界面编程中实现程序的退出功能等。
  • ​void gc()​​:该方法的作用是请求系统进行垃圾回收,至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
  • ​String getProperty(String key)​​:该方法的作用是获得系统中属性名为​​key​​的属性对应的值。
System.out.println(System.getProperty("java.version"));  // 1.8.0_302
System.out.println(System.getProperty("java.home")); // /Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre

System.out.println(System.getProperty("os.name")); // Mac OS X
System.out.println(System.getProperty("os.version")); // 12.0.1

System.out.println(System.getProperty("user.name"));
System.out.println(System.getProperty("user.dir"));


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)​​:角度=>弧度。
BigInteger与BigDecimal

BigInteger

​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()​
  • ​public BigInteger add(BigInteger val)​
  • ​public BigInteger subtract(BigInteger val)​
  • ​public BigInteger multiply(BigInteger val)​
  • ​public BigInteger divide(BigInteger val)​
  • ​public BigInteger remainder(BigInteger val)​
  • ​public BigInteger divideAndRemainder(BigInteger val)​​:返回由商和余数组成的​​BigInteger​​数组。
  • ​public BigInteger pow(int exponent)​

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)​