大数

当基本的整数和浮点数精度不能够满足你的需求的时候,我们就可以引入在java.math包中的两个类——BigIntegerBigDecimal。这两个类可以处理任意长度的数值。

BigInteger类可以处理任何精度的整数运算,而BigDecimal类可以处理任何精度的浮点数运算

它们的使用方法非常简单:

1
2
BigInteger bi = new BigInteger("...");//大整数
BigDecimal bd = new BigDecimal("...");//大浮点数

bi / bd处可以填入任意你想叫的名字,当然,最好还是尊重一下命名规则,除非你想让你的代码无人能够流畅阅读,甚至是刚睡了一觉的你。而...处是填入你想要的给bi / bd赋的数值。

我们也可以使用静态的valueOf方法将普通的数转换为大数,就像这样:

1
BigInteger bi = BigInteger.valueOf(100);//100这里可以改成别的数或者是变量

由于大数不是基础数据类型,我们就无法使用熟悉的算数运算符来处理大数,而是应该使用大数类型中的方法,下表列出最常见的运算:

BigInteger:

方法名称 说明
add(BigInteger other) 做加法运算
subtract(BigInteger other) 做减法运算
multiply(BigInteger other) 做乘法运算
divide(BigInteger other) 做除法运算
remainder(BigInteger other) 做取余数运算
pow(int n) 做n次方运算
mod(BigInteger other) 返回两个大数的和、差、积、商、余数

BigDecimal:

BigDecimal基本运算大致与BigInteger相同,但除法有所不同,因为需要考虑到除不尽末尾小数的处理方法。

方法名称 说明
add(BigDecimal other) 做加法运算
subtract(BigDecimal other) 做减法运算
multiply(BigDecimal other) 做乘法运算
divide(BigDecimal other) 做除法运算
divide(BigDecimal other,int scale, roundingMode) 做除法运算,三个参数分别代表除数,商后的位数,近似值的处理模式

近似值的处理模式有太多种了,这里只介绍一个,即最常见的四舍五入——ROUND_HALF_UP

来个例子吧:

1
2
3
4
5
6
7
8
public class Test {
public static void main(String[] args) {
BigDecimal bd1 = new BigDecimal("1234567890123456789012345678901234567890");
BigDecimal bd2 = new BigDecimal("9876543210987654321098765432109876543210");
BigDecimal bd3 = bd1.divide(bd2, 10, BigDecimal.ROUND_HALF_UP);
System.out.println(bd3);//out:0.1249999989
}
}

用var声明局部变量

在Java10以上的版本,对于可以从变量初始值推导出他们的类型的,可以用var关键词声明局部变量。

注意,一定是在Java10以上的版本,var关键词是在该版本才引入的。

1
2
var a = new Student("a", 18, 100);
var b = "hello world";

var关键词避免了重复写类型名,优化了写代码体验与观感,非常便利。

字符串

子串

String类中的substring方法可以从字符串中提取出一个子串。

使用方法:

1
2
String s1 = "Hello";
String s2 = s1.substring(1, 3);//s2 = "el"

1处填入的是截取开始的位置,3截取结束的位置。(tips:字符串位置跟数组一样是从0开始的)

拼接

有截取的方法,那自然有拼接的方法,使用+号就可以拼接起两个字符串:

1
2
String s1 = "Hello";
String s2 = s1+s1;//s2 = "HelloHello"

当一个字符串与非字符串拼接时,非字符串就会转换成字符串进行拼接:

1
2
3
String s1 = "Hello";
int i = 233;
String s2 = s1 + i;//s2 = "Hello233"

这种用法我们就常常用在输出结果。

当我们希望多个字符串放在一起的时候,我们也可以使用join方法:

1
2
3
String s1 = "Hello";
String s2 = "World";
String s3 = String.join(s1, " ", s2);//s3 = "Hello World"

在Java11以上的版本,还提供了一个重复某个字符串多次的方法repeat

1
2
String s1 = "Hello";
String s2 = s1.repeat(3);//s2 = "HelloHelloHello"

不可变字符串

Java的字符串与C语言的字符串不太相同,Java字符串不是一个数组,它的字符串不可以修改里面的某一个字符,想修改字符串,只能通过截取字符串,再重新拼接方式来修改:

1
2
String s1 = "Helle";
s1 = s1.substring(0, 4)+"o!";//s1 = "Hello!"

判断字符串是否相等

虽然字符串不是一个数组,但是我们也不能通过==来判断是否相等,而是应该用equals方法来判断:

1
2
3
4
5
String s1 = "Hello";
String s2 = "World";
String s3 = "Hello";
s1.equals(s2);// false
s1.equals(s3);// true

如果我们想让判断不区分大小写,我们还可以用equalsIgnoreCase来判断。

==判断符只能判断两个字符串是否在同一位置(地址)上,而不能真正判断是否相等:

1
2
3
4
String str = "Hello";
if(str.substring(0, 3) == "Hel"){
System.out.println("true");//
}//none

构建字符串

如果我们遇到需要经常拼接的情况,例如读取按键的时候,我们采用上面那种字符串拼接方式,就会导致每次都要构建一个新的String对象,既耗时又浪费空间,效率低下,这时候,我们使用StringBuilder类就可以避免这个问题的发生。

首先我们需要构建一个空的字符串构造器:

1
StringBuilder builder = new StringBuilder();

然后就可以使用StringBuilder类的方法来构建字符串了,下面给出部分常用的方法:

方法名 作用
append(String str / char c) 添加一个字符串 / 代码单元
setCharAt(int i, char c) 讲第 i 个代码单元替换为 c
insert(int i, String str / char c) 在 i 的位置插入字符串str / 代码单元 c
delete(int i, int j) 删除 i 到 j 的代码单元

在构建完字符串之后就可以使用toString返回一个字符串了。

例:

1
2
3
4
StringBuilder builder = new StringBuilder();
builder.append("hello");
builder.append("world");
System.out.println(builder.toString());//out:helloworld

文件的输入输出

当我们需要读取一个文件,需要构建一个Scanner对象:

1
Scanner in = new Scanner(Path.of("test.txt"), StandardCharsets.UTF_8);

Path.of("...")这里面填入的是文件的位置,当你填入像上面那种相对地址时,该相对地址是相对于Java虚拟机启动目录的位置,实际上我认为还是填入绝对地址比较方便,例如c:\\testPath\\test.txt/home/icewindy/testPath/test.txt

StandardCharsets.UTF_8很容易看出,这里填入的是文件的编码格式,如果不指定文件的编码格式,则会使用运行该程序的机器的“默认编码”,或许会导致不同平台上运行效果的差异,不建议这样使用。