关于java:JavaSE第13篇常用API冒泡排序二分查找正则

21次阅读

共计 11714 个字符,预计需要花费 30 分钟才能阅读完成。

外围概述:本篇咱们将会学习罕用的 API,其中有 Object 类、日期相干操作类、数组相干操作类 Arrays、正则表达式;同时也会学习对于数组的一些罕用算法,其余中有冒泡排序、二分查找法。

第一章:Object 类

1.1- 概述(理解)

java.lang.Object类是 Java 语言中的根类,每个类都应用 Object 作为超类。所有对象(包含数组)都实现这个类的办法。

如果一个类没有特地指定父类,那么默认则继承自 Object 类。例如:

public class MyClass /*extends Object*/ {// ...}

1.2- 本地办法(理解)

在 Object 类的源码中定义了 native 润饰的办法,native润饰的办法称为本地办法。

本地办法的特点

  • 被 native 润饰的办法,非 Java 语言编写,是由 C ++ 语言编写。
  • 本地办法在运行期间进入本地办法栈内存,本地办法栈是一块独立内存的区域。
  • 本地办法的意义是和操作系统进行交互。

如 Object 类中局部源码:

private static native void registerNatives();
static {registerNatives();
}

当程序运行的时候,Object 类会最先被加载到内存中。类进入内存后首先加载本人的动态成员,static 代码块中调用了本地办法registerNatives(),和操作系统进行交互。

查看 Object 类源码:在 IDEA 编辑器中,新建一个类,在类中一个 main 办法中 new Object(),鼠标停留在Object 类上,按住ctrl + 点击鼠标,进入 Object 类源码中。

1.3-toString 办法(了解)

意识 toString 办法

办法申明:public String toString():返回该对象的字符串示意。

Object 类 toString()办法源码:

public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

源码剖析:

  • getClass().getName()返回类的全限定名字。
  • hashCode()办法返回 int 值,能够临时了解为对象的内存地址。
  • Integer.toHexString()将 int 类型的值转成十六进制。
  • 因而调用对象的 toString()办法将看到内存的地址值。

创立 Person 类,并调用办法 toString()

public static void main(String[] args){Student stu = new Student();
    String str = stu.toString();
    System.out.println(str);    // www.penglei666.com.demo01.Student@5f2050f6
    System.out.println(stu);    // www.penglei666.com.demo01.Student@5f2050f6
}

通过程序运行,失去论断,在输入语句中打印对象,就是在调用对象的 toString()办法

重写 toString 办法

因为 toString 办法返回的后果是内存地址,而在开发中,内存地址并没有理论的利用价值,常常须要依照对象的属性失去相应的字符串表现形式,因而也须要重写它。

public class Student {  
    private String name;
    private int age;

    @Override
    public String toString() {return "Student:" + name + "," + age;}
    // 省略结构器与 Getter Setter
}

1.4-equals 办法(了解)

意识 equals 办法

办法申明:public boolean equals(Object obj):批示其余某个对象是否与此对象“相等”。

Object 类 equals()办法源码:

public boolean equals(Object obj) {return (this == obj);
}

源码剖析:

  • this 是以后对象,哪个对象调用的 equals 办法就示意哪个对象。
  • obj 表述传递的参数,参数类型 Object,能够传递任意类型对象。
  • this==obj 比拟两个对象的内存地址是否雷同

equals 办法默认比拟两个对象的内存地址是否雷同,雷同则返回 true。

重写 equals 办法

理论利用中,比拟内存地址是否雷同并没有意义,咱们能够定义对象本人的比拟形式,比拟对象中成员变量的值是否雷同。须要对办法进行重写。

需要:重写 equals()办法,比拟两个对象中姓名和年龄是否雷同,如果姓名和年龄都雷同返回 true,否则返回 false。

public class Person {
    private String name;
    private int age;
    
    public boolean equals(Object obj){
        // 判断两个对象地址弱雷同,即为同一个对象
        if(this == obj)
            return true;
        //obj 对象为空,无需比拟,返回 false
        if(obj == null)
            return  false;
        //obj 如果是 Person 类型对象,则强制转换
        if(obj instanceof Person){Person person = (Person)obj;
            // 比拟两个对象的 name 属性和 age 属性,如果相等,返回 true
            return this.name.equals(person.name) && this.age == person.age;
        }
        return false;
    }
}

第二章:日期操作类

2.1-Date 类(记忆)

构造方法

  • public Date():从运行程序的此时此刻到工夫原点经验的毫秒值, 转换成 Date 对象,调配 Date 对象并初始化此对象,以示意调配它的工夫(准确到毫秒)。
  • public Date(long date):将指定参数的毫秒值 date, 转换成 Date 对象,调配 Date 对象并初始化此对象,以示意自从规范基准工夫(称为“历元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。
public class Test01 {public static void main(String[] args) {Date date = new Date();
        System.out.println(date);    // Fri Jul 31 11:59:20 CST 2020
        Date date2 = new Date(0);
        System.out.println(date2);   // Thu Jan 01 08:00:00 CST 1970
    }
}

罕用办法

  • public long getTime() 把日期对象转换成对应的工夫毫秒值。
  • public void setTime(long time) 把办法参数给定的毫秒值设置给日期对象。
public class Test02 {public static void main(String[] args) {Date date = new Date();
        System.out.println(date.getTime());        // 1596168137169
        date.setTime(15961681371611L);
        System.out.println(date);                  // Tue Oct 22 00:22:51 CST 2475
    }
}

毫秒值(工夫戳)和日期对象相互转换

日期对象转换为毫秒值:日期对象.getTime();

毫秒值转换为日期对象:new Date(long time);

获取以后工夫的毫秒值:System.currentTimeMillis()

public class Test02 {public static void main(String[] args) {
        // 从 1970 年到当初的总毫秒值(也叫工夫戳)long millis = System.currentTimeMillis();
        System.out.println(millis);       // 1596168719242
        // 毫秒值转日期对象
        Date date = new Date(millis);
        System.out.println(date);         // Fri Jul 31 12:11:59 CST 2020
        // 日期对象转毫秒值
        long millis2 = date.getTime();
        System.out.println(millis2);      // 1596168719242
    }
}

2.2-DateFormat 类(记忆)

概述

java.text.DateFormat 是日期 / 工夫格式化子类的抽象类,咱们通过这个类能够帮咱们实现日期和文本之间的转换, 也就是能够在 Date 对象与 String 对象之间进行来回转换。

  • 格式化:依照指定的格局,把 Date 对象转换为 String 对象。
  • 解析:依照指定的格局,把 String 对象转换为 Date 对象

构造方法

因为 DateFormat 为抽象类,不能间接应用,所以须要罕用的子类java.text.SimpleDateFormat。这个类须要一个模式(格局)来指定格式化或解析的规范。构造方法为:

  • public SimpleDateFormat(String pattern):用给定的模式和默认语言环境的日期格局符号结构 SimpleDateFormat。

参数 pattern 是一个字符串,代表日期工夫的自定义格局。

罕用的格局规定为:

标识字母(辨别大小写) 含意
y
M
d
H
m
s

备注:更具体的格局规定,能够参考 SimpleDateFormat 类的 API 文档。

转换方法

  • String format(Date date) 传递日期对象,返回格式化后的字符串。
  • Date parse(String str) 传递字符串,返回日期对象。
  public static void main(String[] args) throws ParseException {
    // 创立以后日期对象
    Date date = new Date();
    // 创立格式化对象
    DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    String dateStr = format.format(date);
    System.out.println(dateStr);   // 2019-12-07 05:37:53
    // 把格式化日期转换为日期对象
    Date date2 = format.parse("2100-12-12 12:12:12");
    System.out.println(date2);   // Sun Dec 12 00:12:12 CST 2100
  }

2.3-Calendar 类(记忆)

概述

java.util.Calendar是日历类,在 Date 后呈现,替换掉了许多 Date 的办法。该类将所有可能用到的工夫信息封装为动态成员变量,不便获取。日历类就是不便获取各个工夫属性的。

获取日历对象

Calendar 是抽象类,不能创建对象,须要应用子类对象。java.util.GregorianCalendar类是 Calendar 的子类,然而创立日历对象须要依据本地的时区,语言环境来创立,比拟艰难,Calendar 类提供了静态方法 getInstance()间接获取子类的对象。

public static Calendar getInstance():应用默认时区和语言环境取得一个日历。

  public static void main(String[] args) {
    // 获取日历对象
    Calendar calendar = Calendar.getInstance();}

罕用办法

罕用办法

  • public int get(int field):返回给定日历字段的值。
  • public void set(int field, int value):将给定的日历字段设置为给定值。
  • public abstract void add(int field, int amount):依据日历的规定,为给定的日历字段增加或减去指定的工夫量。
  • public Date getTime():返回一个示意此 Calendar 工夫值(从历元到当初的毫秒偏移量)的 Date 对象。

field:Calendar 类中提供很多成员常量,代表给定的日历字段:

字段值 含意
YEAR
MONTH 月(从 0 开始,能够 + 1 应用)
DAY_OF_MONTH 月中的天(几号)
HOUR 时(12 小时制)
HOUR_OF_DAY 时(24 小时制)
MINUTE
SECOND
DAY_OF_WEEK 周中的天(周几,周日为 1,能够 - 1 应用)

代码:

  public static void main(String[] args) {
    // 获取日历对象
    Calendar calendar = Calendar.getInstance();
    // 获取以后日期的局部数据
    System.out.println(calendar.get(Calendar.YEAR));
    System.out.println(calendar.get(Calendar.MONTH));    // 月份 0-11
    System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
    System.out.println(calendar.get(Calendar.HOUR_OF_DAY));
    System.out.println(calendar.get(Calendar.MINUTE));
    System.out.println(calendar.get(Calendar.SECOND));
    System.out.println(calendar.get(Calendar.DAY_OF_WEEK));

  }

练习

需要:获取任意一年的二月有多少天

剖析:

  • 能够将日历设置到任意年的三月一日
  • 向前偏移一天
  • 获取偏移后的日历即可

代码:

public static void main(String[] args) {
    // 键盘录入任意的年份
    Scanner sc = new Scanner(System.in);
    System.out.println("请输出年:");
    int year = sc.nextInt();

    // 设置日历对象的年、月、日
    Calendar c = Calendar.getInstance();
    c.set(year, 2, 1);

    // 3 月 1 日往前推一天,就是 2 月的最初一天
    c.add(Calendar.DATE, -1);

    // 获取这一天输入即可
    int date = c.get(Calendar.DATE);
    System.out.println(year + "年的 2 月份有" + date + "天");

第三章:System 类

3.1- 概述(理解)

java.lang.System类中提供了大量的静态方法,能够获取与零碎相干的信息或零碎级操作。System 类公有润饰构造方法,不能创建对象,间接类名调用。

3.2- 罕用办法(记忆)

3.3- 测试程序运行时长(练习)

需要:在控制台输入 1 -10000,计算这段代码执行了多少毫秒

public static void main(String[] args) {
    // 获取以后工夫毫秒值
    System.out.println(System.currentTimeMillis()); 
    // 计算程序运行工夫
    long start = System.currentTimeMillis();
    for (int i = 1; i <= 10000; i++) {System.out.println(i);
    }
    long end = System.currentTimeMillis();
    System.out.println("共耗时毫秒:" + (end - start));
 }  

3.4-arryCopy 办法(记忆)

参数

  • Object src:要复制的数据源数组
  • int srcPost:数据源数组的开始索引
  • Object dest:复制后的目标数组
  • int destPos:目标数组开始索引
  • int length:要复制的数组元素的个数

代码

将源数组中从 1 索引开始,复制 3 个元素到目标数组中

public static void main(String[] args){int[] src = {1,2,3,4,5};
    int[] dest = {6,7,8,9,0};
    // 将源数组中从 1 索引开始,复制 3 个元素到目标数组中
    System.arraycopy(src,1,dest,0,3);
    for(int i = 0 ; i < dest.length;i++){System.out.println(dest[i]);
}

3.5-gc 办法(理解)

运行垃圾回收器,JVM 将从堆内存中清理对象,清理对象的同时会调用对象的 finalize()办法,JVM 的垃圾回收器是通过另一个线程开启的,因而程序中的成果并不显著。

Person 类

public class Person {protected void finalize() throws Throwable {System.out.println("对象被回收");
}

测试类:

public static void main(String[] args){new Person();
    new Person();
    new Person();
    new Person();
    new Person();
    new Person();
    System.gc();}

第四章:数组的冒泡排序

数组的排序,是将数组中的元素依照大小进行排序,默认都是以升序的模式进行排序,数组排序的办法很多,咱们解说的是数组的冒泡排序。

排序,都要进行数组 元素大小的比拟,再进行地位的替换。冒泡排序法是采纳数组中相邻元素进行比拟换位。

4.1- 什么是冒泡排序(理解)

冒泡排序(Bubble Sort),是一种较简略的排序算法。

反复地 走访过要排序的元素列,顺次 比拟两个相邻 的元素,如果程序谬误就把他们 替换 过去。走访元素的工作是 反复地进行直到没有相邻元素须要替换,也就是说该元素列曾经排序实现。

这个算法的名字由来是因为越小的元素会经由替换缓缓“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

实 质:把小(大)的元素往前(后)调

4.2- 冒泡排序的剖析和实现(练习)

需要

对数组 {3, 6, 4, 2, 1, 5} 进行从小到大的排序。

该数组共 6 个元素。

图解冒泡算法解析过程

代码实现

经上述图解剖析:代码实现须要

  1. 双重循环

    • 外层循环,管制躺数(躺数从 0 开始,因为数组索引从 0 开始,比拟好计算)。 躺数 = 数组长度 - 1
    • 内层循环,管制每趟比拟的次数。每趟比拟的次数 = 数组的长度 - 以后躺数 - 1
  2. 比拟相邻的两个数字,若地位谬误,则两个数字替换
public class Test06 {public static void main(String[] args) {
        // 定义要排序的数组
        int[] arr = {3, 6, 4, 2, 1, 5};
        System.out.println("数组排序前:" + showArray(arr));
        /**
         * 冒泡排序
         */
        for (int i = 0; i < arr.length - 1; i++) {
            // 外层循环管制躺数
            // i 示意以后躺数
            for (int j = 0; j < arr.length - i - 1; j++) {
                // 内层循环管制每趟比拟的次数
                // 相邻的两个数字开始比拟:arr[j] 和 arr[j+1]
                if (arr[j] > arr[j + 1]) {
                    // 地位谬误产生替换
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        System.out.println("数组排序后:" + showArray(arr));
    }
    /**
     * 查看数组
     */
    public static String showArray(int[]arr) {StringBuilder sb = new StringBuilder();
        sb.append("{");
        for (int i = 0; i < arr.length; i++) {if (i == arr.length - 1) {sb.append(arr[i]);
            } else {sb.append(arr[i] + ",");
            }
        }
        sb.append("}");
        return sb.toString();}
}

执行后果:

/*
    数组排序前:{3, 6, 4, 2, 1, 5}
    数组排序后:{1, 2, 3, 4, 5, 6}
*/

第五章:数组的二分查找

目标:从数组中查问一个元素,比拟高效的查问形式,就是二分查找。

5.1- 什么是二分查找(理解)

二分查找也称折半查找(Binary Search),它是一种效率较高的查找办法,然而,折半查找要求查问的数组的元素是有序排列的

查找过程如下:

  • 首先,假如数组中的元素是按 升序排列
  • 将数组两头地位记录的元素值与要查找的元素值比拟,如果两者相等,则查找胜利;
  • 否则利用两头地位的记录将数组分成前、后两个子数组;
  • 如果两头地位记录的元素值大于要查找元素值,则进一步查找前一子数组,否则进一步查找后一子数组。
  • 反复以上过程,直到找到满足条件的记录,使查找胜利,或直到子表不存在为止,此时查找不胜利。

5.2- 二分查找的剖析和实现(练习)

需要

从数组 {2, 5, 9, 10, 18, 20, 24} 中别离查问出元素5203

折半查找,不能简略的除以 2,须要确认最小索引和最大索引。因为可能会屡次折半(一次 折半可能查找不胜利),索引最小索引和最大索引可能会变动。所以须要确定以下变量:

最小索引:min = 0

最大索引:max = 数组的长度 – 1

两头索引:(max + min)/2

图解剖析

图解剖析查问元素 5 的过程

图解剖析查问元素 20 的过程:

图解剖析查问元素 3(一个不存在的元素)的过程:

论断

对于要查问的元素:

  1. 折半次数不确定(可能是屡次),应用 while 循环更简便。
  2. 折半过程中,若查问的值小于 mid 地位的值,则更改索引 max 为:max = mid – 1
  3. 折半过程中,若查问的值大于 mid 地位的值,则更改索引 min 为:min = mid + 1
  4. 查问胜利,要查问的元素 和 mid 值相等时,终止查问。
  5. 元素中不存在该元素,条件是索引 min 大于索引 max 时,终止查问。

代码

public class Test06 {public static void main(String[] args) {
        // 定义数组
        int[]arr = { 2, 5, 9, 10, 18, 20, 24};
        // 查问元素 5
        int index1 = binarySearch(arr,5);
        System.out.println("从数组:{ 2, 5, 9, 10, 18, 20, 24}查问元素 5 的索引是:" + index1);
        // 查问元素 20
        int index2 = binarySearch(arr,20);
        System.out.println("从数组:{ 2, 5, 9, 10, 18, 20, 24}查问元素 20 的索引是:" + index2);
        // 查问元素 3
        int index3 = binarySearch(arr,3);
        System.out.println("从数组:{ 2, 5, 9, 10, 18, 20, 24}查问元素 3 的索引是:" + index3);
    }

    /**
     * 二分查找, 返回要查找的元素的索引
     * @param arr 数组
     * @param key 要查问的元素值
     * @return 查问的后果,- 1 示意不存在该元素
     */
    public static int binarySearch(int[]arr, int key) {
        // 最小索引初始化为 0
        int min = 0;
        // 最大索引初始化为数组的长度 -1
        int max = arr.length - 1;
        // 两头索引
        int mid = 0;
        // 定义查问后的元素的索引,默认为 -1,示意不存在该元素
        int index = -1;
        // 循环查问
        while (min <= max){mid = (max + min)/2;
            if(key > arr[mid]) {min = mid + 1;}else if(key < arr[mid]){max = mid - 1;}else {
               index = mid;
               break;
            }
        }
        return index;
    }

}

查问后果:

/*
    从数组:{2, 5, 9, 10, 18, 20, 24}查问元素 5 的索引是:1
    从数组:{2, 5, 9, 10, 18, 20, 24}查问元素 20 的索引是:5
    从数组:{2, 5, 9, 10, 18, 20, 24}查问元素 3 的索引是:-1
*/

第六章:Arrays 类

咱们发现操作数组时,不论是排序、二分查找等,每次实现都须要本人剖析写代码。在开发过程中,影响开发效率。所以 Java 中提供了操作数组的工具类 Arrays。

6.1- 概述(理解)

java.util.Arrays 此类蕴含用来操作数组的各种办法,比方排序和搜寻等。Arrays 类公有润饰构造方法,其所有办法均为静态方法,调用起来非常简单。

6.2- 罕用办法(记忆)

理解更多办法可查问 API

    public static void main(String[] args) {
        // 定义数组
        int[]arr = { 2, 9, 5, 10, 24, 20, 18};
        // 排序
        Arrays.sort(arr);
        // 排序后的数组
        System.out.println(Arrays.toString(arr));
        // 二分查找元素 5 的索引
        System.out.println(Arrays.binarySearch(arr,5));
        // 二分查找元素 20 的索引
        System.out.println(Arrays.binarySearch(arr,20));
        // 二分查找元素 3 的索引
        System.out.println(Arrays.binarySearch(arr,3));
    }

第七章:正则表达式

在理论开发中,咱们常常会对一些字符串做验证,比方验证邮箱格局、手机号码、身份证号码等。此时,最无效的验证形式就是正则表达式,只须要用正则形容验证规定,而后间接匹配字符串即可。

7.1- 概述(理解)

正则表达式是对字符串操作的一种规定,当时定义好一些字符串,这些字符串称为规定字符串,应用规定字符串表白一些逻辑性能。

例如:指定一个字符串 704181501@qq.com,判断出这个字符串是否合乎电子邮件的规定。应用字符串 String 对象的办法是能够实现的,然而非常复杂,若应用正则表达式则会十分的简略实现。

7.2- 正则规定 - 字符类(记忆)

在中括号中定义的字符

7.3- 正则规定 - 预约义字符类(记忆)

预约义字符,具备非凡含意的字符。

留神:对于 w、d、W、D 在 java 中示意时用双杠如 \\w 示意,因为在 java 的字符串中示意本义。

7.4- 正则规定 - 数量词(记忆)

7.5- 正则规定 - 分组(记忆)

分组,就是将多个字符看做一个整体,用 小括号 示意。

比方:”(李){4}” 示意字符“李”必须呈现四次

比方:”(李小龙){4}” 示意字符 ” 李小龙 ” 必须间断呈现四次

7.6- 正则规定 - 本义符(记忆)

对于,具备非凡含意的字符若示意为一般字符,能够应用本义符 \, 如. 就在正则中示意任意字符,但若就是示意为一般的点的话,则须要本义\. java 字符串中示意用\\.

7.5-Java 中应用正则表达式(练习)

String 类 matches 办法应用正则表达式

办法:boolean matches(String regex)传递正则表达式规定,检测字符串是否匹配正则表达式规定,匹配返回 true。

需要:查看手机号,查看邮件地址。

剖析:

  • 手机号:只能 1 结尾,第二位能够是 345678 任意一个,第三位开始全数字,总长 11 位。
  • 邮件地址:@后面能够是数字,字母,下划线。@前面是字母和.。
public static void main(String[] args){
    //【验证手机号码】String tel = "13800138000";
    // 规定
    String telRegex = "1[345678][0-9]{9}";
    // 检测
    boolean flag = tel.matches(telRegex);
    System.out.println(flag); 
    //【验证邮件地址】String email = "lpl2015@vip.qq.com";
    String emailReg = "\\w+@(\\w+\\.)+\\w+";
    flag = email.matches(emailReg);
    System.out.println(flag);
}

String 类 split 办法应用正则表达式

办法:String[] split(String regex)传递正则表达式规定,以正则规定对字符串进行切割,返回数组。

public static void main(String[] args){
    String str1 = "ab  a   bbb  abc   aa      c";
    // 对空格进行切割
    String[] strArr =str1.split("+");
    System.out.println(Arrays.toString(strArr));

    String str2 = "192.168.1.121";
    strArr = str2.split("\\.");
    System.out.println(Arrays.toString(strArr));
}

留神:输入数组元素时会看到存在一个多余空格,Arrays.toString()办法源码中追加的空格。

正文完
 0