01.07_学习Java的day17(详解)

JDK:Java程序的开发工具包
JRE:Java程序运行环境
JVM:Java虚拟机

JDK = JRE + 开发工具
JRE = JVM + 核心类库libs

一、和数学运算相关的类

1、java.lang.Math类

Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
(1)double Math.PI
(2)double Math.sqrt(double x)
(3)double Math.random():返回[0,1)的随机值
(4)double/int/… abs(x):求x的绝对值
(5)double ceil(double a) :向上取整
(6)double floor(double a) :向下取整
(7)long round(double a) :四舍五入
(8)double pow(double a, double b) :求a的b次方
(9)double max(double a, double b):求a和b的最大值
(10)double min(double a, double b):求a和b的最小值

2、java.math包

BigInteger和BigDecimal,它们都是引用数据类型,用对象来表示数值。

(1)BigInteger:表示大整数

当long类型的变量都无法表示的数据,就可以用BigInteger

面试题:int,Integer,BigInteger什么区别?
int:基本数据类型
Integer:是int的包装类,支持与int自动装箱与拆箱
BigInteger:是引用数据,用于表示特别大的整数

(2)BigDecimal:表示任意精度的小数

之前float和double是浮点型小数。

面试题:double,Double,BigDecimal
double:基本数据类型,浮点型,不精确的
Double:是double的包装类,可以与double类型自动装箱与拆箱
BigDecimal:是引用数据类型,是可以表示任意精度的小数

3、java.util.Random类

用于产生随机值
boolean nextBoolean();
double nextDouble();
int nextInt();
long nextLong();

int nextInt(int bound):产生[0,bound)范围的int值

public class Math {
    @Test
    public void test05(){
        Random random = new Random();
        System.out.println(random.nextBoolean());
        System.out.println(random.nextDouble());
        System.out.println(random.nextInt());

        //产生[0,10)范围的整数
        System.out.println((int)(Math.random()*10));
        System.out.println(random.nextInt(10));
    }

    @Test
    public void  test04(){
        double largeNum = 1.23456789012345678901234567890;
        System.out.println(largeNum);//1.2345678901234567 近似处理
        BigDecimal big = new BigDecimal("1.23456789012345678901234567890");
        System.out.println(big);

        BigDecimal big1 = new BigDecimal("112.3456789012345678901234567890");
        BigDecimal big2 = new BigDecimal("9.23456789012345678901234567890");
//        System.out.println("和:" + (big1 + big2));//不支持直接使用+运算符

        //对象想要完成xx功能,就是调方法
        System.out.println("和:" + big1.add(big2));
        System.out.println("减:" + big1.subtract(big2));
        System.out.println("乘:" + big1.multiply(big2));
//        System.out.println("除:" + big1.divide(big2));//除不尽
        //这里报ArithmeticException

        System.out.println("除:" + big1.divide(big2,30,BigDecimal.ROUND_UP));
        System.out.println("余:" + big1.remainder(big2));
    }
    @Test
    public void  test03(){
//        long largeNum = 123456789012345678901234567890L;
        BigInteger big1 = new BigInteger("1123456789012345678901234567890");
        BigInteger big2 = new BigInteger("923456789012345678901234567890");
//        System.out.println("和:" + (big1 + big2));//不支持直接使用+运算符

        //对象想要完成xx功能,就是调方法
        System.out.println("和:" + big1.add(big2));
        System.out.println("减:" + big1.subtract(big2));
        System.out.println("乘:" + big1.multiply(big2));
        System.out.println("除:" + big1.divide(big2));//整数/整数结果值保留整数部分
        System.out.println("余:" + big1.remainder(big2));
    }

    @Test
    public void  test01(){
        System.out.println(Math.ceil(2.3));//3.0
        System.out.println(Math.floor(2.3));//2.0
        System.out.println(Math.round(2.3));//2
    }

    @Test
    public void  test02(){
        System.out.println(Math.ceil(2.7));//3.0
        System.out.println(Math.floor(2.7));//2.0
        System.out.println(Math.round(2.7));//3
    }
}

二 、日期时间相关的API

(一)JDK1.8之前:

1、java.util.Date类:类 Date 表示特定的瞬间,精确到毫秒。

要区别于java.sql.Date。
java.sql.Date是java.util.Date的子类,用于和数据库中的日期时间映射用的。
(1)Date():获取系统时间
(2)Date(毫秒):根据毫秒值,得到对应的日期时间
(3)long getTime():距离1970年1月1日凌晨的经历的毫秒值
为什么选择1970年1月1日时间作为基准?
因为操作系统的时间基准是以Unix操作系统一开始选择的时间基准为标准的。
Unix操作系统一开始选择1970年1月1日这个为基准点。
当时的操作系统都是32位的,long类型的表示不了太长的值。

2、java.util.Calendar:日历类型

作为Date类型的一个补充。
它有一个直接子类:GregorianCalendar

(1)获取对象:

Calendar getInstance():使用当前系统默认的时区,语言环境来返回的日历对象
Calendar getInstance(TimeZone,Locale):根据指定的时区与语言环境来获取日历对象

(2)get(常量字段):根据常量字段,获取对应的时间值

3、java.util.TimeZone:时区

static TimeZone getTimeZone(String ID)

4、java.util.Locale:语言环境

Locale.常量对象

回忆:获取对象
(1)直接new
(2)类名.常量对象:适用于枚举
(3)调用方法得到xx对象

5、java.text.DateFormat与SimpleDateFormat

y:年
M:月
d:日
H:24小时制的小时
h:12小时制的小时
m:分
s:秒
S:毫秒
E:星期
D:一年的第几天

public class Date {
    @Test
    public void test08(){
        //Date
        Date now = new Date();
        System.out.println(now);//Tue Jan 07 09:28:30 CST 2020  不符合我们中国人的日期时间表示习惯

        //可以逐项获取,太麻烦
        Calendar c = Calendar.getInstance();
        System.out.println(c);

        System.out.println("年:" + c.get(Calendar.YEAR));
        System.out.println("月:" + (c.get(Calendar.MONTH)+1));
        System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));

        //使用DateFormat,日期格式化
        //DateFormat抽象类,
        DateFormat df = DateFormat.getDateInstance();
        String s = df.format(now);
        System.out.println(s);//2020-1-7

        DateFormat df2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS E 是这一年的第D天");
        System.out.println(df2.format(now));
    }

    @Test
    public void test07(){
        String[] iDs = TimeZone.getAvailableIDs();
        for (int i = 0; i < iDs.length; i++) {
            String iD = iDs[i];
            System.out.println(iD);
        }
    }

    @Test
    public void test06(){
        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"), Locale.US);
        System.out.println(c);

        System.out.println("年:" + c.get(Calendar.YEAR));
        System.out.println("月:" + (c.get(Calendar.MONTH)+1));
        System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
        System.out.println("时:" + c.get(Calendar.HOUR_OF_DAY));
        System.out.println("分:" + c.get(Calendar.MINUTE));
    }

    @Test
    public void test05(){
//        Calendar c = new Calendar();//Calendar是抽象类,无法直接创建对象
//        Calendar c = new GregorianCalendar();//子类名太长,不直接new

        Calendar c = Calendar.getInstance();
        System.out.println(c);

        System.out.println("年:" + c.get(Calendar.YEAR));
        System.out.println("月:" + (c.get(Calendar.MONTH)+1));
        System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
    }

    @Test
    public void test04(){
        //Date(int year, int month, int date) 已过时
        Date date = new Date(2019,12,31);
        System.out.println(date);//Sat Jan 31 00:00:00 CST 3920
        /*
        int year:是相对于1900年,间隔几年
        int month:month - 0-11 的月份
         */
    }

    @Test
    public void test03(){
        Date now = new Date();
        long time = now.getTime();
        System.out.println(time);//1578360704483
    }

    @Test
    public void test02(){
        Date now = new Date(Long.MAX_VALUE);
        System.out.println(now);//Sun Aug 17 15:12:55 CST 292278994
    }

    @Test
    public void test01(){
        Date now = new Date();
        System.out.println(now);//Tue Jan 07 09:28:30 CST 2020
    }
}

(二)JDK1.8之后的日期时间API

1、为什么要引入新版的API

原来的Date和Calendar有一些问题:
(1)很多API过时
(2)可变性
开发中任意,一个日期时间对象,一旦创建好,就固定代表某个日期时间,不应该可变。
(3)偏移性:
Date中的年份是从1900开始的,而月份都是从0开始的
(4)格式化的支持:格式化只对Date有用,Calendar则不行
(5)此外,它们也不是线程安全的,不能处理闰秒等。
开始要对日期时间API进行改版。

2、Java8新增了很多包和类

  • java.time – 包含值对象的基础包
  • java.time.chrono – 提供对不同的日历系统的访问。
  • java.time.format – 格式化和解析时间和日期
  • java.time.temporal – 包括底层框架和扩展特性
  • java.time.zone – 包含时区支持的类

3、java.time包中

本地日期时间类型:掌握
LocalDate:表示日期
LocalTime:表示时间
LocalDateTime:表示日期和时间

(1)now:获取系统的日期或时间
(2)of(…):指定日期或时间
(3)plusXxx/withXxx/minusXxx:加上/设置/减去日期或时间,得到新的日期时间对象,原来的日期时间对象不变。
(4)getXxx:获取指定日期和时间值
(5)boolean isLeapYear():判断是否是闰年

4、java.time包中(了解)

ZonedDateTime:获取指定时区和语言环境的日期时间对象

5、java.time包中

日期间隔:Period
时间间隔:Duration

6、java.time.format.DateTimeFormatter

(1)自定义
“yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒 E 是这一年的D天”
(2)预定义的国际标准
DateTimeFormatter.ISO_DATE_TIME;
(3)长、短、中等的风格
FormatStyle枚举类型:SHORT,LONG,MEDIUM,FULL等

public class Date2 {
    @Test
    public void test09() {
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);

        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒  SSS毫秒  E 是这一年的D天");
        System.out.println(df.format(now));//2020年01月07日 10时45分33秒  910毫秒  星期二 是这一年的7天

        DateTimeFormatter df2 = DateTimeFormatter.ISO_DATE_TIME;
        System.out.println(df2.format(now));//2020-01-07T10:45:33.91

        //FormatStyle枚举类型
        DateTimeFormatter df3 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
        System.out.println(df3.format(now));//20-1-7 上午10:45

        DateTimeFormatter df4 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
        System.out.println(df4.format(now));//2020年1月7日 上午10时45分33秒
    }
    @Test
    public void test08() {
        LocalTime now = LocalTime.now();
        LocalTime rest = LocalTime.of(12,0,0);
        Duration d = Duration.between(now,rest);
        System.out.println(d);//PT1H18M41.421S
    }

    @Test
    public void test07() {
        LocalDate today = LocalDate.now();
        LocalDate birth = LocalDate.of(2002,6,1);

        Period p = Period.between(today,birth);
        System.out.println(p);//P-17Y-7M-6D
    }

    @Test
    public void test06() {
        ZonedDateTime t = ZonedDateTime.now();
        System.out.println(t);//2020-01-07T10:36:26.914+08:00[Asia/Shanghai]

        ZonedDateTime t2 = ZonedDateTime.now(ZoneId.of("America/New_York"));
        System.out.println(t2);//2020-01-06T21:37:25.433-05:00[America/New_York]
    }

    @Test
    public void test05() {
        LocalDate today = LocalDate.now();
        System.out.println(today.isLeapYear());
    }

    @Test
    public void test04() {
        LocalDate today = LocalDate.now();
        System.out.println("年:" + today.getYear());
        System.out.println("月:" + today.getMonth());
        System.out.println("月:" + today.getMonthValue());
        System.out.println("日:" + today.getDayOfMonth());

        System.out.println("星期:" + today.getDayOfWeek());
        System.out.println("一年的第几天:" + today.getDayOfYear());
    }

    @Test
    public void test03() {
        LocalDate today = LocalDate.now();
        System.out.println(today);
        System.out.println("-------------");

        LocalDate future = today.plusDays(130);
        System.out.println(future);
        System.out.println(today);//不可变对象,修改会产生新对象
    }
    @Test
    public void test02(){
        LocalDate today = LocalDate.now();
        System.out.println(today);//2020-1-7

        LocalDate birth = LocalDate.of(2002,6,1);
        System.out.println(birth);
    }

    @Test
    public void test01(){
        Calendar c = Calendar.getInstance();//代表当前系统时间
        System.out.println("年:" + c.get(Calendar.YEAR));
        System.out.println("月:" + (c.get(Calendar.MONTH)+1));
        System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));

        System.out.println("--------------------");
        c.set(Calendar.YEAR, 2019);
        c.set(Calendar.MONTH,11);
        c.set(Calendar.DATE,2);
        System.out.println("年:" + c.get(Calendar.YEAR));
        System.out.println("月:" + (c.get(Calendar.MONTH)+1));
        System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));

    }
}

三、和系统相关的API

1、java.lang.System类

(1)System.out.println()
System.out.print()

print()和println()不是System类的API,它是out对象的API,out对象是PrintStream类型。
我们在IO流类中介绍它。

(2)long System.currentTimeMillis()
(3)public static void arraycopy(Object src,int srcPos, Object dest,int destPos, int length) 重要
作用:可以用于复制数组,数组移动元素
第一个参数:Object src:原数组
第二个参数:int srcPos:原数组的起始下标
第三个参数:Object dest:目标数组
第四个参数:int destPos:目标数组的起始下标
第五个参数:int length:一共复制或移动几个元素

当原数组与目标数组不是同一个数组,就相当于复制
当原数组与目标数组是同一个数组,就相当于移动元素
当srcPos > destPos:往左/前移动
当srcPos < destPos:往右/后移动
(4)void System.exit(…):退出JVM
根据惯例,非 0 的状态码表示异常终止。
(5)void System.gc():调用GC回收垃圾。这个方法调用了,不代表GC立刻工作,但是最终会响应。
不建议频繁的手动调用gc()。
(6)String getProperty(String key)

系统属性是:(key,value),根据key获取/设置value,
例如:os.name:表示操作系统类型

file.encoding=UTF-8
user.language=zh
file.separator=
os.name=Windows 7
sun.jnu.encoding=GBK

2、java.lang.Runtime:它的对象代表JVM的运行环境

每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。
应用程序不能创建自己的 Runtime 类实例。
Runtime是单例。(唯一的实例对象)

public class System {
    @Test
    public void test07(){
        Runtime runtime = Runtime.getRuntime();

        System.out.println("总内存:" + runtime.totalMemory());
        System.out.println("空闲内存:" + runtime.freeMemory());
        System.out.println("使用内存:" + (runtime.totalMemory() - runtime.freeMemory()));
    }

    @Test
    public void test06(){
        Properties properties = System.getProperties();
        System.out.println(properties);
        Set<Map.Entry<Object, Object>> entries = properties.entrySet();
        for (Map.Entry<Object, Object> entry : entries) {
            System.out.println(entry);
        }


//        String name = System.getProperty("os.name");
//        System.out.println(name);
    }


    @Test
    public void test05() {
        int[] arr = {1, 2, 3, 4, 5};

        //arr数组移动之前
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
        //1 2 3 4 5
        System.out.println();
        System.out.println("---------------");
        System.arraycopy(arr,1,arr,0,4);
         /*
        第一个参数:Object src:原数组                arr
        第二个参数:int srcPos:原数组的起始下标       1
        第三个参数:Object dest:目标数组              arr
        第四个参数:int destPos:目标数组的起始下标     0
        第五个参数:int length:一共复制或移动几个元素    4
        相当于从arr[0]一共移动了4个元素,arr[1]移动到arr[0]
         */
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
        //2 3 4 5 5
    }

    @Test
    public void test04() {
        int[] arr = {1, 2, 3, 4, 5};

        //arr数组移动之前
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
        //1 2 3 4 5
        System.out.println();
        System.out.println("---------------");
        System.arraycopy(arr,0,arr,2,3);
         /*
        第一个参数:Object src:原数组                arr
        第二个参数:int srcPos:原数组的起始下标       0
        第三个参数:Object dest:目标数组              arr
        第四个参数:int destPos:目标数组的起始下标     2
        第五个参数:int length:一共复制或移动几个元素    3
        相当于从arr[0]一共移动了3个元素,arr[0]移动到arr[2]
         */
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
        //1 2 1 2 3
    }

    @Test
    public void test03(){
        int[] arr = {1,2,3,4,5};
        int[] arr2 = new int[10];//10个0

        System.arraycopy(arr,0,arr2,3,3);
        /*
        第一个参数:Object src:原数组                arr
        第二个参数:int srcPos:原数组的起始下标       0
        第三个参数:Object dest:目标数组              arr2
        第四个参数:int destPos:目标数组的起始下标     3
        第五个参数:int length:一共复制或移动几个元素    3
        相当于从arr[0]一共复制3个元素到arr2中,存入arr2[3]开始的三个位置
         */

        //arr数组元素不变
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        System.out.println("-------------------------");
        for (int i = 0; i < arr2.length; i++) {
            System.out.println(arr2[i]);
        }
        //0,0,0,1,2,3,0,0,0,0
    }

    @Test
    public void test02(){
        long time = System.currentTimeMillis();
        System.out.println(time);//1578366364748 距离1970年1月1日凌晨的毫秒值
    }

    @Test
    public void test01(){
        System.out.println("输出并换行");
        System.out.print("输出不换行");
        System.out.print("\n");

        System.out.println();//输出换行符
//        System.out.print();//错误,print()没有无参
    }
}

四、数组的相关算法

(一)回忆:

1、数组的统计(掌握)

偶数个数、素数个数、xx倍数个数…

2、数组的查找(掌握)

(1)顺序查询

3、数组的最值的查找(掌握)

(1)最大/小值
(2)最大/小值的下标

4、排序

(1)冒泡排序(掌握)

public class Array {
    @Test
    public void test01(){
        int[] arr = {1,2,3,4,5};

        //反转之前
        System.out.println("反转之前:");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
        System.out.println("--------------------");

        //调用反转的方法
//        reverse1(arr);
//        reverse2(arr);
//        reverse3(arr);//失败
        arr = reverse4(arr);//重新接受新数组

        System.out.println("反转之后:");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    //形参:int[] arr
    //返回值类型:void ,因为数组是引用数据类型,对形参的反转,相当于对实参的反转
    public void reverse1(int[] arr){
        //首尾交换
        for(int i=0; i< arr.length/2; i++){  //循环次数就是交换次数
            //arr[i] 与 arr[arr.length-1-i]交换
            int temp = arr[i];
            arr[i] = arr[arr.length-1-i];
            arr[arr.length-1-i] = temp;
        }
    }

    public void reverse2(int[] arr){
        //首尾交换
        for(int left=0,right=arr.length-1; left < right; left++,right--){
//            arr[left] 与arr[right]交换
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
        }
    }

    public void reverse3(int[] arr){
        //创建一个新数组
        int[] newArr = new int[arr.length];

        //从arr逆向复制元素到newArr中
        for (int i = 0; i < newArr.length; i++) {
            newArr[i] = arr[arr.length-1-i];
        }

        //让arr指向新的newArr
        //当arr形参指向新对象/新数组,和原来的实参数组就无关了
        arr = newArr;
    }

    public int[] reverse4(int[] arr){
        //创建一个新数组
        int[] newArr = new int[arr.length];

        //从arr逆向复制元素到newArr中
        for (int i = 0; i < newArr.length; i++) {
            newArr[i] = arr[arr.length-1-i];
        }

        return newArr;
    }
}

今天再学习

(二)

1、数组的反转

2、数组的扩容

public class Array2 {
    @Test
    public void test01(){
        int[] arr= {1,2,3,4,5};

        //扩大arr数组的容量,增加一个元素
       arr = grow(arr, arr.length*2);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

    /*
    形参:int[] arr:代表原数组
            int newLength  如果没有第二个参数,那么可以自己选择是增加1个元素,还是扩大为原来的1.5倍或2倍等
    返回值类型:int[]
    数组本身的长度是不能变的,需要扩容,只增新建一个更大的数组
    如果要创建新数组,就需要返回新数组
     */
    public int[] grow(int[] arr,int newLength){
        //(1)创建新数组
        int[] newArr = new int[newLength];

        //(2)赋值元素:把原来数组的元素复制到新数组中
        for (int i = 0; i < arr.length; i++) {
            newArr[i] = arr[i];
        }

        //(3)返回新数组
        return newArr;
    }
}

3、数组的插入

public class Array3 {
    @Test
    public void test01(){
        int[] arr = {1,2,3,4,5};

        //在arr[1]插入一个元素6
//       arr= insert(arr,1,6);
       arr= insert2(arr,1,6);

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

    public int[] insert(int[] arr, int index, int value){
        //(1)先扩容
        int[] newArr = new int[arr.length+1];

        //(2)把原数组的元素复制到新数组中
        for (int i = 0; i < arr.length; i++) {
           newArr[i] = arr[i];
        }

        //(3)把value值插入到[index]位置
        //先将[index]以及后面的元素往右移动
        /*
        从newArr[index]开始移动,目标数组newArr,把newArr[index]放到newArr[index+1]位置。
        假设实际元素的个数5, index=1,移动[1][2][3][4]
        [0]~[4]
         */
        System.arraycopy(newArr,index,newArr,index+1, arr.length-index);
//        将value值赋值给newArr[index]
        newArr[index] = value;

        return newArr;
    }

    public int[] insert2(int[] arr, int index, int value){
        //(1)先扩容
        int[] newArr = new int[arr.length+1];
        //分为三段处理新数组
        /*
        [0,index]为一部分
        [index]为一部分
        [index,最后]为一部分
         */

        //(2)把原数组的arr[0,index-1]先复制到newArr中
        for (int i = 0; i < index; i++) {
            newArr[i] = arr[i];
        }

        //(3)把value值插入到newArr[index]位置
        newArr[index] = value;

        //(4)把arr[index+1,最后]复制到newArr
        for (int i = index; i<arr.length; i++){
            newArr[i+1] = arr[i];
        }

        return newArr;
    }
}

4、数组的删除

public class Array4 {
    @Test
    public void test01(){
        int[] arr = {1,2,3,4,5};

        //删除arr[1]
        delete(arr,1);

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);

        }
    }

    public void delete(int[] arr,int index){
        //(1)把[index+1]后面的元素往前移动
        /*
        假设arr.length=5,index=1,移动[2][3][4]
         */
        System.arraycopy(arr, index+1, arr, index, arr.length-index-1);

        //(2)把最后一个位置还原为默认值
        arr[arr.length-1] = 0;
    }
}

5、数组的查找

(1)顺序查找:遍历数组,挨个比较元素
(2)二分查找,折半查找(必须会手写,笔试题中出现好几次)
要求数组必须是有序的
即无序的数组不能使用二分查找

public class Array5 {
    @Test
    public void test01(){
        int[] arr = {1,2,13,24,24,50,60};
        System.out.println(binarySearch(arr,11));
        System.out.println(binarySearch(arr,60));
    }

    public int binarySearch(int[] arr, int value){
        int left = 0;
        int right = arr.length-1;
        int mid = (left + right)/2;

        while(left <= right){
            if(arr[mid]==value){
                return mid;
            }else if(arr[mid] > value){
                //往左找,修改right
                right = mid - 1;
            }else if(arr[mid] < value){
                //往右边找,修改left
                left = mid +1;
            }
            mid = (left + right)/ 2;
        }
        return -1;
    }
}

6、数组的排序

(1)冒泡排序
(2)直接选择排序

public class Array6 {
    @Test
    public void test01(){
        int[] arr = {49,38,65,97,76,13,27,49};
        selectSort(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+ " ");
        }
    }

    public void selectSort(int[] arr){
        /*
        每一轮,找出本轮未排序元素中的最小/大值,然后看它是否在它应该在的位置,如果不在,
        与它应该在的位置交换。
        经过多轮,实现最终排序
        例如:{49,38,65,97,76,13,27,49}
        第一轮:最小值13,它现在在[5]位置,但是它应该在[0],交换[5]与[0]
               {13,38,65,97,76,49,27,49}
        第二轮:找出本轮未排序元素中的最小值,13不参与,它已经在正确的位置
                最小值27,它现在在[6],但是它应该在[1],交换[6]与[1]
                {13,28,65,97,76,49,38,49}
        第三轮: 最小值38,它现在在[6],但是它应该在[2],交换[6]与[2]
                 {13,28,38,97,76,49,65,49}
         第四轮: 最小值49,它现在在[5],但是它应该在[3],交换[5]与[3]
                {13,28,38,49,76,97,65,49}
          第五轮:最小值49,它现在在[7],但是它应该在[4],交换[7]与[4]
              {13,28,38,49,49,97,65,76}
          第六轮:最小值65,它现在在[6],但是它应该在[5],交换[6]与[5]
                 {13,28,38,49,49,65,97,76}
           第七轮:最小值76,它现在在[7],但是它应该在[6],交换[7]与[6]
                 {13,28,38,49,49,65,76,97}
         */

        //轮数:n-1轮
        for (int i=1; i<arr.length; i++){
            //(1)先找出本轮未排序部分的最小值及其下标
            /*
            第一轮i=1:[0,arr.length-1],本轮第一个元素下标为[0]
            第二轮i=2:[1,arr.length-1],本轮第一个元素下标为[1]
            第三轮i=3:[2,arr.length-1],本轮第一个元素下标为[2]
            ...
            找最小值,假设第一个元素最小,用min与后面的元素一一比较
             */
            int min = arr[i-1];
            int index = i-1;

            for (int j=i; j<arr.length; j++){
                if(arr[j] < min){
                    min = arr[j];
                    index = j;
                }
            }

            //判断min是否在它应该在的位置
            //min应该在本轮第一个元素的位置
            if(index != i-1){
                //交换arr[index]与arr[i-1]
                int temp = arr[index];
                arr[index] = arr[i-1];
                arr[i-1] = temp;
            }
        }
    }
}

五、JRE的核心类库中有一个数组工具类:java.util.Arrays

1、public static int binarySearch(int[] a, int key):在a数组中查找key是否存在,如果存在返回它的下标,不存在返回负数。
如果不存在,它返回的是“-插入点-1"。插入点是假设这个数存在,它应该在哪个位置。
2、public static int[] copyOf(int[] original, int newLength):根据original数组,复制一个新数组,新数组的长度为newLength,
我们调用时,需要接受新数组
3、public static int[] copyOfRange(int[] original,int from, int to):根据original数组,复制一个新数组,
从original[from]开始复制,如果to超过original的length,那么复制到original最后一个,
如果to在original的合理下标范围内,那么[from,to)
4、public static boolean equals(int[] a,int[] a2):比较两个数组的长度,元素是否相等
5、public static void fill(int[] a, int val):使用val填充a数组
6、public static void sort(int[] a):对基本数据类型的数组实现从小到大排序

public static void sort(Object[] a):对对象数组实现从小到大排序,但是要求数组的元素类型必须实现java.lang.Comparable接口
public static void sort(T[] a, Comparator c):对对象数组实现从小到大排序,但是要求指定定制比较器器对象

7、public static String toString(int[] a):将数组a的元素,拼接为一个字符串返回

public class Arrays {
    @Test
    public void test07(){
        int[] arr = {1,2,3,4,5};
        System.out.println(Arrays.toString(arr));
    }

    @Test
    public void test06(){
        class Student implements Comparable{
            private String name;
            private int score;

            public Student(String name, int score) {
                this.name = name;
                this.score = score;
            }

            public String getName() {
                return name;
            }

            public int getScore() {
                return score;
            }

            @Override
            public int compareTo(Object o) {
                return this.score - ((Student)o).score;
            }

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

        Student[] arr = new Student[3];
        arr[0] = new Student("扎告诉你",89);
        arr[1] = new Student("贾自强",78);
        arr[2] = new Student("刘鑫",90);

//        Arrays.sort(arr);
        Arrays.sort(arr ,new Comparator(){

            @Override
            public int compare(Object o1, Object o2) {
                return ((Student)o1).score - ((Student)o2).score;
            }
        });

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i] + " ");
        }
    }

    @Test
    public void test05(){
        int[] arr = {49,38,65,97,76,13,27,49};
        Arrays.sort(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

    @Test
    public void test04() {
        int[] arr = new int[3];
        Arrays.fill(arr,1);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

    @Test
    public void test03() {
        int[] arr = {1, 4, 7, 9, 10};
//        arr = Arrays.copyOfRange(arr, 2, 10);
        arr = Arrays.copyOfRange(arr, 2, 4);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

    @Test
    public void test02() {
        int[] arr = {1, 4, 7, 9, 10};
        arr = Arrays.copyOf(arr, arr.length * 2);
//        arr = Arrays.copyOf(arr, 3);
//        arr = copyOf(arr, 10);
//        arr = copyOf(arr, 3);

        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

    public int[] copyOf(int[] arr, int newLength){
        if(newLength < 0){
            throw new IllegalArgumentException("数组的长度不能为负数");
        }
        //(1)创建一个新数组
        int[] newArr = new int[newLength];

        //(2)从arr赋值元素到newArr
//        for (int i=0; i<arr.length && i<newArr.length; i++){
//            newArr[i] = arr[i];
//        }
        int len = arr.length < newLength ? arr.length : newLength;
        System.arraycopy(arr,0,newArr,0,len);
        //(3)返回新数组
        return newArr;
    }


    @Test
    public void test01(){
        int[] arr = {1,4,7,9,10};
        int value = 8;

        int index = Arrays.binarySearch(arr, value);
        System.out.println(index);//8如果存在,应该在[3]位置,-3-1=-4

        value = 7;
        index = Arrays.binarySearch(arr, value);
        System.out.println(index);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值