Math类
常用方法
//Math常用方法
//1.abs绝对值
int abs = Math.abs(-647);
System.out.println(abs);//647
//2.pow求幂
double pow = Math.pow(2, 4);//求2的4次方
System.out.println(pow);//16.0
//3.ceil向上取整,返回>=该参数的最小整数
double ceil = Math.ceil(-3.001);
System.out.println(ceil);//-3.0
//4.floor向下取整
double floor = Math.floor(2.97);
System.out.println(floor );//2.0
//5.round四舍五入
long round = Math.round(99.99);
System.out.println(round);//100
//6.sqrt求开方
double sqrt = Math.sqrt(9.0);
System.out.println(sqrt);//3.0
//7.random求随机数 random返回的是0~1之间的随机小数 [0,1)
System.out.println(Math.random());//0.5390963838028429
//请写出获取a~b之间的一个随机整数,a,b均为整数 2~7间
for (int i = 0; i < 10; i++) {
System.out.println((int)(Math.random()*6+2));
}
//求[a,b]间随机数的公式: (int)(a+Math.random()*(b-a+1));
//Math.max Math.min就是返回最大值和最小值,就不演示了
Arrays类
常用方法1.0
//1.toString返回数组的字符串形式s
int[] arr ={6,4,7};
String string = Arrays.toString(arr);
System.out.println(string);//[6, 4, 7]
//2.sort排序
Integer arrr[] = {1,-7,6,4,7,0,99};
//数组是引用类型,所以通过sort排序后,会直接影响到实参 arrr
Arrays.sort(arrr);//默认的从小到大的排序
System.out.println("排序后,可得:");
//此时可得到从小到大的排序结果
// System.out.println(Arrays.toString(arrr));//[-7, 0, 1, 4, 6, 7, 99]
//那如果想实现从大到小的输出呢?
//sort是可以重载的,也可以通过传入一个接口Comparator也就是比较器,来实现定制排序
//调用定制排序时,传入了两个参数,1.需要排序的数组2.实现了Comparator接口的匿名内部类,要求实现了compare方法
//定制排序
/**
* 剖析源码可知
* 1.Arrays.sort(arrr, new Comparator<Integer>()
* 2.最终到TimSort类的 private static <T> void binarySort(T[] a, int lo, int hi, int start,
* Comparator<? super T> c) {
* 3.执行到binarySort方法中的这部分,会根据动态绑定机制,到了c.compare()时,
* 执行我们传入的匿名内部类的compare方法
* while (left < right) {
* int mid = (left + right) >>> 1;
* if (c.compare(pivot, a[mid]) < 0)
* right = mid;
* else
* left = mid + 1;
* }
* 4.然后回到new Comparator<Integer>() {
*
* @Override
* public int compare(Integer o1, Integer o2) {
* //然后到这儿看你此时写的是哪个-哪个,写法会影响到回传回if的参数,最终决定走if-else中哪个逻辑
* // return o1-o2;
* return o2-o1;
* }
* }
* 5.public int compare(Integer o1, Integer o2) {返回的值>0 or <0
* 会影响整个排序结果 ,这就充分体现了接口编程+动态绑定++匿名内部类的综合使用
*/
Arrays.sort(arrr, new Comparator<Integer>() {//这里有没有想起来之前讲的匿名内部类呢hhh
@Override
public int compare(Integer o1, Integer o2) {
// return o1-o2;//此时底下输出的是按照从小到大的结果[-7, 0, 1, 4, 6, 7, 99]
return o2-o1;//[99, 7, 6, 4, 1, 0, -7]
}
});
System.out.println(Arrays.toString(arrr));
定制冒泡排序接口来sort
public static void main(String[] args) {
int[] arr = {6, 4, 7,1,-1,0};
// bubbleSort(arr);//正常的冒泡排序
bubble2(arr, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//重写
int i1 = (Integer)o1;//拆箱
int i2 = (Integer)o2;
//此时是按照从小到大排.输出-1 0 1 4 6 7
return i1-i2;//这里的谁-谁,决定c.compare(arr[j],arr[j+1])
//返回的值的正负,进而决定是否进入内部swap,如果大于0,则swap,
//进而决定了数组最后排序的呈现顺序是从小到大的
//接下来是想按照从大到小排输出的写法
// return i2-i1;//7 6 4 1 0 -1
}
});
for(int i :arr){
System.out.print(i+" ");
}
}
//使用冒泡完成排序
public static void bubbleSort(int[] arr){
if(arr==null || arr.length<0){
return;
}
for(int e = arr.length-1;e>0;e--){
for(int j=0;j<e;j++){
if(arr[j]>arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
//结合冒泡+定制
public static void bubble2(int[] arr,Comparator c){
if(arr==null || arr.length<0){
return;
}
for(int e = arr.length-1;e>0;e--){
for(int j=0;j<e;j++){
//数组排序由c.compare(arr[j],arr[j+1])返回的值决定
if(c.compare(arr[j],arr[j+1])>0){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
常用方法2.0
Integer[] arr = {1,2,5,8,6647};
//binarySearch 通过二分搜索法进行查找,要求必须排好
/**
*1.使用binarySearch 二叉查找
*2.要求该数组是有序的,如果该数组是无序的,不能使用binarySearch
*3.如果数组中不存在要查找的数,则返回-(其应该插入的位置索引+1)
* return -(low + 1); // key not found.
*
*/
int index = Arrays.binarySearch(arr,1);
int index2 = Arrays.binarySearch(arr,8);
int index3 = Arrays.binarySearch(arr,10);
System.out.println(index);//0
System.out.println(index2);//3
System.out.println(index3);//-5 -(10本应该插在4索引处,再+1) = -5
//4.copyOf 数组元素的复制
//从arr中拷贝arr.length长度的元素到newArr
//如果拷贝的长度>arr.length 就在新数组的后面,增加null
//拷贝0个,输出[] 拷贝-1个 抛出异常
//该方法的底层使用的是 System.arraycopy();
Integer[] newArr = Arrays.copyOf(arr, arr.length);
System.out.println("拷贝完成后============");
System.out.println(Arrays.toString(newArr));//[1, 2, 5, 8, 6647]
Integer[] newArr2 = Arrays.copyOf(arr, arr.length+1);
System.out.println(Arrays.toString(newArr2));//[1, 2, 5, 8, 6647, null]
//5.fill 数组元素的扩充
Integer[] num = new Integer[]{9, 3, 2};
//使用99 去填充num数组,可以理解成是替换原来的元素
Arrays.fill(num,99);
System.out.println("num数组填充后================");
System.out.println(Arrays.toString(num));//[99, 99, 99]
//6.equals比较两个数组元素的内容是否完全一致
//如果一样就返回true
Integer[] arr2 = {1,2,5,8,6647};
boolean equals = Arrays.equals(arr,arr2);
System.out.println("equals==========="+equals);
//7.asList将一组值,转换成List集合
//返回的asList编译类型 List(接口)
//asList运行类型java.util.Arrays$ArrayList 是Arrays类的静态内部类
// private static class ArrayList<E> extends AbstractList<E>
// implements RandomAccess, java.io.Serializable{...}
List<Integer> asList = Arrays.asList(2,3,4,5,6,1);
System.out.println("asList="+asList);//asList=[2, 3, 4, 5, 6, 1]
System.out.println("asList的运行类型"+asList.getClass());//java.util.Arrays$ArrayList
实践练习
//给定的数据对象如下
Book[] books = new Book[4];
books[0] = new Book("红楼梦",100);
books[1] = new Book("新金瓶梅",90);
books[2] = new Book("青年文摘2020",5);
books[3] = new Book("Java从入门到放弃",300);
//完整代码实现
//Book类
class Book{
private String bookName;
private double price;
public Book(String bookName, double price) {
this.bookName = bookName;
this.price = price;
}
public Book() {
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"bookName='" + bookName + '\'' +
", price=" + price +
'}';
}
}
//main方法
public class Journey {
public static void main(String[] args) {
Book[] books = new Book[4];
books[0] = new Book("红楼梦",100);
books[1] = new Book("新金瓶梅",90);
books[2] = new Book("青年文摘2020",5);
books[3] = new Book("Java从入门到放弃",300);
//1.实现按照价格从大到小排序
Arrays.sort(books, new Comparator() {
//这里是对Book数组排序,因此o1 和 o2就是Book对象
@Override
public int compare(Object o1, Object o2) {
//先转为Book类型
Book book1 = (Book) o1;
Book book2 = (Book) o2;
//这里之所以用double型的difference是因为compare要求了返回的是int类型,
//Arrays的sort方法在底层调用compare方法,其要求返回int,回顾之前的,深挖Arrays.sort源码,我们
//发现,其进入到了TimSort类的binarySort方法,在binarySort方法内部,会根据动态绑定机制执行c.compare
//其要求我们传入的是整数,所以如果直接将book2.getPrice()-book1.getPrice()传入就通不过了,因为类型不匹配
/**
* while (left < right) {
* int mid = (left + right) >>> 1;
* if (c.compare(pivot, a[mid]) < 0)
* right = mid;
* else
* left = mid + 1;
* }
*/
double difference = book2.getPrice()-book1.getPrice();//用一个double类型的引用来接收两数之差
//以下这里进行了转换,根据差值来返回不同的整数,以满足既能符合重写compare的要求,
//又不降低比较的要求(不改变用double类型来接收差值)
//如果发现返回结果和预期相反,就修改调换下返回的1和-1
if(difference>0){
return 1;
}else if (difference < 0){
return -1;
}else {
return 0;
}
}
});
System.out.println(Arrays.toString(books));
/**
* [Book{bookName='Java从入门到放弃', price=300.0}, Book{bookName='红楼梦', price=100.0},
* Book{bookName='新金瓶梅', price=90.0}, Book{bookName='青年文摘2020', price=5.0}]
*/
//2.实现价格从小到大排序
Arrays.sort(books, new Comparator() {
//这里是对Book数组排序,因此o1 和 o2就是Book对象
@Override
public int compare(Object o1, Object o2) {
//先转为Book类型
Book book1 = (Book) o1;
Book book2 = (Book) o2;
double difference = book2.getPrice()-book1.getPrice();//用一个double类型的引用来接收两数之差
//以下这里进行了转换,根据差值来返回不同的整数,以满足既能符合重写compare的要求,又不降低比较的要求(不改变用double类型来接收差值)
//如果发现返回结果和预期相反,就修改调换下返回的1和-1
if(difference>0){
//这里写-2,-3都行,因为深层次的源码,进入while循环,if (c.compare(pivot, a[mid]) < 0)这儿判断,只要求知道是大于0还是小于0
return -1;
}else if (difference < 0){
return 1;
}else {
return 0;
}
}
});
System.out.println(Arrays.toString(books));
/**
* [Book{bookName='青年文摘2020', price=5.0}, Book{bookName='新金瓶梅', price=90.0},
* Book{bookName='红楼梦', price=100.0}, Book{bookName='Java从入门到放弃', price=300.0}]
*/
//按照书名的长度从大到小排序
Arrays.sort(books, new Comparator() {
//这里是对Book数组排序,因此o1 和 o2就是Book对象
@Override
public int compare(Object o1, Object o2) {
//先转为Book类型
Book book1 = (Book) o1;
Book book2 = (Book) o2;
//要求按照书名的长度来进行排序,此时的返回结果就是整数
return book2.getBookName().length()-book1.getBookName().length();
}
});
System.out.println(Arrays.toString(books));
/**
* [Book{bookName='Java从入门到放弃', price=300.0}, Book{bookName='青年文摘2020', price=5.0},
* Book{bookName='新金瓶梅', price=90.0}, Book{bookName='红楼梦', price=100.0}]
*/
}
}
实践练习2.0
/**
假设你有一个包含 Person 对象的数组,每个 Person 对象有三个属性:name(字符串),age(整数),和 height(浮点数)。你需要实现一个自定义排序功能,要求能够根据不同的排序条件对 Person 对象数组进行排序。
需求:
实现一个 Person 类,包含 name、age、height 三个属性,并提供合适的构造函数和 toString 方法。
实现一个 bubbleSort 方法,接收一个 Person[] 数组和一个 Comparator<Person> 接口,用于按照自定义排序规则对数组进行排序。
提供以下几种排序条件:
按照 age 从小到大排序。
按照 height 从大到小排序。
按照 name 的字母顺序排序(不区分大小写)。
在 main 方法中:
创建几个 Person 对象并放入数组。
分别调用 bubbleSort 方法,实现上述三种排序,打印排序后的结果。
*/
import java.util.Arrays;
import java.util.Comparator;
public class Journey {
public static void main(String[] args) {
Person[] person = new Person[4];
person[0] = new Person("Alice", 23, 165.5);
person[1] = new Person("Bob", 30, 175.0);
person[2] = new Person("Charlie", 28, 185.0);
person[3] = new Person("Ali", 18, 170.0);
//1.实现按照age从小到大排序
BubbleSortPlus(person, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
System.out.println(Arrays.toString(person));
/**
* [Person{name='Ali', age=18, height=170.0}, Person{name='Alice', age=23, height=165.5},
* Person{name='Charlie', age=28, height=185.0}, Person{name='Bob', age=30, height=175.0}]
*/
//2.实现按照height从大到小排序
BubbleSortPlus(person, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
double heightDifference = o1.getHeight() - o2.getHeight();
if(heightDifference>0){
return -10;
}else if (heightDifference<0){
return 10;
}else {
return -2;//相等时交换与否没啥意义
}
}
});
System.out.println(Arrays.toString(person));
/**
*[Person{name='Charlie', age=28, height=185.0}, Person{name='Bob', age=30, height=175.0},
* Person{name='Ali', age=18, height=170.0}, Person{name='Alice', age=23, height=165.5}]
*/
//3.按照name中的字母顺序排序
BubbleSortPlus(person, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
//思路1.逐个比较,取短串来做循环,如果不等,就返回此时的字符差值
/* // 逐字符比较,使用compareToIgnoreCase来忽略大小写差异
int length1 = o1.getName().length();
int length2 = o2.getName().length();
int minLength = Math.min(length1, length2);
for (int i = 0; i < minLength; i++) {
char char1 = o1.getName().charAt(i);
char char2 = o2.getName().charAt(i);
if (char1 != char2) {//=0的话,直接一边玩去
return char1 - char2;//>0,说明要交换才符合题意
//<0,说明符合题意,之后在compare那儿不会调换顺序
}
}
// 当一个字符串是另一个的前缀时,较短的字符串应排在前面 ABC ABCD
//比完ABC和ABCD的前三个字母,此时按理来说ABC应该排在前面,所以return负数,在compare那儿不交换
return length1 - length2;*/
//思路2.推荐使用,谁让你个憨憨忘掉了String的这个方法
return o1.getName().compareToIgnoreCase(o2.getName());
}
});
System.out.println(Arrays.toString(person));
/**
* [Person{name='Ali', age=18, height=170.0}, Person{name='Alice', age=23, height=165.5},
* Person{name='Bob', age=30, height=175.0}, Person{name='Charlie', age=28, height=185.0}]
*/
}
public static void BubbleSortPlus(Person[] person, Comparator<Person> comparator){
for(int e= person.length-1;e>0;e--){
for(int i=0;i<e;i++){
if(comparator.compare(person[i],person[i+1])>0){
Person temp = null;
temp = person[i];
person[i] = person[i+1];
person[i+1] = temp;
}
}
}
}
}
class Person {
private String name;
private int age;
private double height;
public Person(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
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 double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
}
大数处理方案
//当我们编程中,需要处理很大很大的整数,long不够用
//可以使用BigInteger的类来搞定
// long l = 238989329382930232099320;//报异常Integer number too large
BigInteger bigInteger = new BigInteger("238989329382930232099320");
BigInteger bigInteger2 = new BigInteger("10");
System.out.println(bigInteger);//238989329382930232099320
//1.在对BigInteger进行加减乘除的时候,需要使用相对应的方法,不能直接+-*/
// 可以创建一个要操作的 BigInteger 然后进行相应的操作
BigInteger addres = bigInteger.add(bigInteger2);
System.out.println(addres);//238989329382930232099330
BigInteger subres = bigInteger.subtract(bigInteger2);
System.out.println(subres);//238989329382930232099310
BigInteger mulres = bigInteger.multiply(bigInteger2);
System.out.println(mulres);//2389893293829302320993200
BigInteger divres = bigInteger.divide(bigInteger2);
System.out.println(divres);//23898932938293023209932
//当我们需要保存一个精度很高的数时,double不够用,会发生精度缩减
//此时可以使用BigDecimal
double d = 199.111568999999999999999524;
System.out.println(d);//199.111569
BigDecimal bigDecimal = new BigDecimal("199.111568999999999999999524");
// BigDecimal bigDecimal = new BigDecimal("199.11156");
BigDecimal bigDecimal2 = new BigDecimal("0.1");
System.out.println(bigDecimal);//199.111568999999999999999524
//2.对BigDecimal进行加减乘除的时候,需要使用相对应的方法,不能直接+-*/
// 可以创建一个要操作的 BigDecimal 然后进行相应的操作
BigDecimal Baddres = bigDecimal.add(bigDecimal2);
System.out.println(Baddres);//199.211568999999999999999524
BigDecimal Bsubres = bigDecimal.subtract(bigDecimal2);
System.out.println(Bsubres);//199.011568999999999999999524
BigDecimal Bmulres = bigDecimal.multiply(bigDecimal2);
System.out.println(Bmulres);//19.9111568999999999999999524
BigDecimal Bdivres = bigDecimal.divide(bigDecimal2);
//相除时,有时可能会抛出异常,因为其可能是除不尽的,其保留的小数点精度极高的,
// 如果除数此时是0.3,相除是个无限循环小数,会抛出异常如下
//ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
System.out.println(Bdivres);//1991.11568999999999999999524
//如何解决相除时抛异常的情况呢?
//在调用divide 方法时,指定精度即可 BigDecimal.ROUND_CEILING
//如果有无限循环小数,其就会发挥作用,只保留到 分子 的精度
// 即199.111568999999999999999524 有小数点后有几位,就保留到几位。
//if 199.111568999999999999999524变成了199.11156 ,则输出的结果也会只保留小数点后5位
// 此时输出了 663.70520
BigDecimal bigDecimal3 = new BigDecimal("0.3");//新建一个不处理的话,会抛出异常的除数对象
System.out.println(bigDecimal.divide(bigDecimal3,BigDecimal.ROUND_CEILING));//663.705229999999999999998414
应用场景
- BigInteger适合保存比较大的整型
- BigDecimal适合保存精度更高的浮点型
二者底层都是将大数当作字符串,之后再转成相应的对象