常用类(四)Math类和Arrays类

一、Math类 

  Math类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数

我们查看math类的常用方法:

我们查看他的源码如下所示:

我们查看他的类图:

他的这些方法基本都是静态的:

 我们的代码设置如下所示:

package com.ypl.Math_;

public class MathMethod_ {
    public static void main(String[] args) {
        //Math常用的方法(静态方法)
        //1.abs  绝对值
        int abs = Math.abs(-9);
        System.out.println(abs);//9
        //2.pow 求幂
        double pow = Math.pow(2, 4); //2的4次方
        System.out.println(pow); //16
        //3.ceil  向上取整,返回>=该参数的最小整数(转成double)
        double ceil = Math.ceil(-3.0001);
        System.out.println(ceil);//-3
        //4.floor 向下取整,返回<=该参数的最大整数(转成double)
        double floor = Math.floor(-4.999);
        System.out.println(floor);//-5.0
        //5.round  四舍五入 Math.floor(该参数+0.5)
        long round = Math.round(-5.001);
        System.out.println(round);
        //6.sqrt 求开方
        double sqrt = Math.sqrt(9.0);
        System.out.println(sqrt); //3.0
        //7.random 求随机数
        //random 返回的是0<=x<1之间的一个随机小数。
        //思考:请写出获取a-b之间的一个随机整数,a,b均为整数,比如a=2,b=7.
        // 即返回一个数 x ,   2<=x<=7 .

        //Math.random()*(b-a)返回的就是0<= X <= b-a

        //(1)(int)(a)<=x<=(int)(a+ Math.random()*(b-a+1))
        //(2)使用具体的数进行解释如下:
        //a= 2  b=7
        //(int)(a+Math.random( )*(b-a  +1))=(int)(2+Math.random( )*(6)
        //Math.random( )*6 返回的是 0<=x<6  小数
        //2+Math.random( )*6 返回的就是  2<=x<8
        //(int)2+Math.random( )*6  =   2<=x<=7
        //(3)公式就是 (int)(a+ Math.random()*(b-a+1))
        //如果写成(int)(b)即为一个固定的值,而(int)(a + b-a)可以进行如上操作
        for (int i = 0; i< 3; i++) {
            System.out.println((int)(2+Math.random()*(7-2+1 )));
        }
       //获取一个a-b之间的一个随机整数
        //int num=(int)(Math.random()*(b-a +1)+a);

        //max,min返回最大值和最小值
        System.out.println("max="+Math.max(55,99));//99
        System.out.println("min="+Math.min(66,88));//66

    }
}

我们运行之后如下所示:

 我们了解到规律如下所示:
获取一个a-b之间的一个随机整数
int num=(int)(Math.random()*(b-a +1)+a);

二、Arrays类

Arrays里面包含了一系列静态方法,用于管理或操作数组(比如排序和搜索)

(1)toString 返回数组的字符串形式

我们按以前的方式如下所示:

package com.ypl.Arrays_;

public class ArrayMethod01 {
    public static void main(String[] args) {
        Integer[]  integers={1,20,90};
        //遍历数组
        for (int i=0;i<integers.length;i++){
            System.out.println(integers);
        }
    }
}

我们运行之后如下所示:

 

我们 采用toString方法如下所示:

package com.ypl.Arrays_;

import java.util.Arrays;

public class ArrayMethod01 {
    public static void main(String[] args) {
        Integer[]  integers={1,20,90};
        //遍历数组
        //直接使用Arrays.toString方法,显示数组。
        System.out.println(Arrays.toString(integers));
    }
}

我们运行之后如下所示:

 

我们查看toString的源码如下所示:

public static String toString(Object[] a) {
        if (a == null)
            return "null";

        int iMax = a.length - 1;
        if (iMax == -1)
            return "[]";

        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; ; i++) {
            b.append(String.valueOf(a[i]));
            if (i == iMax)
                return b.append(']').toString();
            b.append(", ");
        }
    }

 (2)sort 排序(自然排序和定制排序) Integer  arr[ ] ={1,-1,7,0,89};

我们可以通过这个方法Comparator这个比较器,可以指定排序的规则是什么,可以选择从大到小,也可以选择从小到大。可以根据自己的想法去设计。 

我们设计的代码如下所示:

package com.ypl.Arrays_;

import java.util.Arrays;
import java.util.Comparator;

public class ArrayMethod01 {
    public static void main(String[] args) {
        //演示sort方法的使用
        Integer arr[]={1,-1,7,0,89};
        //进行排序
        //1.可以直接使用冒泡排序,也可以直接使用Arrays提供的sort方法排序
        //2.因为数组是引用类型,所以通过sort排序后,会直接影响到实参 arr.
        //3.sort重载的,也可以通过传入一个接口 Comparator 实现定制排序
        //4.Arrays.sort(arr) 默认排序方法。
        //默认排序
        Arrays.sort(arr);
        System.out.println("=====排序后=====");
        System.out.println(Arrays.toString(arr));
        //5.调用定制排序时,传入两个参数(1)排序的数组 arr
         //(2)实现了Comparator接口的匿名内部类,要求实现 compare方法
        //6.这里体现了接口编程的方式
        //源码分析:
        //(1) Arrays.sort(arr, new Comparator() 
        //(2)最终到TimeSort的
       // 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() {
        //           @Override
        //           public int compare(Object o1, Object o2) {
        //               Integer i1 = (Integer) o1;
        //               Integer i2 = (Integer) o2;
        //
        //               return i2-i1;
        //           }
        //       });
        //(5) public int compare(Object o1, Object o2)方法返回的值>0的还是<0的会影响整个排序的结果
        //这就充分体现了接口编程+动态绑定+匿名内部类的综合使用
        //将来的底层框架和源码的使用方式,会非常常见。
        //定制排序
        Arrays.sort(arr, new Comparator() {
           @Override
           public int compare(Object o1, Object o2) {
               Integer i1 = (Integer) o1;
               Integer i2 = (Integer) o2;

               return i2-i1;
           }
       });
        System.out.println("=====排序后=====");
        System.out.println(Arrays.toString(arr));


    }
}

我们在运行的时候,我们会先调用sort方法,这个sort方法底层会调用Comparator接口。

我们运行之后如下所示:

我们通过debug来看待如何进行的自己定义的排序:

我们在如下地方打断点:

 我们追进去如下所示:

 我们传进去一个匿名类,所以不为null。

 

我们发现底层其实是二叉树排序:

我们继续进去如下所示:

 在binarySort方法底层,会通过实现的匿名内部类的compare方法来决定排序的顺序

在排序的底层,它调用了传入的接口实现的compare方法。

我们通过模拟排序来加深对排序的认识:

我们设计的代码如下所示:

package com.ypl.Arrays_;

import java.util.Arrays;
import java.util.Comparator;

public class ArraysSourtCustom {
    public static void main(String[] args) {
        int [] arr={1,-1,8,0,20};
        bubble01(arr);
        System.out.println("默认排序为:"+Arrays.toString(arr));
        bubble02(arr, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                int i1=(Integer) o1;
                int i2=(Integer)o2;
                return i2-i1;  //return  i2-i1;
            }
        });
        System.out.println("===定制排序后的情况===");
        System.out.println(Arrays.toString(arr));
    }

    //使用冒泡完成排序
    public  static void  bubble01(int [] arr){
        int temp=0;
        for (int i=0;i<arr.length-1;i++){
            for (int j=0;j< arr.length-1-i;j++){
                //从小到大
                if(arr[j]>arr[j+1]){
                    temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
        }
    }
    //结合冒泡+定制
    public static  void  bubble02(int [] arr, Comparator c){
        int temp=0;
        for (int i=0;i<arr.length-1;i++){
            for (int j=0;j< arr.length-1-i;j++){
                //数组排序由c.compare(arr[j],arr[j+1])返回的值决定
                if(c.compare(arr[j],arr[j+1])>0) {
                    temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
        }

    }

}

我们运行之后如下所示:

 我们通过debug来进行更加清晰的认识:

我们继续进行追加进去如下所示:
 我们继续进行下一步,如下所示:

 其中c.compare就是我们传进去的匿名对象的Comparator,里面有动态绑定,我们进去step into,如下所示:会将arr[j]和arr[j+1]这两个元素传递给我们传入的匿名的类。

 

 (3)  binarySearch 通过二分搜索法进行查找,要求必须排好序       

   int  index =Arrays.binarySearch(arr,3);

我们设计代码如下所示:

package com.ypl.Arrays_;

import java.util.Arrays;

public class ArrayMethod02 {
    public static void main(String[] args) {
        // binarySearch 通过二分搜索法进行查找,要求必须排好序
        Integer[]  arr={1,2,90,123,567};
        //1.使用binarySearch 二叉查找
        //2.要求该数组是有序的,如果该数组是无序的,不能使用 binarySearch。
        int index = Arrays.binarySearch(arr, 1);
        System.out.println("index="+index);
        int i = Arrays.binarySearch(arr, 123);
        System.out.println("i="+i);
        //3.如果数组中不存在该元素,就返回-1.
        int i3 = Arrays.binarySearch(arr, -127);
        System.out.println("i3="+i3);
        int i1 = Arrays.binarySearch(arr, 556);
        System.out.println("i1="+i1);
        int i2 = Arrays.binarySearch(arr, 92);
        System.out.println("i2="+i2);


    }
}

我们运行之后如下所示:

我们发现我们搜索不存在的数组的时候,我们返回的是-5,不是-1.我们来查看源码:

我们根据源码我们了解到,low为值应该存放的地址,我们所求的556,如果存在的话应该位于第4个,即4为源码的low值,---(4+1),为-5. 
我们设计的代码如下所示:

(4)copyOf 数组元素的复制: 

package com.ypl.Arrays_;

import java.util.Arrays;

public class ArrayMethod03 {
    public static void main(String[] args) {
        //copyOf  数组元素的复制
        //1.从arr数组中,拷贝arr.length个元素到 newArr数组中
        Integer [] arr={1,2,90,123,567};
        Integer[] newArr = Arrays.copyOf(arr, arr.length);
        System.out.println("==拷贝执行哦完毕后===");
        System.out.println(Arrays.toString(newArr));
        //2.如果拷贝的长度>arr.length就在新数组的后面增加null。
        //3.如果拷贝的长度<0就抛出异常NegativeArraySizeException
        //4.该方法的底层使用的是System.arraycopy( )
        Integer[] integers1 = Arrays.copyOf(arr, arr.length + 1);
        System.out.println(Arrays.toString(integers1));
        Integer[] integers = Arrays.copyOf(arr, 3);
        System.out.println(Arrays.toString(integers));
     
    }
}

运行之后如下所示:

我们查看copy的底层源码:

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

(5) fill数组元素的填充

Integer [] num=new Integer [ ]{9,3,2};

Arrays.fill(num,99)

我们设计的代码如下所示:

package com.ypl.Arrays_;

import java.sql.Array;
import java.util.Arrays;

public class ArrayMethod04 {
    public static void main(String[] args) {
        //fill 数组元素的填充
      Integer[] num= new Integer[]{9,3,2};
      //1.使用99去填充num数组,可以理解成是替换原来的元素
        Arrays.fill(num,99);
        System.out.println("==num数组填充后==");
        System.out.println(Arrays.toString(num));
        
    }
}

我们运行之后如下所示:

 (6)equals  比较两个数组元素内容是否完全一致

boolean equals=Arrays.equals(arr,arr2);

我们设计的代码如下所示:

package com.ypl.Arrays_;

import java.util.Arrays;

public class ArrayMethod05 {
    public static void main(String[] args) {
        //equals 比较两个数组元素内容是否完全一致
        Integer [] arr ={1,2,90,123,567};
        Integer [] arr2={1,2,90,123,567};
        Integer[] num= new Integer[]{9,3,2};
        //1.如果arr 和 arr2 数组的元素一样,则返回true
        boolean equals = Arrays.equals(arr, arr2);
        //2.如果不是完全一样,就返回false.
        boolean equals1 = Arrays.equals(arr, num);
        System.out.println("equals="+equals);
        System.out.println("equals1="+equals1);
    }
}

我们运行之后如下所示:

(7)aList将一组值,转换成list

Liist<Integer> aList =Arrays.aList(2,3,4,5,6,1);

System.out.println("asList="+aList);

我们设计的代码如下所示:

package com.ypl.Arrays_;

import java.util.Arrays;
import java.util.List;

public class ArrayMethod06 {
    public static void main(String[] args) {
        //1.asList方法,会将(2,3,4,5,6,1)数据转成一个List集合
        //2.返回的asList编译类型 List(接口)
        //3.asList 运行类型  java.util.Arrays$ArrayList,是Arrays类的静态内部类
        
        List<Integer> asList = Arrays.asList(2, 3, 4, 5, 6, 1);
        System.out.println("asList="+asList);
        System.out.println("asList的运行类型"+asList.getClass());
    }
}

我们运行之后如下所示:

我们查看Arrays的类图如下所示:Arrays的内部类如下:

 我们查看他的源码如下所示:

 private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
    
    

(八)课堂练习:

案例:自定义Book类,里面包含name和price,按price排序(从大到小)。要求使用两种方式排序,对对象的某个属性排序,有一个Book[ ] books=5本书对象。

使用前面学习过的传递实现Comparator接口匿名内部类,也称为定制排序。

可以按照价格price(1)从大到小  (2)从小到大   (3)按照书名长度从大到小

我们设计的代码如下:

package com.ypl.Arrays_;

import java.util.Arrays;
import java.util.Comparator;

public class ArrayExercise {
    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("青年文摘20年",5);
        books[3]=new Book("java从入门到放弃~",300);

        //(1)price从大到小
        Arrays.sort(books, new Comparator() {
            //这里是对Book数组排序,因此,o1和o2就是Book对象
            @Override
            public int compare(Object o1, Object o2) {
                Book book1 = (Book) o1;
                Book book2 = (Book) o1;
                return book2.getName().length() - book1.getName().length();
            }
        });
        System.out.println(Arrays.toString(books));
    }
}

class Book {
   private  String name;
   private  double price;

    public Book(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}




我们运行之后如下所示:

猜你喜欢

转载自blog.csdn.net/weixin_59448049/article/details/128999879