JavaImprove--Lesson03--String的工具类,Math,Runtime,BigDecimal,Date

发布时间 2024-01-07 12:10:57作者: 回忆也交给时间

一String的工具类

String的作为字符串对象,也是使用最多的数据类型对象

所以难免有很多操作,字符串的常见操作包括:字符串拼接,字符串反转,字符串长度,字符串转换等

直接使用String类型来操作是不推荐的,因为它是不变长类型对象,效率很低,我们需要频繁的操字符串的时候就需要使用变长的字符串类

String的工具类有:StringBuilder,StringBuffer,StringJoiner

StringBuilder

在Java中,StringBuilder是一个可变的字符序列,用于构建和操作字符串。它提供了比String类更高的性能,因为它允许修改字符串内容而不需要创建新的字符串对象。

与String不同,StringBuilder对象的内容是可变的。你可以使用各种方法来修改它,例如append(), insert(), delete(), 和 replace()。

//无参构造
StringBuilder s1 = new StringBuilder();
//有参构造,初始化一些字符串数据
StringBuilder s2 = new StringBuilder("test");

 

 

append()实现字符串拼接,可以拼接任何的数据类型,最后返回拼接好的字符串:

//无参构造
StringBuilder s1 = new StringBuilder();
s1.append(1); //拼接 int 型
s1.append('a'); //拼接字符
s1.append(25.3); //拼接浮点数
s1.append("asdf"); //拼接字符串
System.out.println(s1.toString()); // 1a25.3asdf

 

reverse()实现字符串反转:

System.out.println(s1.toString()); // 1a25.3asd
System.out.println(s1.reverse()); //fdsa3.52a1

 

toString()将StringBuilder对象转换为字符串输出:

String rs = s1.toString();
System.out.println(rs);// 1a25.3asdf

 

StringBuffer

StringBuffer和StringBuilder使用的的方式是一样的,甚至连API都是一样的

它们的不同点在于StringBuffer是基于线程安全的,而StringBuilder是线程步安全的

也就是说,当在多线程,多用户操作的系统内,使用StringBuilder是不安全的,而StringBuffer则是可以在多用户下正常工作的

//无参构造
StringBuffer s1 = new StringBuffer();
//有参构造
StringBuffer s2 = new StringBuffer("test");

 

append(),replace(),reverse(),toStrring()等方法和StrngBuilder是一样的

StringJoiner

StringJoiner 是 Java 中的一个类,位于 java.util 包中。它是用来将多个字符串连接成一个字符串的便捷工具

它是一个JDK8出现的工具类,它具有比StringBuilder处理更快,但是代码更简介的特点

在实现字符拼接时可以通过有参构造传入:间隔符,开始符,结束符

注意这里是间隔符,两两之间才能叫间隔符,开始符和结束符也是对应整个字符串的开始和结束 

//有参构造,间隔符
StringJoiner s1 = new StringJoiner(", ");
//有参构造,间隔符,开始符,结束符
StringJoiner s2 = new StringJoiner(", ","{ "," }");

 

add()字符串拼接:

//有参构造,间隔符
StringJoiner s1 = new StringJoiner(", ");
s1.add("abc");
s1.add("xyz"); 
System.out.println(s1.toString());  //abc, xyz

 

案例:将数组中的元素转化为字符串,数据:{11,22,22},格式为:[11, 22, 33]

使用StringBuilder作答:

public static void main(String[] args) {
    //传入参数为匿名对象
    System.out.println(ArrToString(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}));
    //[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
}
public static String ArrToString(int[] arr){
    //判空
    if (arr == null){
        return null;
    }
    StringBuilder s1 = new StringBuilder();
    //拼接开始符
    s1.append("[ ");
    for (int i = 0; i < (arr.length-1); i++) {
        //拼接中间元素和间隔符
        s1.append(arr[i]).append(", ");
    }
    //拼接最后一个元素和结束符
    s1.append(arr[arr.length-1]).append(" ]");
    return s1.toString();
}

 

使用StringJoiner作答:

    public static void main(String[] args) {
        //传入参数为匿名函数
        System.out.println(ArrayToString(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}));
        //[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
    }
    public static String ArrayToString(int[] arr){
        if (arr == null){
            return null;
        }
        //StringJoiner直接声明:间隔符,开始符,结束符
        StringJoiner s1 = new StringJoiner(", ", "[ ", " ]");
        for (int i = 0; i < arr.length; i++) {
            s1.add(String.valueOf(arr[i]));
        }
        return s1.toString();
    }

 

二.Math,Runtime

Math是数学函数库

常用的数学函数

abs()取绝对值:

// public static double abs(double a)
//取绝对值
System.out.println(Math.abs(-12.3));// 12.3

 

ceil()向上取整:

//public static double ceil(double a);
//向上取整
System.out.println(Math.ceil(12.3)); //13.0

 

floor()向下取整:

//public static double floor(double a)
//向下取整
System.out.println(Math.floor(12.3)); //12.0

 

round()四舍五入:

//public static long round(double a)
//四舍五入
System.out.println(Math.round(12.3));//12

 

max()/min()最大最小值:

// public static int max / min (int a,int b
//查找最大值或最小值
System.out.println(Math.max(12, 13)); //13

 

pow()求次方数:

// public static double pow(double a,double b)
//取次方
System.out.println(Math.pow(2, 3)); //2的3次方 :8.0

 

random()取随机数:

//public static double random()
//取随机数
System.out.println(Math.random()); //[0,1) 

Runtime

指的是Java的JVM虚拟机的运行的一个状态类,并且是个单例类,因为运行状态只有一个

Java的Runtime类是Java虚拟机的一部分,它提供了与运行时环境相关的各种方法和功能

需要注意的是,由于Runtime类与底层系统紧密相关,因此在使用它时要特别小心。不正确的使用可能会导致资源泄漏、性能问题或安全风险。在大多数情况下,使用标准Java API(如System类)提供的工具和方法更为安全和可靠。

获取Runtime对象:

// public static Runtime getRuntime()
//返回与当前Java应用程序关联的运行时对象
Runtime run = Runtime.getRuntime();

 

终结JVM虚拟机:

//public void exit(int status)
//终结当前的虚拟机运行,输入的状态码 0 表示正常结束,非 0 表示非正常结束

 

获取当前系统的处理器数:

//public int availableProcessors()
//获取当前的的处理器数
System.out.println(run.availableProcessors());

 

JVM的内存总量,单位B:

//public long totalMemory()
//返回Java虚拟机的内存总量 单位:B
System.out.println(run.totalMemory()/1024.0/1024 + "MB");//243.5MB

 

JVM当前可用容量,单位B:

//public long freeMemory()
//返回Java虚拟机中的可用内存量
System.out.println(run.freeMemory()/1024.0/1024 + "MB");//238.4MB

 

启动其它程序:

//public Process exec(String command)
//启动某个程序,并返回代表此程序的对象
Process process = run.exec("D:\\Tencent\\WeChat\\WeChat.exe"); //启动微信
Thread.sleep(5000);//线程休眠5s
process.destroy();//销毁进程,=》关闭微信

 三.BigDecimal

 在数据运算时候,尤其是对浮点数的加减乘除,都是有可能丢失精度的

因为基本类型的浮点数,double,float都是讲浮点数转为分数来计算的,如:1/2 + 1/3 + 1/4 + .... 1/n等

但是这就存在丢失精度的可能了,最简单的例子0.1 + 0.2 :

double a = 0.1;
double b = 0.2;
System.out.println(a + b); //0.30000000000000004

 

这就是基本类型的普通浮点数直接运算的问题,为了解决这个问题,Java提供了BigDecimal类来解决,解决思想是将浮点数转为字符数组来按位计算

BigDecimal 是 Java 中的一个类,用于表示和操作高精度的十进制数。

它通常用于金融和货币计算,因为它可以提供精确的小数点后的数值表示,而不会出现浮点数运算中的舍入误差。 

 BigDecimal有两种构造方式,

一种是构造器中传入一个浮点数

一种构造器是传入一个String类型

  •  将构造器中传入一个浮点数是不推荐的做法,因为在进行运算的时候还是以浮点数double进行运算的,所以该有的精度丢失还是会有的
double a = 0.1;
double b = 0.2;
BigDecimal a1 = new BigDecimal(a);
BigDecimal b1 = new BigDecimal(b);
BigDecimal c1 = a1.add(b1);
System.out.println(c1); //0.3000000000000000166533453693773481063544750213623046875

 

  •  在构造器中传入一个String类型的数据,利用字符数组来存储,然后按位计算
double a = 0.1;
double b = 0.2;
BigDecimal a1 = new BigDecimal(String.valueOf(a));
BigDecimal b1 = new BigDecimal(String.valueOf(b));
BigDecimal c1 = a1.add(b1);
System.out.println(c1); //0.3

 

 如上,如果传入的是字符串的形式就不会存在精度丢失的情况了

我们可以利用DeBug来查看这些情况:

 如上图:

我们的BigDecimal类是将浮点数利用字符数组存储的,包括小数点都有一个ASCII码存在字符数组里

相关的方法:

valueOf()将一个double类型的数据转换为BigDecimal类:

此方法是一个静态方法,可以直接点 出来

double a = 0.1;
BigDecimal a1 = BigDecimal.valueOf(a);
double b = 0.2;
BigDecimal b1 = BigDecimal.valueOf(b);
System.out.println(a1.add(b1));

 

使用valueOf()也是Java官方推荐的,并且是转为字符数组然后按位运算

add()加法:

double a = 0.1;
BigDecimal a1 = BigDecimal.valueOf(a);
double b = 0.2;
BigDecimal b1 = BigDecimal.valueOf(b);
//public BigDecimal add(BigDecimal b)
//两个BigDecimal对象进行加法运算
BigDecimal c1 = a1.add(b1);
System.out.println(c1);
subtract()减法:
double a = 0.1;
BigDecimal a1 = BigDecimal.valueOf(a);
double b = 0.2;
BigDecimal b1 = BigDecimal.valueOf(b);
//public BigDecimal subtract(BigDecimal b)
//两个BigDecimal对象进行减法运算
BigDecimal c1 = a1.subtract(b1);
System.out.println(c1);// -0.1
multiply()乘法:
double a = 0.1;
BigDecimal a1 = BigDecimal.valueOf(a);
double b = 0.2;
BigDecimal b1 = BigDecimal.valueOf(b);
//public BigDecimal multiply(BigDecimal b)
//两个BigDecimal对象进行乘法运算
BigDecimal c1 = a1.multiply(b1);
System.out.println(c1);// 0.02
divide()除法:
double a = 0.1;
BigDecimal a1 = BigDecimal.valueOf(a);
double b = 0.2;
BigDecimal b1 = BigDecimal.valueOf(b);
//public BigDecimal divide(BigDecimal b)
//两个BigDecimal对象进行除法运算
BigDecimal c1 = a1.divide(b1);
System.out.println(c1);// 0.5

 doubleValue()返回为double类型:

double a = 0.1;
BigDecimal a1 = BigDecimal.valueOf(a);
double b = 0.2;
BigDecimal b1 = BigDecimal.valueOf(b);
BigDecimal c1 = a1.divide(b1);
//将BigDecimal对象还原成为double类型
double c2 = c1.doubleValue();
System.out.println(c2);// 0.5

 

使用divide()方法时,需要注意,被计算的两个数一定要是可以有精确值的

意味着这两个数的结果不能是,无限循环小数,无限不循环小数等无限数,否则会报错(Non-terminating decimal expansion; no exact representable decimal result.)

因为BigDecimal类是用于解决精度丢失的问题的,不是解决无限数的

如果被除数一定要是无线数,就可以通过传入保留位数和舍入方式来控制

double a = 0.1;
BigDecimal a1 = BigDecimal.valueOf(a);
double b = 0.3;
BigDecimal b1 = BigDecimal.valueOf(b);
//被除数 保留两位小数  四舍五入
BigDecimal c1 = a1.divide(b1,2, RoundingMode.HALF_UP);
System.out.println(c1);// 0.5

 四.Date

Date代表的是系统当前的时间

Java 的 Date 类是 Java 核心库的一部分,位于 java.util 包中。它是用来表示特定的瞬时,精确到毫秒的时间。这个类经常用于日期和时间相关的操作,包括日期的获取、日期的比较以及日期的格式化。

Date类推荐的构造器有两个

无参构造:直接获得时间格式

//无参构造
Date d1 = new Date();
System.out.println(d1); //Sun Jan 07 10:18:54 CST 2024

 

有参构造:将时间戳转换为时间格式

//有参构造
long d2 = d1.getTime();
Date d3 = new Date(d2);
System.out.println(d3);  //Sun Jan 07 10:18:54 CST 2024

 

常用的Date对象方法:

getTime():获得当前时间对象的时间戳

//有参构造
long d2 = d1.getTime();
System.out.println(d2); //1704594144133

 

setTime(long str):设置时间对象的时间

//无参构造
Date d1 = new Date();
System.out.println(d1); //Sun Jan 07 10:24:58 CST 2024
//有参构造
long d2 = d1.getTime();
long tim = d2 + 5*1000; //向后加 5s
d1.setTime(tim);
System.out.println(d1);  //Sun Jan 07 10:25:03 CST 2024

 

SimpleDateFormat

SimpleDateFormat 是 Java 中的一个类,属于 java.text 包。它用于日期和时间的格式化和解析,提供了以与语言环境有关的方式来格式化和解析日期的方法。

SimpleDateFormat 允许将日期转换为字符串,以及将字符串解析为日期。它提供了多种用于格式化和解析的静态方法

其中格式化时间符号:

y:年,M:月,d:日,H:时,m:分,s:秒,EEE:星期几,a:区分上下午

示例:

//获得时间对象
Date date = new Date();
//创建SimpleDateFormat对象并且传入时间格式
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE a");
//.format方法实现格式化
String day = dateFormat.format(date);
System.out.println(day); //2024-01-07 10:32:33 星期日 上午

 

注意,时间格式是可以进行字符拼接的,只要时间符号保持原位就行了,比如拼接上-年-月-日

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a"); //2024年01月07日 10:41:32 星期日 上午

 

parse(String str):将字符串格式的时间转换为Date类型的时间

//字符串日期
String data = "2002-11-04 12:25:31";
//格式样式
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//将字符转为Date
Date parse = dateFormat.parse(data);
System.out.println(parse);

 

注意,使用parse方法需要保证字符转时间格式和待转换的时间格式是一样的,不然会出错,且不能进行字符串拼接了

Calender

代表当前系统的日历对象

在编程中,Calendar 对象通常是指与日期和时间相关的数据结构或类。Calendar 提供了一个表示特定日期或时间的方式,并且常常用于日期和时间的计算、格式化以及解析。

在 Java 中,java.util.Calendar 是一个非常常用的 Calendar 类。它提供了一系列方法来操作日期和时间,例如添加或减去时间,获取月份、星期、日期的天数等

getInstance():

//获得日历对象。官方推荐使用静态方法,而不是使用构造器
Calendar calendar = Calendar.getInstance();

 

get(int  n):获取日历的内容,传入的参数是Calender类的常量

//获得年份
int year = calendar.get(Calendar.YEAR);
System.out.println(year); //2024
//获得月份 0~ 11
int month = calendar.get(Calendar.MONTH);
System.out.println(month);//0
//获得日期
int day = calendar.get(Calendar.DAY_OF_YEAR);
System.out.println(day); //7

 

getTime():获得时间

//获得当前日期,和Date相同
Date time = calendar.getTime();
System.out.println(time);//Sun Jan 07 11:54:33 CST 2024

 

getTimeInMillis():获得时间戳

//获得时间戳 
long t = calendar.getTimeInMillis();
System.out.println(t);//1704599837468

 

set(int feild,int value):修改日历中的某个值:feild:Calender类的常量,value:修改的值

//获得当前年份
int year = calendar.get(Calendar.YEAR);
System.out.println(year);//2024
//更改当前年份
calendar.set(Calendar.YEAR,2028);
int year2 = calendar.get(Calendar.YEAR);
System.out.println(year2);//2028

 

add(int feild,int amount):对某个信息增加/减少指定的值

//获得当前年份
int year = calendar.get(Calendar.YEAR);
System.out.println(year);//2024
//增加10年
calendar.add(Calendar.YEAR,10);
int year2 = calendar.get(Calendar.YEAR);
System.out.println(year2);//2034
//减少20年
calendar.add(Calendar.YEAR,-20);
int year3 = calendar.get(Calendar.YEAR);
System.out.println(year3);//2014

 

注:calender是可变对象,一旦修改后其对象本身表示的时间也会变化(单例模式)