✨✨个人主页:沫洺的主页
📚📚系列专栏: 📖 JavaWeb专栏📖 JavaSE专栏 📖 Java基础专栏📖vue3专栏
📖MyBatis专栏📖Spring专栏📖SpringMVC专栏📖SpringBoot专栏
📖Docker专栏📖Reids专栏📖MQ专栏📖SpringCloud专栏
💖💖如果文章对你有所帮助请留下三连✨✨
🌼BigDecimal
BigDecimal是用来精确计算的
常用的构造方法
BigDecimal(double val) 参数为double
BigDecimal(String val) 参数为String(推荐使用)
package moming11; import java.math.BigDecimal; public class B1 { public static void main(String[] args) { BigDecimal bigDecimal1 = new BigDecimal(10.0); BigDecimal bigDecimal2 = new BigDecimal("0.3"); System.out.println(bigDecimal1); System.out.println(bigDecimal2); } }
10 0.3
常用方法
public BigDecimal add(另一个BigDecimal对象) 加法
public BigDecimal subtract (另一个BigDecimal对象) 减法
public BigDecimal multiply (另一个BigDecimal对象) 乘法
public BigDecimal divide (另一个BigDecimal对象) 除法
public BigDecimal divide (另一个BigDecimal对象,精确几位,舍入模式) 除法
package moming11; import java.math.BigDecimal; public class B2 { public static void main(String[] args) { BigDecimal bd1 = new BigDecimal(0.1); BigDecimal bd2 = new BigDecimal(0.2); BigDecimal add = bd1.add(bd2); System.out.println(add); //参数为Double的构造方法运算也会出现精度丢失 System.out.println(0.1+0.2);//普通运算double类型会精度丢失,String类型/int类型不会精度丢失 BigDecimal bd3 = new BigDecimal("0.1"); BigDecimal bd4 = new BigDecimal("0.2"); BigDecimal add1 = bd3.add(bd4);//加法 System.out.println(add1); BigDecimal subtract = bd3.subtract(bd4);//减法 System.out.println(subtract); BigDecimal multiply = bd3.multiply(bd4);//乘法 System.out.println(multiply); BigDecimal divide = bd3.divide(bd4);//除法 System.out.println(divide); BigDecimal bd5 = new BigDecimal("10.0"); BigDecimal bd6 = new BigDecimal("3.0"); //进一法 bigDecimal.ROUND_UP BigDecimal divide1 = bd5.divide(bd6, 2, BigDecimal.ROUND_UP); System.out.println(divide1); //去尾法 BigDecimal divide2 = bd5.divide(bd6, 2, BigDecimal.ROUND_FLOOR); System.out.println(divide2); //四舍五入 BigDecimal divide3 = bd5.divide(bd6, 2, BigDecimal.ROUND_HALF_UP); System.out.println(divide3); } }
0.3000000000000000166533453693773481063544750213623046875 0.30000000000000004 0.3 -0.1 0.02 0.5 3.34 3.33 3.33
浮点类型,十进制转换为二进制时会出现精度丢失
二进制只能精确表示2的-n次方的整数倍小数,这样是不能精确表示所有小数的。
案例
package moming11; import java.math.BigDecimal; /** * 平均值 */ public class B3 { public static void main(String[] args) { double[] doubles = {0.3,0.4,0.5}; BigDecimal sum = new BigDecimal(0); for (int i = 0; i < doubles.length; i++) { BigDecimal bd = new BigDecimal(doubles[i]+""); sum = sum.add(bd); } BigDecimal lengBig = new BigDecimal(doubles.length+""); BigDecimal divide = sum.divide(lengBig, 3, BigDecimal.ROUND_HALF_UP); System.out.println(divide); } }
0.400
总结
1, BigDecimal是用来进行精确计算的
2,创建BigDecimal的对象,构造方法使用参数类型为字符串的。
3,四则运算中的除法,如果除不尽请使用divide的三个参数的方法。
代码示例:
BigDecimal divide = bd1.divide(参与运算的对象, 小数点后精确到多少位, 舍入模式);
参数1 ,表示参与运算的BigDecimal 对象。
参数2 ,表示小数点后面精确到多少位
参数3 ,舍入模式
BigDecimal.ROUND_UP 进一法
BigDecimal.ROUND_FLOOR 去尾法
BigDecimal.ROUND_HALF_UP 四舍五入
🌹包装类
包装类就是将基本数据类型封装为对象,将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据 常用的操作之一:用于基本数据类型与字符串之间的转换
基本数据类型 包装器类型(对象类型)valueOf().parse() boolean Boolean char Character int Integer byte Byte short Short long Long float Float double Double
🌷装箱、拆箱
装箱:把基本数据类型转换为对应的包装类类型
拆箱:把包装类类型转换为对应的基本数据类型
自动装箱 可以自动的将基本数据类型转换成包装类
自动拆箱 可以自动的将包装类转换成基本数据类型自动装箱的本质
将java文件编译成class文件时,将 Integer i1 = 10; 自动的转换成了Integer i1 = Integer.valueOf(10);自动拆箱的本质
将java文件编译成class文件时, 将 int i3 = i2; 自动的转换成了 int i3 = i2.intValue();
Integer i = 100; // 自动装箱
i += 200; // i = i + 200; i + 200 自动拆箱;i = i + 200; 是自动装箱
Integer i1 = 128; // 装箱,相当于 Integer.valueOf(128);
int t = i1; //相当于 i1.intValue() 拆箱
泛型不支持基本类型
List<int> 错误的
List<Integer> 正确的
package cn.moming11;
//8大基本类型 byte short int long float double char boolean
public class Demo {
public static void main(String[] args) {
//自动装箱 装箱(包装类.valueOf)
Byte a = 95; //Byte a = Byte.valueOf((byte) 95);
Short b = 10; //Short b = Short.valueOf((short) 10);
Integer c = 100; //Integer c = Integer.valueOf(100);
Long d = 1000l; //Long d = Long.valueOf(1000);
Float e = 1.23f; //Float e = Float.valueOf(1.23f);
Double f = 4.56; //Double f = Double.valueOf(4.56);
Character g = 'a'; //Character g = Character.valueOf('a');
Boolean h = true; //Boolean h = Boolean.valueOf(true);
//自动拆箱 拆箱(.基本类型Value())
byte aa = a; //byte aa = a.byteValue();
short bb = b; //short bb = b.shortValue();
int cc = c; //int cc = c.intValue();
long dd = d; //long dd = d.longValue();
float ee = e; //float ee = e.floatValue();
double ff = f; //double ff = f.doubleValue();
char gg = g; //char gg = g.charValue();
boolean hh = h; //boolean hh = h.booleanValue();
}
}
注意
在使用包装类类型的时候,如果做操作,最好先判断是否为 null ,只要是对象,在使用前就必须进行不为 null 的判断
获取Integer对象
public static Integer valueOf(String s) 返回一个保存指定值的Integer对象
Integer.valueOf方法使用时,参数只能是 字符串类型的整数
int 和 String 的相互转换
package cn.moming11; public class Demo { public static void main(String[] args) { //int 和 String 的相互转换 int a = 10; String b = "20"; //int转换为String //方式一 String aa1 = a+""; //方式二 String aa2 = String.valueOf(a); //String转换为int int bb = Integer.parseInt(b); } }
double和String相互转换
package cn.moming11; public class Demo1 { public static void main(String[] args) { double d = 10.23; String c = "6.7"; //double转换为String //方式一 String dd1 = d+""; //方式二 String dd2 = String.valueOf(d); //String转换为double double cc = Double.parseDouble(c); } }
byte和String相互转换
package cn.moming11; public class Demo1 { public static void main(String[] args) { byte e = 'a'; String f = "97"; //byte转换为String //方式一 String ee1 = e+""; //方式二 String ee2 = String.valueOf(e); //String转换为byte byte ff = Byte.parseByte(f); //System.out.println(e==ff); } }
boolean和String相互转换
package cn.moming11; public class Demo1 { public static void main(String[] args) { boolean x = true; String y = "false"; //boolean转换为String //方式一 String xx1 = x+""; //方式二 String xx2 = String.valueOf(x); //String转换为boolean boolean yy = Boolean.parseBoolean(y); } }
其他基本数据类型同理
注意:
包装类毕竟是引用数据类型,引用数据类型就可以赋值成null, 那么拿包装类直接进行加减乘除运算时就很有可能出现空指针异常
🌻冒泡排序
排序:将一组数据按照固定的规则进行排列
冒泡排序:相邻的数据两两比较,小的放前面,大的放后面。
如果有n个数据进行排序,总共需要比较n-1次
每一次比较完毕,下一次的比较就会少一个数据参与
package cn.moming11; import java.util.Arrays; public class BubbleSort { public static void main(String[] args) { int[] arr = {4,51,23,77,99,1,2,33,54,20,15,88,17,36,43}; int[] newArr = getSort(arr); System.out.println(Arrays.toString(newArr)); } private static int[] getSort(int[] arr) { for (int i = 0; i < arr.length-1; i++) {//④整个内循环执行一次,就有个最大值的位置固定,此时i就表示有几个固定的值(内循环执行完一次i就加1) for (int j = 0; j < arr.length-1-i; j++) {//②然后j自身加1,继续进行两两比较,比较到最后,最大的一定是先经过循环比较,放到了最右边 //③又因为随着每次的内循环比较,最大值(次大值~~)的位置已经固定了,所以参与比较到数就没必要和最大值(次大值~~)去比较了(没意义),所以索引j < arr.length-1-i if(arr[j]>arr[j+1]){//①两两比较,拿第一个和第二个比较,大的放右边,小的放左边 int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } return arr; } }
[1, 2, 4, 15, 17, 20, 23, 33, 36, 43, 51, 54, 77, 88, 99]
🌺递归
什么是递归
方法自己调用自己
什么时候使用递归
- 使用递归一定要设计出口,防止出现死循环
- 能使用循环解决的就直接使用循环就行了,不能循环在考虑递归
- 主要解决:当我们没办法确定循环层数的需求,使用递归
案例一
计算1到指定数的累加和
package cn.moming11; /** * 计算1到指定数的累加和 */ public class Recursion { public static void main(String[] args) { int num = 100;//1~100的累加 int sum = getAdd(num); System.out.println(sum); } private static int getAdd(int i) { if(i==1){//如果指定的数是1,返回1 return i; }else { int i1 = getAdd(i - 1) + i;//注意getAdd获取的是返回值 return i1; } } }
5050
所以递归的返回值是通过最底层的get(1)返回值,逐层的向上返回
也就是先通过get(1)的返回值,获取get(2)的返回值,...... ,最后获取get(100)的返回值
案例二
package cn.moming11; /** * 计算指定数的阶乘 */ public class Recursion { public static void main(String[] args) { int num = 4; long ft = getFactorial(num); System.out.println(ft); } private static long getFactorial(long i) { if (i==1)return 1; else return getFactorial(i-1)*i; } }
24
💐二分查找
二分查找的前提,对数组而言一定是有序的
数组的二分查找步骤
1,定义两个变量,表示要查找的范围。默认min = 0 , max = 最大索引
2,循环查找,但是min <= max
3,计算出mid的值
4,判断mid位置的元素是否为要查找的元素,如果是直接返回对应索引
5,如果要查找的值在mid的左半边,那么min值不变,max = mid -1.继续下次循环查找
6,如果要查找的值在mid的右半边,那么max值不变,min = mid + 1.继续下次循环查找
7,当 min > max 时,表示要查找的元素在数组中不存在,返回-1.
package cn.moming11; public class BinarySearchIndex { public static void main(String[] args) { int[] arr = new int[]{11,12, 15, 27, 27, 38, 39, 42, 46, 55, 66, 69, 81, 94, 101}; int num = 11; int index = getIndex1(arr, num); System.out.println(index); } private static int getIndex1(int[] arr, int num) { int min = 0; int max = arr.length - 1; while (min <= max) { //查找的前提是min<=max int mid = (min + max) >> 1; //计算中间索引 if (arr[mid] > num) { //如果中间索引位置的元素大于指定数num max = mid - 1; //说明num在中间值左边,那么最大索引max=mid-1 } else if (arr[mid] < num) { //如果中间索引位置的元素小指定数num min = mid + 1; //说明num在中间值右边,那么最大索引max=mid+1 } else { //如果上述都不成立,说明中间值arr[mid]就是num return mid; } } return -1; //如果min!<=max,说明已经查完了,不存在 } }
0
注意上述代码查找的数组指定元素是没有重复的,如果出现重复它只能返回其中一个元素的索引。
案例
二分查找结合递归,解决重复元素索引都输出
package cn.moming11; import java.util.HashSet; public class BinarySearch { public static void main(String[] args) { int[] arr = new int[]{11, 11, 12, 15, 27, 27, 38, 39, 42, 46, 55, 55, 55, 66, 69, 81, 94, 101, 101}; int num = 27; HashSet<String> indexs = getIndexs(arr, num); System.out.println(indexs); } //通过二分查找后返回的单个元素的索引,判断该索引前后的元素是否与该索引元素相等,如果相等,将相等的元素的索引也一并返回 private static HashSet<String> getIndexs(int[] arr, int num) { int index = getIndex(arr, num);//此方法是二分查找后返回的单个元素的索引 int i = index; String indexs = i + " ";//int 转换为 String while (true) { //找左边的是否相等 if (i > 0) { //判断是不是最左边的索引位置,不是就进行判断,目的是放在索引越界异常 if (arr[i] == arr[i - 1]) {//如果左边的元素和二分查找后返回的单个元素的索引相等 indexs += (i - 1) + " ";//就加上该索引,并用空格分开 i--;//继续左边的左边(通过死循环接着找) } else break;//如果左边的元素和二分返回索引不相等,就没必要查左边了 } else break;//如果是最左边的索引位置,就不需要找左边了 } while (true) { if (i < arr.length - 1) {//判断是不是最右边的索引位置,不是就进行判断,目的是放在索引越界异常 if (arr[i] == arr[i + 1]) {//如果右边的元素和二分查找后返回的单个元素的索引相等 indexs += (i + 1) + " ";//就加上该索引,并用空格分开 i++;//继续右边的右边(通过死循环接着找) if (i > arr.length - 1) break; } else break;//如果右边的元素和二分返回索引不相等,就没必要查右边了 } else break;//如果是最左边的索引位置,就不需要再找右边了 } //由于拼接后的索引中,二分返回索引有两个,需要去掉一个 String[] s = indexs.split(" ");//将索引拼接字符串通过空格分割为字符串数组 HashSet<String> set = new HashSet<>();//利用set集合的去重特性 for (String s1 : s) {//增强for遍历 set.add(s1);//将字符串数组添加到set集合中 } return set;//最后返回集合 } private static int getIndex(int[] arr, int num) {//方法重载 int min = 0;//最小索引 int max = arr.length - 1;//最大索引 int mid = (min + max) >> 1;//中间索引 return getIndex(arr, num, min, max, mid);//方法的返回值放在这里再次返回 } private static int getIndex(int[] arr, int num, int min, int max, int mid) { mid = (min + max) >> 1;//重写计算中间索引,配合递归 if (max < min) { //如果min>max,说明已经查完了,不存在 mid = -1; //返回-1 return mid; //真正的返回值(没找到的索引) } if (arr[mid] > num) {//如果中间索引位置的元素大于指定数num max = mid - 1;//说明num在中间值左边,那么最大索引max=mid-1 return getIndex(arr, num, min, max, mid);//递归后继续查找,递归方法的返回值放在这里返回 } if (arr[mid] < num) {//如果中间索引位置的元素小指定数num min = mid + 1;//说明num在中间值右边,那么最大索引max=mid+1 return getIndex(arr, num, min, max, mid);//递归后继续查找,递归方法的返回值放在这里返回 } if (arr[mid] == num) {//中间值arr[mid]和num相等,直接返回该索引mid return mid; //真正的返回值(找到的索引) } return 0; //只是语法需要,不起作用,真正的返回值在上面 } }
[4, 5]
🌾Arrays类
Arrays 类包含用于操作数组的各种方法
public static String toString(int[] a) 返回指定数组的内容的字符串表示形式
public static void sort(int[] a) 按照数字顺序排列指定的数组
public static int binarySearch(int[] a, int key) 利用二分查找返回指定元素的索引
package cn.moming11; import java.util.Arrays; public class ArraysDemo { public static void main(String[] args) { int[] arr = {4, 51, 23, 77, 99, 1, 2, 33, 54, 20, 15, 88, 17, 36, 43}; Arrays.sort(arr);//按照数字顺序排列指定的数组 System.out.println(Arrays.toString(arr));//返回指定数组的内容的字符串表示形式 int index = Arrays.binarySearch(arr, 43);//利用二分查找返回指定元素的索引 System.out.println(index); } }
[1, 2, 4, 15, 17, 20, 23, 33, 36, 43, 51, 54, 77, 88, 99] 9