Java常用类的一些基础API的使用
数字相关类、日期时间API、系统相关类、数组工具类及自然排序和定制排序的介绍
Author: Msuenb
Date: 2023-02-15
数字相关类
Math类
java.lang.Math
类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。类似这样的工具类,其所有方法均为静态方法,并且不会创建对象,调用起来非常简单。
public static double abs(double a)
:返回 double 值的绝对值。
double d1 = Math.abs(-5); //d1的值为5
double d2 = Math.abs(5); //d2的值为5
public static double ceil(double a)
:返回大于等于参数的最小的整数。
double d1 = Math.ceil(3.3); //d1的值为 4.0
double d2 = Math.ceil(-3.3); //d2的值为 -3.0
double d3 = Math.ceil(5.1); //d3的值为 6.0
public static double floor(double a)
:返回小于等于参数最大的整数。
double d1 = Math.floor(3.3); //d1的值为3.0
double d2 = Math.floor(-3.3); //d2的值为-4.0
double d3 = Math.floor(5.1); //d3的值为 5.0
public static long round(double a)
:返回最接近参数的 long。(相当于四舍五入方法)
long d1 = Math.round(5.5); //d1的值为6.0
long d2 = Math.round(5.4); //d2的值为5.0
- public static double pow(double a,double b):返回a的b幂次方法
- public static double sqrt(double a):返回a的平方根
- public static double random():返回[0,1)的随机值
- public static final double PI:返回圆周率
- public static double max(double x, double y):返回x,y中的最大值
- public static double min(double x, double y):返回x,y中的最小值
double result = Math.pow(2,31);
double sqrt = Math.sqrt(256);
double rand = Math.random();
double pi = Math.PI;
Random类
java.util.Random
用于产生随机数
boolean nextBoolean()
:返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 boolean 值。void nextBytes(byte[] bytes)
:生成随机字节并将其置于用户提供的 byte 数组中。double nextDouble()
:返回下一个伪随机数,它是取自此随机数生成器序列的、在 0.0 和 1.0 之间均匀分布的 double 值。float nextFloat()
:返回下一个伪随机数,它是取自此随机数生成器序列的、在 0.0 和 1.0 之间均匀分布的 float 值。double nextGaussian()
:返回下一个伪随机数,它是取自此随机数生成器序列的、呈高斯(正态)分布的 double 值,其平均值是 0.0,标准差是 1.0。int nextInt()
:返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。int nextInt(int n)
:返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。long nextLong()
:返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 long 值。
@Test
public void test03(){
Random r = new Random();
System.out.println("随机整数:" + r.nextInt());
System.out.println("[0,100)范围的随机整数:" + r.nextInt(100));
System.out.println("随机小数:" + r.nextDouble());
System.out.println("随机布尔值:" + r.nextBoolean());
}
BigInteger和BigDecimal
java.math.BigInteger
用于表示不可变的任意精度的整数
BigInteger(String val)
:构造器BigInteger add(BigInteger val)
:BigInteger subtract(BigInteger val)
BigInteger multiply(BigInteger val)
BigInteger divide(BigInteger val)
BigInteger remainder(BigInteger val)
:取余- ....
@Test
public void test01(){
// long bigNum = 123456789123456789123456789L;
BigInteger b1 = new BigInteger("123456789123456789123456789");
BigInteger b2 = new BigInteger("78923456789123456789123456789");
// System.out.println("和:" + (b1+b2));//错误的,无法直接使用+进行求和
System.out.println("和:" + b1.add(b2));
System.out.println("减:" + b1.subtract(b2));
System.out.println("乘:" + b1.multiply(b2));
System.out.println("除:" + b2.divide(b1));
System.out.println("余:" + b2.remainder(b1));
}
java.math.BigDecimal
用于表示不可变的、任意精度的有符号十进制数。
BigDecimal(String val)
BigDecimal add(BigDecimal val)
BigDecimal subtract(BigDecimal val)
BigDecimal multiply(BigDecimal val)
BigDecimal divide(BigDecimal val)
BigDecimal divide(BigDecimal divisor, int roundingMode)
BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
BigDecimal remainder(BigDecimal val)
- ....
@Test
public void test02(){
/*double big = 12.123456789123456789123456789;
System.out.println("big = " + big);*/
BigDecimal b1 = new BigDecimal("123.45678912345678912345678912345678");
BigDecimal b2 = new BigDecimal("7.8923456789123456789123456789998898888");
// System.out.println("和:" + (b1+b2));//错误的,无法直接使用+进行求和
System.out.println("和:" + b1.add(b2));
System.out.println("减:" + b1.subtract(b2));
System.out.println("乘:" + b1.multiply(b2));
System.out.println("除:" + b1.divide(b2,20,RoundingMode.UP));//divide(BigDecimal divisor, int scale, int roundingMode)
System.out.println("除:" + b1.divide(b2,20,RoundingMode.DOWN));//divide(BigDecimal divisor, int scale, int roundingMode)
System.out.println("余:" + b1.remainder(b2));
}
日期时间API
JDK8之前的日期时间
java.util.Date
-
new Date():当前系统时间
-
long getTime():返回该日期时间对象距离1970-1-1 0.0.0 0毫秒之间的毫秒值
-
new Date(long 毫秒):把该毫秒值换算成日期时间对象
@Test
public void test2(){
long time = System.currentTimeMillis();
System.out.println(time);//1559806982971
//当前系统时间距离1970-1-1 0:0:0 0毫秒的时间差,毫秒为单位
}
@Test
public void test1(){
Date d = new Date();
System.out.println(d);
}
java.text.SimpleDateFormat
用于日期时间的格式化。
- public final String format(Date date):将一个 Date 格式化为日期/时间字符串。
- public Date parse(String source):从给定字符串的开始解析文本,以生成一个日期。
@Test
public void test9(){
Date d = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒 E Z");
//把Date日期转成字符串,按照指定的格式转
String str = sf.format(d);
System.out.println(str);
}
java.util.TimeZone
-
通常,使用 getDefault 获取 TimeZone,getDefault 基于程序运行所在的时区创建 TimeZone。
-
也可以用 getTimeZone 及时区 ID 获取 TimeZone 。例如美国太平洋时区的时区 ID 是 "America/Los_Angeles"。
@Test
public void test2(){
TimeZone t = TimeZone.getTimeZone("UTC");
System.out.println(t);
}
常见时区ID:
Asia/Shanghai
UTC
America/New_York
America/Los_Angeles
java.util.Locale
:表示特定的地理、政治和文化地区。
-
需要 Locale 来执行其任务的操作称为语言环境敏感的 操作,它使用 Locale 为用户量身定制信息。
-
语言参数是一个有效的 ISO 语言代码。这些代码是由 ISO-639 定义的小写两字母代码。
-
国家/地区参数是一个有效的 ISO 国家/地区代码。这些代码是由 ISO-3166 定义的大写两字母代码。
-
Locale 类提供了一些方便的常量,可用这些常量为常用的语言环境创建 Locale 对象。
@Test
public void test02(){
Locale china = Locale.CHINA;
System.out.println("china = " + china);
}
java.util.Calendar
Calendar 类是一个抽象类。与其他语言环境敏感类一样,Calendar 提供了一个类方法 getInstance,以获得此类型的一个通用的对象。修改和获取 YEAR
、MONTH
、DAY_OF_MONTH
、HOUR
等日历字段对应的时间值。
void add(int field,int amount)
int get(int field)
void set(int field, int value)
示例代码:
@Test
public void test2(){
TimeZone t = TimeZone.getTimeZone("America/Los_Angeles");
Calendar c = Calendar.getInstance(t);
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH)+1;
int day = c.get(Calendar.DATE);
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
System.out.println(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second);
}
JDK8中的日期时间
Date 和 Calendar 存在较多问题。Java 8 吸收了 Joda-Time 的精华,创建了新的 java.time API,包含了所有关于Clock、LocalDate、LocalTime、LocalDateTime、ZonedDateTime、Duration的类。
java.time
– 包含值对象的基础包java.time.chrono
– 提供对不同的日历系统的访问。java.time.format
– 格式化和解析时间和日期java.time.temporal
– 包括底层框架和扩展特性java.time.zone
– 包含时区支持的类
本地日期时间
序号 | 方法 | ****描述 |
---|---|---|
1 | now() / now(ZoneId zone) | 静态方法,根据当前时间创建对象/指定时区的对象 |
2 | of() | 静态方法,根据指定日期/时间创建对象 |
3 | getDayOfWeek() | 获得星期几(返回一个 DayOfWeek 枚举值) |
4 | getHours()/getMinute()/getSecond() | 获得当前对象对应的小时、分钟、秒 |
5 | plus(TemporalAmount t)/minus(TemporalAmount t) | 添加或减少一个 Duration 或 Period |
6 | isBefore()/isAfter() | 比较两个 LocalDate |
7 | isLeapYear() | 判断是否是闰年(在LocalDate类中声明) |
8 | format(DateTimeFormatter t) | 格式化本地日期、时间,返回一个字符串 |
9 | parse(Charsequence text) | 将指定格式的字符串解析为日期、时间 |
import org.junit.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class TestLocalDateTime {
@Test
public void test4(){
LocalDate now = LocalDate.now();
LocalDate before = now.minusDays(100);
System.out.println(before);//2019-02-26
}
@Test
public void test03(){
LocalDate lai = LocalDate.of(2019, 5, 13);
System.out.println(lai.getDayOfYear());
}
@Test
public void test02(){
LocalDate lai = LocalDate.of(2019, 5, 13);
System.out.println(lai);
}
@Test
public void test01(){
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
}
}
指定时区日期时间
常见时区ID:
Asia/Shanghai
UTC
America/New_York
America/Los_Angeles
可以通过ZondId获取所有可用的时区ID:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;
public class TestZone {
@Test
public void test01() {
//需要知道一些时区的id
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
//快捷模板iter
for (String availableZoneId : availableZoneIds) {
System.out.println(availableZoneId);
}
}
@Test
public void test02(){
ZonedDateTime t1 = ZonedDateTime.now();
System.out.println(t1);
ZonedDateTime t2 = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println(t2);
}
}
持续日期/时间
Period
:用于计算两个日期间隔
Duration
:用于计算两个时间间隔
import org.junit.Test;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
public class TestPeriodDuration {
@Test
public void test01(){
LocalDate t1 = LocalDate.now();
LocalDate t2 = LocalDate.of(2018, 12, 31);
Period between = Period.between(t1, t2);
System.out.println(between);
System.out.println("相差的年数:"+between.getYears());
System.out.println("相差的月数:"+between.getMonths());
System.out.println("相差的天数:"+between.getDays());
System.out.println("相差的总数:"+between.toTotalMonths());
}
@Test
public void test02(){
LocalDateTime t1 = LocalDateTime.now();
LocalDateTime t2 = LocalDateTime.of(2017, 8, 29, 0, 0, 0);
Duration between = Duration.between(t1, t2);
System.out.println(between);
System.out.println("相差的总天数:"+between.toDays());
System.out.println("相差的总小时数:"+between.toHours());
System.out.println("相差的总分钟数:"+between.toMinutes());
System.out.println("相差的总秒数:"+between.getSeconds());
}
}
日期时间格式化
DateTimeFormatter
:该类提供了三种格式化方法:
-
预定义的标准格式。如:ISO_DATE_TIME;ISO_DATE
-
本地化相关的格式。如:ofLocalizedDate(FormatStyle.MEDIUM)
-
自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
public class DatetimeFormatterTest {
@Test
public void test01() {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter df = DateTimeFormatter.ISO_DATE_TIME; // 预定义
String str = df.format(now);
System.out.println(str);
}
@Test
public void test02() {
LocalDateTime now = LocalDateTime.now();
// 本地化相关格式
DateTimeFormatter df = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withZone(ZoneId.systemDefault());
String str = df.format(now);
System.out.println(str);
}
@Test
public void test03() {
LocalDateTime now = LocalDateTime.now();
// 自定义格式
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String str = df.format(now);
System.out.println(str);
}
}
系统相关类
System类
系统类中很多好用的方法,其中几个如下:
- static long currentTimeMillis() :返回当前系统时间距离1970-1-1 0:0:0的毫秒值
- static void exit(int status) :退出当前系统
- static void gc() :运行垃圾回收器。
- static String getProperty(String key):获取某个系统属性,例如:java.version、user.language、user.country、file.encoding、user.name、os.version、os.name等等
import org.junit.Test;
public class TestSystem {
@Test
public void test01(){
long time = System.currentTimeMillis();
System.out.println("现在的系统时间距离1970年1月1日凌晨:" + time + "毫秒");
System.exit(0);
System.out.println("over");//不会执行
}
@Test
public void test02(){
System.out.println(System.getProperty("java.version"));
System.out.println(System.getProperty("user.language"));
System.out.println(System.getProperty("user.country"));
System.out.println(System.getProperty("file.encoding"));
System.out.println(System.getProperty("user.name"));
System.out.println(System.getProperty("os.version"));
System.out.println(System.getProperty("os.name"));
}
@Test
public void test03() throws InterruptedException {
for (int i=1; i <=10; i++){
MyDemo my = new MyDemo(i);
//每一次循环my就会指向新的对象,那么上次的对象就没有变量引用它了,就成垃圾对象
}
//为了看到垃圾回收器工作,我要加下面的代码,让main方法不那么快结束,因为main结束就会导致JVM退出,GC也会跟着结束。
System.gc();//如果不调用这句代码,GC可能不工作,因为当前内存很充足,GC就觉得不着急回收垃圾对象。
//调用这句代码,会让GC尽快来工作。
Thread.sleep(5000);
}
}
class MyDemo{
private int value;
public MyDemo(int value) {
this.value = value;
}
@Override
public String toString() {
return "MyDemo{" + "value=" + value + '}';
}
//重写finalize方法,让大家看一下它的调用效果
@Override
protected void finalize() throws Throwable {
// 正常重写,这里是编写清理系统内存的代码
// 这里写输出语句是为了看到finalize()方法被调用的效果
System.out.println(this+ "轻轻的走了,不带走一段代码....");
}
}
Runtime类
每个 Java 应用程序都有一个 Runtime
类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime
方法获取当前运行时。 应用程序不能创建自己的 Runtime 类实例。
-
public static Runtime getRuntime(): 返回与当前 Java 应用程序相关的运行时对象。
-
public long totalMemory():返回 Java 虚拟机中的内存总量。此方法返回的值可能随时间的推移而变化,这取决于主机环境。
-
public long freeMemory():回 Java 虚拟机中的空闲内存量。调用 gc 方法可能导致 freeMemory 返回值的增加。
public class TestRuntime {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
long totalMemory = runtime.totalMemory();
String str = "";
for (int i = 0; i < args.length; i++) {
str += i;
}
long freeMemory = runtime.freeMemory();
System.out.println("总内存:" + totalMemory);
System.out.println("空闲内存:" + freeMemory);
System.out.println("已用内存:" + (totalMemory-freeMemory));
}
}
数组工具类
Arrays类
java.util.Arrays数组工具类,提供了很多静态方法来对数组进行操作,而且如下每一个方法都有各种重载形式,以下只列出int[]和Object[]类型的,其他类型的数组依次类推:
- 数组元素拼接
- static String toString(int[] a) :元素将自动调用自己从Object继承的toString方法将对象转为字符串进行拼接,如果没有重写,则返回类型@hash值,如果重写则按重写返回的字符串进行拼接。
- 数组排序
- static void sort(int[] a) :将a数组按照从小到大进行排序
- static void sort(int[] a, int fromIndex, int toIndex) :将a数组的[fromIndex, toIndex)部分按照升序排列
- 数组元素的二分查找
- static int binarySearch(int[] a, int key)
- 数组的复制
- static int[] copyOf(int[] original, int newLength) :根据original原数组复制一个长度为newLength的新数组,并返回新数组
- static T[] copyOf(T[] original,int newLength):根据original原数组复制一个长度为newLength的新数组,并返回新数组
- static int[] copyOfRange(int[] original, int from, int to) :复制original原数组的[from,to)构成新数组,并返回新数组
- static T[] copyOfRange(T[] original,int from,int to):复制original原数组的[from,to)构成新数组,并返回新数组
- 比较两个数组是否相等
- static boolean equals(int[] a, int[] a2) :比较两个数组的长度、元素是否完全相同
- static boolean equals(Object[] a,Object[] a2):比较两个数组的长度、元素是否完全相同
- 填充数组
- static void fill(int[] a, int val) :用val值填充整个a数组
- static void fill(Object[] a,Object val):用val对象填充整个a数组
- static void fill(int[] a, int fromIndex, int toIndex, int val):将a数组[fromIndex,toIndex)部分填充为val值
- static void fill(Object[] a, int fromIndex, int toIndex, Object val) :将a数组[fromIndex,toIndex)部分填充为val对象
import org.junit.Test;
import java.text.Collator;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale;
public class TestArrays {
@Test
public void test01() {
int[] arr = {1, 2, 3, 4, 5};
System.out.println(Arrays.toString(arr));
}
@Test
public void test02() {
int[] arr = {3, 2, 5, 1, 6};
System.out.println("排序前" + Arrays.toString(arr));
Arrays.sort(arr);
System.out.println("排序后" + Arrays.toString(arr));
}
@Test
public void test03() {
int[] arr1 = {1, 2, 3, 4, 5};
int[] arr2 = {1, 2, 3, 4, 5};
System.out.println(Arrays.equals(arr1, arr2));
}
@Test
public void test04() {
int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] arr2 = Arrays.copyOf(arr1, 5);
int[] arr3 = Arrays.copyOfRange(arr1, 3, 8);
System.out.println(Arrays.toString(arr2));
System.out.println(Arrays.toString(arr3));
Arrays.fill(arr1, 5, 9, 3);
System.out.println(Arrays.toString(arr1));
}
}
System类
系统类中很多好用的方法,其中几个如下:
- static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length): 从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。常用于数组的插入和删除
import org.junit.Test;
import java.util.Arrays;
public class TestSystemArrayCopy {
@Test
public void test01(){
int[] arr1 = {1,2,3,4,5};
int[] arr2 = new int[10];
System.arraycopy(arr1,0,arr2,3,arr1.length);
System.out.println(Arrays.toString(arr1));
System.out.println(Arrays.toString(arr2));
}
@Test
public void test02(){
int[] arr = {1,2,3,4,5};
System.arraycopy(arr,0,arr,1,arr.length-1);
System.out.println(Arrays.toString(arr));
}
@Test
public void test03(){
int[] arr = {1,2,3,4,5};
System.arraycopy(arr,1,arr,0,arr.length-1);
System.out.println(Arrays.toString(arr));
}
}
自然排序和定制排序
Comparable
基本数据类型的数据(除boolean类型外)需要比较大小的话,之间使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。Java给所有引用数据类型的大小比较,指定了一个标准接口,就是java.lang.Comparable
接口:
package java.lang;
public interface Comparable{
int compareTo(Object obj);
}
使得某个类的对象可以比较大小步骤如下:
第一步:哪个类的对象要比较大小,哪个类就实现java.lang.Comparable
接口,并重写方法
- 方法体就是你要如何比较当前对象和指定的另一个对象的大小
第二步:对象比较大小时,通过对象调用compareTo方法,根据方法的返回值决定谁大谁小。
- this对象(调用compareTo方法的对象)大于指定对象(传入compareTo()的参数对象)返回正整数
- this对象(调用compareTo方法的对象)小于指定对象(传入compareTo()的参数对象)返回负整数
- this对象(调用compareTo方法的对象)等于指定对象(传入compareTo()的参数对象)返回零
代码示例:
class Student implements Comparable {
private String name;
private int age;
private int score;
public Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
public int getScore() {return score;}
public void setScore(int score) {this.score = score;}
@Override
public String toString() {
return "Student{" +
", name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
@Override
public int compareTo(Object o) {
//这些需要强制,将o对象向下转型为Student类型的变量,才能调用Student类中的属性
Student stu = (Student) o;
return this.score - stu.score;
}
}
测试类
public class TestComparable {
public static void main(String[] args) {
Student[] arr = new Student[5];
arr[0] = new Student("张三",23,90);
arr[1] = new Student("熊大",22,100);
arr[2] = new Student("王五",25,75);
arr[3] = new Student("李四",24,85);
arr[4] = new Student("熊二",18,85);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
Comparator
-
如果一个类,没有实现Comparable接口,而这个类又不方便修改(例如:一些第三方的类,你只有.class文件,没有源文件),那么这样类的对象也要比较大小怎么办?
-
如果一个类,实现了Comparable接口,也指定了两个对象的比较大小的规则,但是不想按照它预定义的方法比较大小,由于会影响其他地方的使用,又不能随意修改,怎么办?
JDK在设计类库之初,也考虑到这种情况了,所以又增加了一个java.util.Comparator
接口。
package java.util;
public interface Comparator{
int compare(Object o1,Object o2);
}
那使得某个类的对象可以比较大小步骤如下::
第一步:编写一个类,我们称之为比较器类型,实现java.util.Comparator接口,并重写方法
- 方法体就是你要如何指定的两个对象的大小
第二步:比较大小时,通过比较器类型的对象调用compare()方法,将要比较大小的两个对象作为compare方法的实参传入,根据方法的返回值决定谁大谁小。
- o1对象大于o2返回正整数
- o1对象小于o2返回负整数
- o1对象等于o2返回零
代码示例:
public class TestComparator {
public static void main(String[] args) {
Student[] arr = new Student[5];
arr[0] = new Student(3,"张三",90,23);
arr[1] = new Student(1,"熊大",100,22);
arr[2] = new Student(5,"王五",75,25);
arr[3] = new Student(4,"李四",85,24);
arr[4] = new Student(2,"熊二",85,18);
Arrays.sort(arr, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
});
System.out.println(Arrays.toString(arr));
}
}