目 录CONTENT

文章目录

从0开始学Java——常用API和常见算法(12)

Eric
2022-01-23 / 0 评论 / 0 点赞 / 147 阅读 / 15,160 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2023-12-12,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

1 String类

1.1 概述

  • String类:代表字符串。Java程序中的所有字符串字面量(如:“abc”)都是此类的实例。

  • String是一个final类,代表不可变的字符序列

  • 字符串是常量,用双引号(“”)引起来表示。它们的值在创建之后不能改变。

  • String对象的字符串内容是存储在一个字符数组value[]中的。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0
    
    ...
}

1.2 字面量的定义方式

  • 示例:
package top.open1024.string.demo1;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-17 20:21
 */
public class Test {
    public static void main(String[] args) {
        // 字面量的定义方式
        String s1 = "123";
        String s2 = "123";

        s1 = "hello";

        System.out.println("s1 = " + s1); // s1 = hello
        System.out.println("s2 = " + s2); // s2 = 123
    }
}

img

1.3 String的特点

  • ① 字符串String类型本身是final修饰的,意味着我们不能继承String。

  • ② 字符串的对象也是不可变对象,意味着一旦进行修改,就会产生新的对象。

注意:如果程序中涉及到了大量的字符串的修改操作,那么此时的内存消耗比较高,可能需要考虑使用StringBuilder或StringBuffer的可变字符序列。

  • ③ String对象内部是用字符数组保存的。

JDK 9之前是用char[]数组保存的,JDK 9之后时用byte[]数组保存的。

  • 例如:下面的代码是等价的
String str = "abc";
char[] chs= {'a','b','c'};
String str = new String(chs);
  • ④ String类中的char[] values数组也是用final修饰的,意味着这个数组不可变,又因为是用private修饰的,意味着外界不能直接操作它。String类提供的所有方法都是用新对象来表示修改后的内容的,保证了String对象的不可变。

  • ⑤ 因为String对象设计为不可变,所以String有常量池来保存很多常量对象。

    • 常量池在方法区。
    • 常量池的细致划分:
      • JDK 6及之前:方法区。
      • JDK 7:堆。
      • JDK 8:元空间。
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); //true
// 内存中只有一个"abc"对象被创建,同时被s1和s2所共享

1.4 String的内存示意图

  • 示例:
package top.open1024.string.demo3;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-18 11:05
 */
public class Test {
    public static void main(String[] args) {
        String str = "abc";
        String str2 = new String("abc");

        System.out.println(str == str2); // false
    }
}

img

1.5 构造String对象

1.5.1 构造方法

  • 初始化新创建的String对象,表示空字符序列:
public String(){}
  • 初始化一个新创建的String对象,使其表示一个和参数相同的字符序列;换言之,新创建的字符串是该参数字符串的副本
public String(String original){}
  • 通过当前参数中的字符数组来构造新的String:
public String(char[] value){}
  • 通过字符数组的一部分来构造新的String:
public String(char[] value,int offset, int count){}
  • 通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String:
public String(byte[] bytes){}
  • 通过使用指定的字符集解码当前参数中的字节数组来构造新的String:
public String(byte[] bytes,String charsetName){}
  • 示例:
package top.open1024.string.demo4;

import java.io.UnsupportedEncodingException;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-19 10:37
 */
public class Test {
    public static void main(String[] args) throws UnsupportedEncodingException {
        // 字符串常量对象
        String str = "hello";
        System.out.println("str = " + str);

        // 无参构造
        String str1 = "";
        System.out.println("str1 = " + str1);

        // 创建"hello"字符串常量的副本
        String str2 = new String("hello");
        System.out.println("str2 = " + str2);

        // 通过字符数组创建
        char[] chs = {'a', 'b', 'c', 'd'};
        String str3 = new String(chs);
        String str4 = new String(chs, 0, 3);
        System.out.println("str3 = " + str3);
        System.out.println("str4 = " + str4);

        // 通过字节数组构造
        byte bytes[] = {97, 98, 99 };
        String str5 = new String(bytes);
        String str6 = new String(bytes,"utf-8");
        System.out.println("str5 = " + str5);
        System.out.println("str6 = " + str6);
    }
}

1.5.2 静态方法

  • 返回指定数组的String:
public static String valueOf(char data[]) {}
  • 返回指定数组的String(指定子数组的开始索引和子数组的长度):
public static String valueOf(char data[], int offset, int count){}
  • 返回各种类型的value的String:
public static String valueOf(xx value) {}
  • 示例:
package top.open1024.string.demo5;

/**
 * String的静态方法
 * 
 * @author open1024
 * @version 1.0
 * @since 2021-09-19 19:01
 */
public class Test {
    public static void main(String[] args) {
        char[] chs = {'A', 'B', '我', '是', '谁'};

        String s = String.valueOf(chs);
        System.out.println("s = " + s);

        String s1 = String.valueOf(chs, 0, 2);
        System.out.println("s1 = " + s1);

        Object obj = "你好啊";
        String s2 = String.valueOf(obj);
        System.out.println("s2 = " + s2);

    }
}

1.5.3 使用“”+

  • 任意数据类型和“字符串”进行拼接,结果都是字符串。

  • 示例:

package top.open1024.string.demo6;

import java.util.ArrayList;
import java.util.List;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-19 19:25
 */
public class Test {
    public static void main(String[] args) {
        int num = 123456;
        String s = num + "";
        System.out.println("s = " + s);

        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);

        String str = list + "";
        System.out.println(str);
    }
}

1.6 字符串拼接问题

1.6.1 拼接结果的存储和比较问题

  • 原则:

    • 常量+常量:结果是常量池。
    • 常量和变量 或 变量和变量:结果是堆。
    • 拼接后调用intern方法:结果在常量池。
  • 示例:

package top.open1024.string.demo7;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-19 19:52
 */
public class Test {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "world";
        String s3 = "helloworld";

        String s4 = (s1 + "world").intern(); // 将拼接的结果放在常量池中
        String s5 = (s1 + s2).intern();

        System.out.println(s3 == s4); // true
        System.out.println(s3 == s5); // true
    }
}
  • 示例:
package top.open1024.string.demo8;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-19 19:57
 */
public class Test {
    public static void main(String[] args) {
        final String s1 = "hello";
        final String s2 = "world";
        String s3 = "helloworld";

        String s4 = s1 + "world"; // s1是常量,"world"也是常量,所以s4是常量

        String s5 = s1 + s2; // s1是常量,s2是常量,所以s5是常量

        String s6 = "hello" + "world"; // "hello"是常量,"world"是常量,所以s6是常量

        System.out.println(s3 == s4); // true
        System.out.println(s3 == s5); // true
        System.out.println(s3 == s6); // true
    }
}
  • 示例:
package top.open1024.string.demo9;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-19 20:00
 */
public class Test {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "world";

        String s3 = "helloworld";

        String s4 = s1 + "world"; // s1是变量,"world"是常量,所以s4是变量

        String s5 = s1 + s2; // s1是变量,s2是变量,所以s5是变量

        String s6 = "hello" + "world"; // "hello"是常量,"world"是常量,所以s6是常量

        System.out.println(s3 == s4); // false
        System.out.println(s3 == s5); // false
        System.out.println(s3 == s6); // true
    }
}

1.6.2 拼接效率问题

  • 示例:
package top.open1024.string.demo10;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-19 20:03
 */
public class Test {
    public static void main(String[] args) {
        String str = "0";
        for (int i = 0; i < 5; i++) {
            str += i;
        }
        System.out.println("str = " + str);
    }
}
  • 不过,现在的JDK版本,都会使用可变字符序列对如上的代码优化,不信,反编译查看字节码:
javap -c Test.class
Compiled from "Test.java"
public class top.open1024.string.demo10.Test {
  public top.open1024.string.demo10.Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String 0
       2: astore_1
       3: iconst_0
       4: istore_2
       5: iload_2
       6: iconst_5
       7: if_icmpge     35
      10: new           #3                  // class java/lang/StringBuilder
      13: dup
      14: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      17: aload_1
      18: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      21: iload_2
      22: invokevirtual #6                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      25: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      28: astore_1
      29: iinc          2, 1
      32: goto          5
      35: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
      38: new           #3                  // class java/lang/StringBuilder
      41: dup
      42: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      45: ldc           #9                  // String str =
      47: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      50: aload_1
      51: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      54: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      57: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      60: return
}

1.6.3 concat方法拼接

  • concat()方法拼接,哪怕是两个常量对象拼接,结果也是在堆中。

  • 示例:

package top.open1024.string.demo19;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-21 08:43
 */
public class Test {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "world";
        String s3 = "helloworld";

        String s4 = "hello".concat("world");
        String s5 = "hello" + "world";

        System.out.println(s3 == s4); // false
        System.out.println(s3 == s5); // true
        System.out.println(s1 + s2 == s5); // false
    }
}

1.7 字符串对象的比较

1.7.1 ==

  • ==比较的是对象的地址,只有两个字符串变量都指向字符串的常量对象时,才会返回true。

  • 示例:

package top.open1024.string.demo20;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-21 08:47
 */
public class Test {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";
        System.out.println(s1 == s2); // true

        String s3 = new String("hello");
        String s4 = new String("hello");
        System.out.println(s3 == s4); // false
        System.out.println(s1 == s4); // false
    }
}

1.7.2 equals()方法

  • equals()方法比较的是对象的内容,因为String类重写了equals()方法,并且equals()方法区分大小写:
public boolean equals(Object anObject){}
  • 示例:
package top.open1024.string.demo21;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-21 08:51
 */
public class Test {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";

        System.out.println(s1.equals(s2)); // true

        String s3 = new String("hello");
        String s4 = new String("hello");
        System.out.println(s3.equals(s4)); // true
        System.out.println(s1.equals(s4)); // true
    }
}

1.7.3 equalsIgnoreCase()方法

  • equalsIgnoreCase()方法比较的是对象的内容,并且不区分大小写:
public boolean equalsIgnoreCase(String anotherString){}
  • 示例:
package top.open1024.string.demo22;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-21 08:55
 */
public class Test {
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = new String("HELLO");
        System.out.println(s1.equalsIgnoreCase(s2)); // true
    }
}

1.7.4 compareTo()方法

  • String类重写了Comparable接口的抽象方法,自然排序,按照字符的Unicode编码值进行比较大小,严格区分大小写:
public int compareTo(String anotherString){}
  • 示例:
package top.open1024.string.demo23;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-21 08:58
 */
public class Test {
    public static void main(String[] args) {
        String s1 = "i";
        String s2 = "love";

        System.out.println(s1.compareTo(s2)); // -3
    }
}

1.7.5 compareToIgnoreCase()方法

  • compareToIgnoreCase()方法不区分大小写,其他按照字符的Unicode编码值进行比较大小:
public int compareToIgnoreCase(String str){}
  • 示例:
package top.open1024.string.demo24;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-21 09:00
 */
public class Test {
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = new String("Hello");

        System.out.println(s1.compareToIgnoreCase(s2)); // 0
    }
}

1.8 空字符串的比较

1.8.1 那些是空字符串

  • 空字符串的长度是0。

  • 示例:

package top.open1024.string.demo25;

/**
 * 空字符串
 * 
 * @author open1024
 * @version 1.0
 * @since 2021-09-21 10:54
 */
public class Test {
    public static void main(String[] args) {
        String s1 = "";
        String s2 = new String();
        String s3 = new String("");

        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
    }
}

1.8.2 如何判断某个字符串是否为空字符串?

  • 示例:
package top.open1024.string.demo26;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-21 10:56
 */
public class Test {
    public static void main(String[] args) {
        String str = "";

        if ("".equals(str)) {
            System.out.println("是空字符串");
        }
    }
}
  • 示例:
package top.open1024.string.demo27;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-21 10:57
 */
public class Test {
    public static void main(String[] args) {
        String str = "";

        if (null != str && str.isEmpty()) {
            System.out.println("是空字符串");
        }
    }
}
  • 示例:
package top.open1024.string.demo28;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-21 10:58
 */
public class Test {
    public static void main(String[] args) {
        String str = "";
        if(null != str && str.equals("")){
            System.out.println("是空字符串");
        }
    }
}
  • 示例:
package top.open1024.string.demo29;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-21 10:59
 */
public class Test {
    public static void main(String[] args) {
        String str = "";
        if(null != str && str.length() ==0){
            System.out.println("是空字符串");
        }
    }
}

1.9 字符串的常用方法

1.9.1 系列1

  • 字符串是否为空:
public boolean isEmpty() {}
  • 返回字符串的长度:
public int length() {}
  • 拼接,等价于+
public String concat(String str) {}
  • 比较字符串是否相等,区分大小写:
public boolean equals(Object anObject){}
  • 比较字符串是否相等,不区分大小写:
public boolean equalsIgnoreCase(String anotherString){}
  • 比较字符串大小,区分大小写,按照Unicode编码值比较大小:
public int compareTo(String anotherString){}
  • 比较字符串大小,不区分大小写,按照Unicode编码值比较大小:
public int compareToIgnoreCase(String str){}
  • 将字符串中大写字母转为小写:
public String toLowerCase(){}
  • 将字符串中小写字母转为大写:
public String toUpperCase(){}
  • 去掉字符串前后空白符:
public String trim(){}
  • 示例:
package top.open1024.string2.demo;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-24 14:10
 */
public class Test {
    public static void main(String[] args) {
        String str = "hello world";
        String s = str.toUpperCase();
        System.out.println("将字符串中的小写字母转换为大写字母 = " + s);

        String str2 = "Hello WorLD";
        String s1 = str2.toLowerCase();
        System.out.println("将字符串中的大写字母转换为小写字母 = " + s1);

        String str3 = "  hello world  ";
        String s3 = str3.trim();
        System.out.println("去掉字符串前后空白符 = " + s3);
    }
}

1.9.2 系列2:查找

  • 字符串中是否包含子串:
public boolean contains(CharSequence s){}
  • 从前往后查找字符串中的子串,如果有,有返回第一次出现的下标;否则,返回-1:
public int indexOf(String str){}
  • 从后往前查找字符串中的子串,如果有,有返回第一次出现的下标;否则,返回-1:
public int lastIndexOf(String str){}
  • 示例:
package top.open1024.string2.demo2;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-24 14:17
 */
public class Test {
    public static void main(String[] args) {
        String str = "hello world";
        String str2 = "or";

        boolean contains = str.contains(str2);
        if (contains) {
            System.out.println(str + "中是否包含" + str2);
        }

        int index = str.indexOf(str2);
        System.out.println(str2 + "在" + str + "中从前往后查找的索引是:" + index);

        index = str.lastIndexOf(str2);
        System.out.println(str2 + "在" + str + "中从后往前的索引是:" + index);

    }
}

1.9.3 系列3:字符串截取

  • 返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串:
public String substring(int beginIndex){}
  • 返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串:
public String substring(int beginIndex, int endIndex) {}
  • 示例:
package top.open1024.string2.demo3;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-24 14:24
 */
public class Test {
    public static void main(String[] args) {
        String str = "Java is a good computer language";

        System.out.println(str.substring(5)); // is a good computer language
        System.out.println(str.substring(5, 11)); // is a g
    }
}

1.9.4 系列4:和字符相关

  • 返回index位置的字符:
public char charAt(int index){}
  • 将此字符串转换为一个新的字符数组返回:
public char[] toCharArray(){}
  • 返回指定数组中表示该字符序列的String:
public String(char value[]){}
  • 返回指定数组中表示该字符序列的 String:
public String(char value[], int offset, int count){}
  • 返回指定数组中表示该字符序列的 String:
public static String copyValueOf(char data[]){}
  • 返回指定数组中表示该字符序列的 String:
public static String valueOf(char data[], int offset, int count){}
  • 返回指定数组中表示该字符序列的 String:
public static String valueOf(char data[]){}
  • 示例:
package top.open1024.string2.demo4;

import java.util.Arrays;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-24 14:27
 */
public class Test {
    public static void main(String[] args) {
        // 将首字母抓换为大写
        String str = "hello World";
        str = Character.toUpperCase(str.charAt(0)) + str.substring(1);
        System.out.println("str = " + str); // Hello World

        // 将字符串中的字符按照大小顺序排列
        String str2 = "helloworldjava";
        char[] chars = str2.toCharArray();
        Arrays.sort(chars);
        System.out.println("chars = " + Arrays.toString(chars)); // [a, a, d, e, h, j, l, l, l, o, o, r, v, w]
    }
}

1.9.5 系列5:编码和解码

  • 编码,将字符串转换为字节数组,按照平台默认的字符编码进行编码:
public byte[] getBytes(){}
  • 编码,按照指定的编码方式进行编码:
public byte[] getBytes(Charset charset){}
  • 解码,将字节数组转换为字符串,按照平台默认的字符编码进行解码:
public String(byte bytes[]) {}
public String(byte bytes[], int offset, int length){}
  • 解码,按照指定的编码方式进行解码:
public String(byte bytes[], Charset charset){}
public String(byte bytes[], String charsetName) throws UnsupportedEncodingException{}
  • 示例:
package top.open1024.string2.demo5;

import java.nio.charset.StandardCharsets;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-24 14:43
 */
public class Test {
    public static void main(String[] args) {
        String str = "我爱中国";
        System.out.println(new String(str.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8));
    }
}

1.9.6 系列6:开头和结尾

  • 是否以指定字符串开头:
public boolean startsWith(String prefix){}
public boolean startsWith(String prefix, int toffset){}
  • 是否以指定字符串结尾:
public boolean endsWith(String suffix){}
  • 示例:
package top.open1024.string2.demo6;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-24 14:46
 */
public class Test {
    public static void main(String[] args) {
        String str = "我爱中国,我喜欢Java语言,但是我的英语不咋的";
        System.out.println(str.startsWith("我")); // true
        System.out.println(str.startsWith("我爱")); // true
        System.out.println(str.startsWith("我爱中国")); // true

        System.out.println(str.endsWith("不咋的")); // true
        System.out.println(str.endsWith("咋的")); // true
        System.out.println(str.endsWith("的")); // true
    }
}

1.9.7 系列7:正则表达式

  • 正则表达式:用来专门处理字符串的技术。

  • 字符类:

    • [abc]:只能是a或b或c。
    • [^abc]:除了a、b、c以外的任意一个字符。
    • [a-zA-Z]:必须是a-z,A-Z中的任意一个字符。
    • [^a-zA-Z]:除了a-z,A-Z中的任意任意一个字符。
  • 数字类:

    • [0-9]:只能是0和9之间的任意一个数字。
    • \d:等同于[0-9]
    • [^0-9]:除了0和9之间的任意一个数字。
    • \D:等同于[^0-9]
  • 预定于字符类:

    • .:匹配所有字符。
    • \d:等同于[0-9]
    • \D:等同于[^0-9]
    • \w:等同于[a-zA-Z_0-9]
    • \W:等同于[^a-zA-Z_0-9]
  • 边界匹配器:

    • ^:行的开头。
    • $:行的结尾。
  • 数量类:

    • X?:X字符最多只能出现一次(0次或1次)。
    • X*:X字符可以出现0次、1次或多次。
    • X+:X字符可以出现1次或多次。
    • X{n}:X字符只能出现n次。
    • X{n*,}:x字符至少出现n次(在数学中表示[n,+∞))。
    • X{n,m}:x字符只能出现n到m次(在数学中表示[n,m])。
  • 字符串是否匹配指定的正则表达式:

public boolean matches(String regex){}
  • 替换,不支持正则:
public String replace(char oldChar, char newChar){}
public String replace(CharSequence target, CharSequence replacement){}
  • 替换第一个匹配部分:
public String replaceFirst(String regex, String replacement){}
  • 替换所有匹配部分:
public String replaceAll(String regex, String replacement){}
  • 示例:
package top.open1024.string2.demo8;

/**
 * 手机号码的规则:
 * 开头必须是1,长度规定11。
 * 第二位 3 - 9
 * 第三位到最后一位 0 - 9
 *
 * @author open1024
 * @version 1.0
 * @since 2021-09-24 15:31
 */
public class Test {
    public static void main(String[] args) {
        String iphone = "13800138000";
        boolean matches = iphone.matches("^1[3-9]\\d{9}$");
        System.out.println("matches = " + matches);
    }
}
  • 示例:
package top.open1024.string2.demo9;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-24 16:28
 */
public class Test {
    public static void main(String[] args) {
        String str = "hello22world.java;234";
        // 将其中的非字母替换掉
        String s = str.replaceAll("[^a-zA-Z]", "");
        System.out.println("s = " + s);
    }
}

1.9.8 系列8:拆分

  • 按照某种规则将字符串进行拆分:
public String[] split(String regex){}
  • 示例:
package top.open1024.string2.demo10;

import java.util.Arrays;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-24 16:34
 */
public class Test {
    public static void main(String[] args) {
        String str = "张三.23|李四.24|王五.25";
        // 按照|拆分
        String regex = "\\|";
        String[] split = str.split(regex);
        for (String s : split) {
            // 按照.进行拆分
            String[] str2 = s.split("\\.");
            System.out.println(Arrays.toString(str2));
        }
    }
}

1.10 练习题

1.10.1 练习1

  • 在字符串中找出连续最长数字串,返回这个串的长度,并打印这个最长数字串。

  • 例如:abcd12345cd125se123456789,返回9,打印出123456789。

  • 示例:

package top.open1024.string2.demo11;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-24 16:45
 */
public class Test {
    public static void main(String[] args) {
        String str = "abcd12345cd125se123456789";
        String[] split = str.split("[a-zA-Z]+");
        String max = "";
        for (String s : split) {
            if (s.length() > max.length()) {
                max = s;
            }
        }
        System.out.println("最长的字符串是:" + max + ",它的长度是:" + max.length());
    }
}

1.10.2 练习2

  • 将字符串中指定部分进行反转。比如将“abcdefgho”反转为”abfedcgho”。

  • 示例:

package top.open1024.string2.demo12;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-24 16:54
 */
public class Test {
    public static void main(String[] args) {
        String str = "abcdefgho";
        String reverse = reverse(str, 2, 5);
        System.out.println("reverse = " + reverse); // abfedcgho
    }

    public static String reverse(String str, int start, int end) {
        char[] chars = str.toCharArray();
        for (int i = start, j = end; i < j; i++, j--) {
            char temp = chars[i];
            chars[i] = chars[j];
            chars[j] = temp;
        }
        return new String(chars);
    }
}

1.10.3 练习3

  • 计算字符串B(例如:ab)在字符串A(例如: dsabdnabdsnabeabiwpabekabd)中出现的次数。

  • 实现思路:

    • ① 对字符串进行索引查找 indexOf。
    • ② 找到字符串的索引记录,进行字符串截取。
    • ③ 直到找到位置,indexOf的方法是-1。
    • ④ 一旦找到,计算器+1。
  • 示例:

package top.open1024.string2.demo13;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 13:09
 */
public class Test {
    public static void main(String[] args) {
        String a = "dsabdnabdsnabeabiwpabekabd";
        String b = "ab";
        int times = times(a, b);
        System.out.println("times = " + times);
    }

    /**
     * 字符串出现的次数
     * 
     * @param str 字符串A
     * @param sub 字符串B
     * @return 返回字符串B在字符串A中出现的次数
     */
    public static int times(String str, String sub) {
        int count = 0; // 计数器
        int index; // 定义变量,记录字符串查找后的索引
        while ((index = str.indexOf(sub)) != -1) {
            // 计数器+1
            count++;
            // 截取字符串
            str = str.substring(index + sub.length());
        }
        return count;
    }
}

2 StringBuilder类

2.1 概述

  • 因为String对象是不可变的对象,虽然可以共享常量对象,但是对于频繁字符串的修改和拼接操作,效率极低。因此,JDK又在java.lang包中提供了可变字符序列StringBuilder和StringBuffer。

  • StringBuffer:线程安全。

  • StringBuilder:线程不安全。

img

2.2 常用方法

  • 拼接:
 public StringBuilder append(StringBuffer sb){}
public StringBuilder append(CharSequence s) {}
public StringBuilder append(CharSequence s, int start, int end) {}
public StringBuilder append(char[] str){}
public StringBuilder append(char[] str, int offset, int len) {}
public StringBuilder append(boolean b){}
public StringBuilder append(char c) {}
public StringBuilder append(int i) {}
public StringBuilder append(long lng) {}
public StringBuilder append(float f){}
public StringBuilder append(double d){}
  • 在index位置插入:
public StringBuilder insert(int index, char[] str, int offset,
                                int len){}
public StringBuilder insert(int offset, Object obj){}
public StringBuilder insert(int offset, String str) {}
public StringBuilder insert(int offset, char[] str){}
public StringBuilder insert(int dstOffset, CharSequence s) {}
public StringBuilder insert(int dstOffset, CharSequence s,
                                int start, int end){}
public StringBuilder insert(int offset, boolean b) {}
public StringBuilder insert(int offset, char c){}
public StringBuilder insert(int offset, int i){}
public StringBuilder insert(int offset, long l){}
public StringBuilder insert(int offset, float f){}
public StringBuilder insert(int offset, double d) {}
  • 删除[start,end)之间的字符:
public StringBuilder delete(int start, int end){}
  • 删除index位置字符:
public StringBuilder deleteCharAt(int index) {}
  • 替换index位置字符:
public void setCharAt(int index, char ch) {}
  • 反转:
public StringBuilder reverse(){}
  • 设置当前字符序列的长度为newLength:
public void setLength(int newLength){}
  • 替换[start,end)范围的字符序列为str:
public StringBuilder replace(int start, int end, String str){}
  • 查找字符串在字符序列中的位置:
public int indexOf(String str){}
public int indexOf(String str, int fromIndex){}
public int lastIndexOf(String str){}
public int lastIndexOf(String str, int fromIndex){}
  • 截取子串:
public String substring(int start){}
public String substring(int start, int end){}
  • 返回此序列中的数据的字符串表示形式:
public String toString(){}
  • 示例:
package top.open1024.stringbuilder.demo1;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 08:44
 */
public class Test {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("helloworld");
        sb.setLength(30);
        System.out.println("sb = " + sb); // sb = helloworld                    
    }
}
  • 示例:
package top.open1024.stringbuilder.demo2;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 09:20
 */
public class Test {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("helloworld");
        sb.reverse();
        System.out.println("sb = " + sb); // sb = dlrowolleh
    }
}
  • 示例:
package top.open1024.stringbuilder.demo3;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 09:21
 */
public class Test {
    public static void main(String[] args) {
        StringBuilder s = new StringBuilder("helloworld");
        s.delete(1, 3);
        s.deleteCharAt(4);
        System.out.println(s); // hlowrld
    }
}
  • 示例:
package top.open1024.stringbuilder.demo4;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 09:22
 */
public class Test {
    public static void main(String[] args) {
        StringBuilder s = new StringBuilder("helloworld");
        s.insert(5, "java");
        s.insert(5, "open1024");
        System.out.println(s);
    }
}
  • 示例:
package top.open1024.stringbuilder.demo5;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 09:23
 */
public class Test {
    public static void main(String[] args) {
        StringBuilder s = new StringBuilder();
        s.append("hello").append(true).append('a').append(12).append("open1024");
        System.out.println(s); // hellotruea12open1024
        System.out.println(s.length()); //15
    }
}

3 系统相关类

3.1 System类

3.1.1 概述

  • System类,定义在java.lang包中。

  • System类中定义了一些常用的类字段和方法,该类不能实例化。

3.1.2 常用方法

  • 返回当前系统时间距离1970-1-1 0:0:0的毫秒值:
public static native long currentTimeMillis();
  • 从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。常用于数组的插入和删除:
public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);
  • 运行垃圾回收器:
public static void gc(){}
  • 退出当前系统:
public static void exit(int status){}
  • 获取某个系统属性:
public static String getProperty(String key){}
  • 示例:
package top.open1024.system.demo1;

import java.util.Arrays;
import java.util.Enumeration;
import java.util.Properties;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 09:47
 */
public class Test {
    public static void main(String[] args) {
        // 返回当前系统时间距离1970-1-1 0:0:0的毫秒值:
        long current = System.currentTimeMillis();
        System.out.println("current = " + current);
        // 复制数组中的元素
        int[] arr = {1, 2, 3, 4, 5, 6};
        int[] target = new int[arr.length];
        System.arraycopy(arr, 0, target, 0, 2);
        System.out.println(Arrays.toString(target));
        // 获取所有系统属性
        Properties properties = System.getProperties();
        Enumeration<?> enumeration = properties.propertyNames();
        while (enumeration.hasMoreElements()) {
            Object o = enumeration.nextElement();
            System.out.println("o = " + o);
        }
        // 获取指定系统属性
        String os = System.getProperty("os.name");
        System.out.println("os = " + os);
    }
}

3.2 Runtime类

3.2.1 概述

  • 每个应用程序都有一个Runtime类的实例,使得应用程序能够和其运行的环境相连接。

  • 应用程序不能创建自己的Runtime实例,只能通过getRuntime()方法获取当前的运行时。

3.2.2 常用方法

  • 返回与当前 Java 应用程序相关的运行时对象:
public static Runtime getRuntime() {}
  • 返回 Java 虚拟机中的内存总量(此方法返回的值可能随时间的推移而变化,这取决于主机环境):
public native long totalMemory();
  • 返回 Java 虚拟机中的空闲内存量(调用 gc 方法可能导致 freeMemory 返回值的增加):
public native long freeMemory();
  • 示例:
package top.open1024.runtime.demo;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 10:29
 */
public class Test {
    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        Runtime runtime1 = Runtime.getRuntime();
        System.out.println(runtime == runtime1); // true

        long totalMemory = runtime.totalMemory();
        System.out.println("totalMemory = " + totalMemory); // 512753664
        long freeMemory = runtime.freeMemory();
        System.out.println("freeMemory = " + freeMemory); // 504700544
    }
}

4 数学相关的类

4.1 Math类

  • Math类位于java.lang包下,包含了用于执行基本数学运算的方法,如:初等指数、对数、平方根和三角函数等。类似这样的工具类,其所有的方法均为静态方法。

  • 绝对值:

public static double abs(double a){}
  • 返回大于等于参数的最小的整数:
public static double ceil(double a){}
  • 返回小于等于参数最大的整数:
public static double floor(double a)
  • 四舍五入方法 :
public static long round(double a){}
  • 返回a的b幂次方法:
public static double pow(double a,double b){}
  • 返回a的平方根:
public static double sqrt(double a){}
  • 返回[0,1)的随机值:
public static double random(){}
  • 返回圆周率:
public static final double PI
  • 返回x,y中的最大值:
public static double max(double x, double y){}
  • 返回x,y中的最小值:
public static double min(double x, double y){}
  • 示例:
package top.open1024.math.demo1;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 10:46
 */
public class Test {
    public static void main(String[] args) {
        double pi = Math.PI;
        System.out.println("pi = " + pi); // pi = 3.141592653589793
        double e = Math.E;
        System.out.println("e = " + e); // e = 2.718281828459045
        int abs = Math.abs(-1);
        System.out.println("abs = " + abs); // abs = 1
        // 向上取整:大于或等于参数的最小整数
        double ceil = Math.ceil(5.5);
        System.out.println("ceil = " + ceil); // ceil = 6.0
        ceil = Math.ceil(5);
        System.out.println("ceil = " + ceil); // ceil = 6.0
        ceil = Math.ceil(-5.5);
        System.out.println("ceil = " + ceil); // ceil = -5.0
        // 向下取整:小于或等于参数的最大整数
        double floor = Math.floor(5.5);
        System.out.println("floor = " + floor); // floor = 5.0
        floor = Math.floor(5);
        System.out.println("floor = " + floor); // floor = 5.0
        floor = Math.floor(-5.5);
        System.out.println("floor = " + floor); // floor = -6.0
        // 四舍五入
        long round = Math.round(5.1);
        System.out.println("round = " + round); // round = 5
        round = Math.round(5.65);
        System.out.println("round = " + round); // round = 6
        // 指数
        double pow = Math.pow(2, 2);
        System.out.println("pow = " + pow); // pow = 4.0
        // 平方根
        double sqrt = Math.sqrt(4);
        System.out.println("sqrt = " + sqrt); // sqrt = 2.0
        // 最大值
        int max = Math.max(1, 2);
        System.out.println("max = " + max); // max = 2
        // 最小值
        int min = Math.min(1, -2);
        System.out.println("min = " + min); // min = -2
    }
}

4.2 大数运算类

4.2.1 概述

  • 基本数据类型long、double都有其取值范围,一般遇到超过范围的数据,就需要用来大数运算类了。

  • java.math.BigInteger:大整数。

  • java.math.BigDecimal:大浮点。

4.2.2 BigInteger

  • 构造方法:
public BigInteger(String val){}
  • 加法:
public BigInteger add(BigInteger val){}
  • 减法:
public BigInteger subtract(BigInteger val) {}
  • 乘法:
public BigInteger multiply(BigInteger val){}
  • 除法:
public BigInteger divide(BigInteger val){}
  • 余数:
public BigInteger remainder(BigInteger val){}
  • 示例:
package top.open1024.big.demo1;

import java.math.BigInteger;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 11:00
 */
public class Test {
    public static void main(String[] args) {
        BigInteger b1 = new BigInteger("124");
        BigInteger b2 = new BigInteger("123");

        System.out.println("加法:" + b1.add(b2)); // 加法:247
        System.out.println("减法:" + b1.subtract(b2)); // 减法:1
        System.out.println("乘法:" + b1.multiply(b2)); // 乘法:15252
        System.out.println("除法:" + b1.divide(b2)); // 除法:1
        System.out.println("余数:" + b1.remainder(b2)); // 余数:1
    }
}

4.2.3 RoundingMode枚举类

  • UP:远离零方向舍入的舍入模式。

  • DOWN:向零方向舍入的舍入模式。

  • CEILING:向正无限大方向舍入的舍入模式。

  • FLOOR:向负无限大方向舍入的舍入模式。

  • HALF_UP:向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入。

  • HALF_DOWN:向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入。

  • HALF_EVEN:向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。

  • UNNECESSARY:用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入。

4.2.4 BigDecimal

  • 构造方法:
public BigDecimal(String val) {}
  • 加法:
public BigDecimal add(BigDecimal augend){}
  • 减法:
public BigDecimal subtract(BigDecimal subtrahend){}
  • 乘法:
public BigDecimal multiply(BigDecimal multiplicand) {}
  • 除法:
 public BigDecimal divide(BigDecimal divisor){}
public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode){}
public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode){}
  • 余数:
public BigDecimal remainder(BigDecimal divisor){}
  • 示例:
package top.open1024.big.demo2;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 14:16
 */
public class Test {
    public static void main(String[] args) {
        BigDecimal b1 = new BigDecimal("3.55");
        BigDecimal b2 = new BigDecimal("2.12");

        System.out.println("加法:" + b1.add(b2));
        System.out.println("减法:" + b1.subtract(b2));
        System.out.println("乘法:" + b1.multiply(b2));
        System.out.println("除法:" + b1.divide(b2, 2, RoundingMode.HALF_UP));
    }
}

5 数组的相关操作

5.1 数组的算法升华

5.1.1 数组的反转

  • 所谓的数组的反转:就是一开始是[1,2,3,4,5],经过数组的反转之后变成了[5,4,3,2,1]。

  • 其实,数组的反转就是对称位置的元素交换。

注意:数组的反转不是数组的倒叙遍历。

  • 方法一:

    • 借助一个新的数组。
    • 首尾对应位置交换。
    • 将新数组的地址赋值给旧数组。

img

  • 示例:
package top.open1024.array.demo1;

import java.util.Arrays;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 13:02
 */
public class Test {
    public static void main(String[] args) {
        // 原来的数组
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
        // 新的数组
        int[] newArr = new int[arr.length];
        // 给新的数组中插入值
        for (int i = 0; i < newArr.length; i++) {
            newArr[i] = arr[arr.length - 1 - i];
        }
        // 将原来的数组指向新的数组
        arr = newArr;
        // 打印输出
        System.out.println(Arrays.toString(arr));

    }
}
  • 方法二:数组对称位置的元素互换。

img

  • 示例:
package top.open1024.array.demo2;

import java.util.Arrays;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 13:08
 */
public class Test {
    public static void main(String[] args) {
        // 原来的数组
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
        // 数组反转
        for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        // 打印输出
        System.out.println(Arrays.toString(arr));
    }
}

5.1.2 数组的二分查找法

  • 数组的查找:判断一个元素是否存在于数组中。

  • 数组的基本查找法:遍历数组,判断即可。

  • 数组的二分查找法(折半查找法):要求数组元素必须支持比较大小,并且数组中的元素已经按大小排好序,然后对半查找。

img

  • 二分查找法的步骤:

    • ① 定义两个遍历,表示要查找的范围。默认min=0,max=最大索引。
    • ② 循环查找,但是min<=max。
    • ③ 计算出mid的值。
    • ④ 判断mid位置的元素是否为要查找的元素,如果是,直接返回的索引。
    • ⑤ 如果要查找的值在mid的左半边,那么min值不变,max=mid -1,继续下次循环查找。
    • ⑥ 如果要查找的值在mid的右半边,那么max值不变,min=mid +1,继续下次循环查找。
    • ⑦ 当min > max的时候,表示要查找的元素在数组中不存在,返回-1。
  • 示例:

package top.open1024.array.demo3;

/**
 * 基本查找法
 * 
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 13:39
 */
public class Test {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        int result = basicSearch(arr, 6);
        System.out.println("result = " + result);
    }

    /**
     * 
     * 数组的基本查找法
     * 
     * @param arr 数组
     * @param key 元素
     * @return 如果元素在数组中,则返回元素在数组中的索引位置;否则,返回-1
     */
    public static int basicSearch(int[] arr, int key) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == key) {
                return i;
            }
        }
        return -1;
    }
}
  • 示例:
package top.open1024.array.demo4;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 13:46
 */
public class Test {
    public static void main(String[] args) {
        int[] arr = {1, 5, 8, 12, 15};
        int result = binarySearch(arr, 9);
        System.out.println(result);
    }

    /**
     *
     * 数组的二分查找法
     *
     * @param arr 数组
     * @param key 元素
     * @return 如果元素在数组中,则返回元素在数组中的索引位置;否则,返回-1
     */
    public static int binarySearch(int[] arr, int key) {
        // 起始元素索引
        int min = 0;
        // 最后元素索引
        int max = arr.length - 1;
        while (min <= max) {
            // 计算中间元素的索引
            int mid = (min + max) / 2;
            // 如果中间元素就是需要查找的元素,直接返回索引
            if (key == arr[mid]) {
                return mid;
            }
            // 如果需要查找的元素比中间的元素大,那么min就是此时的mid+1,然后再计算mid
            if (key > arr[mid]) {
                min = mid + 1;
            }
            // 如果需要查找的元素比中间的元素小,那么max就是此时的mid-1,然后再计算mid
            if (key < arr[mid]) {
                max = mid - 1;
            }
        }
        return -1;
    }

}

5.1.3 冒泡排序

  • 排序:将一组数据按照固定的规则进行排列。

  • 冒泡排序:相邻的数据两两比较,小的放在前面,大的放在后面。

img

注意:

  • 如果有n个数据进行排序,总共需要比较n-1次。

  • 每一次比较完毕,下一次的比较就会少一个数据参与。

  • 示例:

package top.open1024.array.demo5;

import java.util.Arrays;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 15:14
 */
public class Test {
    public static void main(String[] args) {
        int[] arr = {3, 5, 2, 1, 4};
        System.out.println("排序之前:" + Arrays.toString(arr));
        sort(arr);
        System.out.println("排序之后:" + Arrays.toString(arr));
    }

    /**
     * 冒泡排序
     * 
     * @param arr 需要排序的数据
     */
    public static void sort(int[] arr) {
        // 外层循环控制的是次数,比数组的长度少1次
        for (int i = 0; i < arr.length - 1; i++) {
            // 内层循环就是实际循环比较的
            // -1 为了让数组不越界
            // -i 每一轮结束之后,就会少比一个数字
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

5.1.4 递归

  • 递归:以编程的角度来看,递归指的是方法定义中调用方法本身的现象。

  • 递归解决问题的思路:

    • ① 将一个复杂的问题层层转换为一个和原问题类似的规模较小的问题来求解。
    • ② 递归策略只需要少量的程序就可以描述出解题过程所需要的多次的重复计算。
  • 递归解决问题要遵循以下的规则:

    • ① 递归出口:否则会内存溢出。
    • ② 递归规则:和原问题相似的规模较小的问题。
  • 示例:

package top.open1024.array.demo7;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 15:57
 */
public class Test {
    public static void main(String[] args) {
        int sum = sum(100);
        System.out.println("sum = " + sum);
    }

    /**
     * 使用递归求和
     * 
     * @param n 整数
     * @return 和
     */
    public static int sum(int n) {
        if (n == 1) {
            return 1;
        }
        return n + sum(n - 1);
    }
}
  • 示例:
package top.open1024.array.demo8;

/**
 * 需求:用递归求5的阶乘,并将结果输出在控制台上。 
 * 分析: 
 * ① 阶乘:一个正整数的阶乘是所有小于以及等于该数的正整数的乘积,自然数n的阶乘写作n! 
 * ② 递归出口:1!=1 
 * ③ 递归规则:n!=n*(n-1)!
 * 
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 16:04
 */
public class Test {
    public static void main(String[] args) {
        int factorial = factorial(5);
        System.out.println("factorial = " + factorial);
    }

    public static int factorial(int n) {
        if (n == 1) {
            return 1;
        }
        return n * factorial(n - 1);
    }
}

5.1.5 数组的扩容

  • 当原来的数组长度不够的时候需要扩容,那么新建一个数组,并指定长度,其长度为原来的1.5倍或2倍等,然后将元素复制到新数组中,并将新添加的元素放到新数组的后面。

注意:

  • 新数组的长度定义多少合适,看实际情况,如果新增的元素个数确定,那么可以直接指定长度;如果新增的元素个数不确定,那么可以扩容为原来的1.5倍或2倍等。

  • 数组扩容太多会造成资源浪费,太少会导致频繁扩容,效率低下。

  • 示例:

package top.open1024.array.demo9;

import java.util.Arrays;

/**
 * 数组扩容
 * 
 * @author open1024
 * @version 1.0
 * @since 2021-09-25 16:31
 */
public class Test {
    public static void main(String[] args) {
        // 原数组
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
        // 扩容的数组
        int[] newArr = new int[arr.length * 2];
        // 将数组的数据拷贝到新数组中
        System.arraycopy(arr, 0, newArr, 0, arr.length);
        // 如果还需要使用arr,可以让arr指向新数组
        arr = newArr;
        // 添加新数据到arr的最后
        arr[8] = 10;
        // 遍历显示
        System.out.println(Arrays.toString(arr));
    }
}

5.1.6 数组元素的插入

  • 在原数组的某个index插入一个元素。

  • ① 如果原数组未满,那么直接将index后面的元素(包括index上的元素)移动到后面,然后将元素插入到index上。

  • ② 如果原数组已经满了,那么先扩容,然后重复①。

  • 示例:原数组未满

package top.open1024.array.demo10;

import java.util.Arrays;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 08:16
 */
public class Test {
    public static void main(String[] args) {
        // 原数组
        String[] str = new String[5];
        str[0] = "张三";
        str[1] = "李四";
        str[2] = "王五";
        // 现在想在index为1的位置上插入一个元素赵六
        // 将index为1的位置以及后面的元素依次移动1位
        System.arraycopy(str, 1, str, 2, 2);
        // 在index为1的位置插入元素
        str[1] = "赵六";
        // 打印输出
        System.out.println(Arrays.toString(str));
    }
}
  • 示例:原数组已满
package top.open1024.array.demo11;

import java.util.Arrays;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 08:22
 */
public class Test {
    public static void main(String[] args) {
        // 原数组
        String[] str = new String[3];
        str[0] = "张三";
        str[1] = "李四";
        str[2] = "王五";
        // 现在想在index为1的位置上插入一个元素赵六
        String[] dest = new String[4];
        // 扩容
        System.arraycopy(str, 0, dest, 0, str.length);
        // str指向新数组
        str = dest;
        // 将index为1的位置以及后面的元素依次移动1位
        System.arraycopy(str, 1, str, 2, 2);
        // 在index为1的位置插入元素
        str[1] = "赵六";
        // 打印输出
        System.out.println(Arrays.toString(str));
    }
}

5.1.7 数组元素的删除

  • 希望删除某个index上的元素,但是不希望数组中间空的元素,那么就将index后面的元素依次向前移动一位,最后一个元素置空即可。

  • 示例:

package top.open1024.array.demo12;

import java.util.Arrays;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 08:33
 */
public class Test {
    public static void main(String[] args) {
        String[] arr = {"张三", "李四", "王五"};
        // 希望删除index为1的元素,但是不希望index为1上为空
        System.arraycopy(arr, 2, arr, 1, 1);
        // 最后一个元素置空
        arr[2] = null;
        // 打印输出
        System.out.println(Arrays.toString(arr));
    }
}

5.2 数组工具类

  • java.util.Arrays数组工具类,提供了很多静态方法来对数组进行操作,而且如下的每一个方法都有重载,以下只列出int[]类型的,其他类型依次类推:

  • 二分查找法:要求数组有序,在数组中查找key是否存在,如果存在返回第一次找到的下标,不存在返回负数

public static int binarySearch(int[] a, int key) {}
  • 根据original原数组复制一个长度为newLength的新数组,并返回新数组:
public static int[] copyOf(int[] original, int newLength) {}
  • 复制original原数组的[from,to)构成新数组,并返回新数组:
public static int[] copyOfRange(int[] original, int from, int to){}
  • 比较两个数组的长度、元素是否完全相同:
public static boolean equals(int[] a, int[] a2) {}
  • 用val填充整个a数组:
public static void fill(int[] a, int val) {}
  • 将a数组[fromIndex,toIndex)部分填充为val :
public static void fill(int[] a, int fromIndex, int toIndex, int val){}
  • 将a数组按照从小到大进行排序:
public static void sort(int[] a) {}
  • 将a数组的[fromIndex, toIndex)部分按照升序排列:
public static void sort(int[] a, int fromIndex, int toIndex){}
  • 把a数组的元素,拼接为一个字符串,形式为:[元素1,元素2,元素3。。。]
public static String toString(int[] a) {}
  • 示例:
package top.open1024.array.demo13;

import java.util.Arrays;
import java.util.Random;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 08:41
 */
public class Test {
    public static void main(String[] args) {
        int[] arr = new int[5];
        // 打印数组,输出地址值
        System.out.println(arr); // [I@1540e19d
        // 数组内容转换为字符串
        System.out.println("arr数组的初始状态:" + Arrays.toString(arr)); // [0, 0, 0, 0, 0]
        // 向数组中填充数据
        Arrays.fill(arr, 3);
        System.out.println("arr数组的现在状态:" + Arrays.toString(arr)); // [3, 3, 3, 3, 3]
        // 向数组中赋值100以内的随机数
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(100);
        }
        System.out.println("arr数组的现在状态:" + Arrays.toString(arr)); // [3, 19, 72, 81, 66]
        // 根据original原数组复制一个长度为newLength的新数组,并返回新数组
        int[] arr2 = Arrays.copyOf(arr, 10);
        System.out.println("新数组:" + Arrays.toString(arr2)); // [93, 62, 31, 90, 88, 0, 0, 0, 0, 0]
        // 两个数组比较
        System.out.println(Arrays.equals(arr, arr2)); // false
        // 数组排序
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr)); // [17, 23, 32, 57, 98]
    }
}

6 日期时间API

6.1 JDk 8之前

6.1.1 Date类(★)

  • 表示当前的日期对象,精确到毫秒值。

  • 构造方法:

public Date() {}
public Date(long date) {}
  • 获取当前日期对应的毫秒值:
public long getTime() {}
  • 将毫秒值设置为日期:
public void setTime(long time){}
  • 示例:
package top.open1024.date.jdk7.demo1;

import java.util.Date;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 14:48
 */
public class Test {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println("date = " + date); // date = Sun Sep 26 14:48:52 CST 2021
        Date date1 = new Date(1632638970000L);
        System.out.println("date1 = " + date1); // date1 = Sun Sep 26 14:49:30 CST 2021

        long time = date.getTime();
        System.out.println("time = " + time); // time = 1632639026166

        date.setTime(1632638970000L);
        System.out.println("date = " + date); // date = Sun Sep 26 14:49:30 CST 2021
    }
}

6.1.2 Calendar

  • Calendar类是一个抽象类,它为特定瞬间与一组诸如 YEARMONTHDAY_OF_MONTHHOUR 等 [日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。Calendar 提供了一个类方法 getInstance,以获得此类型的一个通用的对象。

  • 获取Calendar实例:

public static Calendar getInstance() {}
  • 获取给定日历字段的值:
public int get(int field) {}
  • 修改日历的值
public void set(int field, int value) {}
  • 设置日历字段的偏移量:
public abstract void add(int field, int amount);
  • 示例:
package top.open1024.date.jdk7.demo2;

import java.util.Calendar;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 14:55
 */
public class Test {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        int milliSecond = calendar.get(Calendar.MILLISECOND);
        // 2021-9-26 15:14:6:16
        System.out.print(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second + ":" + milliSecond);
    }
}
  • 示例:
package top.open1024.date.jdk7.demo3;

import java.util.Calendar;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 15:39
 */
public class Test {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, 2022);
        System.out.println("calendar = " + calendar.get(Calendar.YEAR));
    }
}
  • 示例:
package top.open1024.date.jdk7.demo4;

import java.util.Calendar;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 15:43
 */
public class Test {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        // 日历向后,偏移180天
        calendar.add(Calendar.DAY_OF_MONTH, 180);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        int milliSecond = calendar.get(Calendar.MILLISECOND);
        System.out.print(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second + ":" + milliSecond);
    }
}

6.1.3 TimeZone

  • TimeZone表示时区。

  • 获取默认的时区:

public static TimeZone getDefault() {}
  • 获取所有的时区ID:
public static synchronized String[] getAvailableIDs() {}
  • 根据时区ID获取时区:
public static synchronized TimeZone getTimeZone(String ID)  {}
public static TimeZone getTimeZone(ZoneId zoneId) {}
  • 示例:
package top.open1024.date.jdk7.demo5;

import java.util.Arrays;
import java.util.TimeZone;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 15:46
 */
public class Test {
    public static void main(String[] args) {
        TimeZone aDefault = TimeZone.getDefault();
        System.out.println("aDefault = " + aDefault.getID()); // Asia/Shanghai
        String[] availableIDs = TimeZone.getAvailableIDs();
        System.out.println("availableIDs = " + Arrays.toString(availableIDs));
        TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai");
        System.out.println("timeZone = " + timeZone);
    }
}

6.1.4 SimpleDateFormat

  • SimpleDateFormat:日期格式化类。

  • 构造方法:

public SimpleDateFormat(String pattern) {}
  • 将日期对象格式化为字符串:
 public final String format(Date date) {}
  • 将字符串解析为日期对象:
public Date parse(String source) throws ParseException {}

img

  • 示例:
package top.open1024.date.jdk7.demo6;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 16:00
 */
public class Test {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        String format = sdf.format(date);
        System.out.println("format = " + format); // format = 2021-09-26 16:02:17
        Date parse = sdf.parse(format);
        System.out.println("parse = " + parse); // parse = Sun Sep 26 16:02:17 CST 2021
    }
}

6.2 JDK 8之后(★)

6.2.1 概述

  • Java 1.0 中包含了一个Date类,但是它的大多数方法已经在Java 1.1中引入Calendar类的时候被废弃了,而Calendar并不比Date类好多少,它们有如下的问题:

    • ① 可变性:像日期和时间这样的类对象应该是不可变的。Calendar类可以使用三种方法更改日历字段:set()add()roll()
    • ② 偏移性:Date中的年份是从1900年开始的,而月份是从0开始的。
    • ③ 格式化:格式化只对Date有效,Calendar则不行。
    • ④ 它们不是线程安全的,不能处理闰秒等。
  • 可以说,对日期和时间的操作一直是Java程序员最为痛苦的地方,没有之一。第三方库joda-time在JDK8出现之前的很长时间备受Java程序员欢迎。当然,JDK8吸收了joda-time的精华,以一个新的开始为Java创建优秀的API。

  • java.time – 包含值对象的基础包

  • java.time.chrono – 提供对不同的日历系统的访问。

  • java.time.format – 格式化和解析时间和日期。

  • java.time.temporal – 包括底层框架和扩展特性。

  • java.time.zone – 包含时区支持的类。

6.2.2 本地日期时间

  • LocalDate表示本地日期,LocalTime表示本地时间,而LocalDateTIme表示本地日期时间。

  • Instant表示瞬间(本地日期时间),精确到纳秒。

LocalDateTIme和Instant的区别:

  • Instant是带时区的(以UTC为准),用来替换以前的Date。

  • LocalDateTIme是不带时区(以本地时区为准)的,用来替换以前的Calendar。

  • 以LocalDateTime为例:

  • 获取对象:

    • ① 获取当前日期时间:
public static LocalDateTime now() {}
public static LocalDateTime now(ZoneId zone) {}
    • ② 根据指定日期时间创建对象:
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute) {}
  • 获取日期时间中的每个值:

    • 获取年份:
public int getYear() {}
    • 获取月份(1~12):
public int getMonthValue() {}
    • 获取月份的第几天(1~31):
public int getDayOfMonth() {}
    • 获取一年中的第几天(1~366):
public int getDayOfYear() {}
    • 获取星期:
public DayOfWeek getDayOfWeek() {}
    • 获取小时:
public int getHour() {}
    • 获取分钟:
public int getMinute() {}
    • 获取秒:
public int getSecond() {}
    • 获取纳秒:
public int getNano() {}
  • 转换:

    • 转换为LocalDate:
public LocalDate toLocalDate() {}
    • 转换为LocalTime:
public LocalTime toLocalTime()
  • with系列:

    • 修改年:
public LocalDateTime withYear(int year) {}
    • 修改月:
public LocalDateTime withMonth(int month) {}
    • 修改日期(一个月中的第几天):
public LocalDateTime withDayOfMonth(int dayOfMonth) {}
    • 修改日期(一年中的第几天):
public LocalDateTime withDayOfYear(int dayOfYear) {}
    • 修改小时:
public LocalDateTime withHour(int hour) {}
    • 修改分钟:
public LocalDateTime withMinute(int minute) {}
    • 修改秒:
public LocalDateTime withSecond(int second) {}
  • plus系列:如果参数为正整数,则为增加;否则,则为减少

    • 增加年或减少年:
public LocalDateTime plusYears(long years) {}
    • 增加或减少月:
public LocalDateTime plusMonths(long months) {}
    • 增加或减少日:
public LocalDateTime plusDays(long days) {}
    • 增加或减少小时:
public LocalDateTime plusHours(long hours) {}
    • 增加或减少分钟:
 public LocalDateTime plusMinutes(long minutes) {}
    • 增加或减少秒:
public LocalDateTime plusSeconds(long seconds) {}
    • 增加或减少周:
public LocalDateTime plusWeeks(long weeks) {}
  • minus系列:如果参数为正整数,则为减少;否则,则为增加

    • 减少或添加年:
public LocalDateTime minusYears(long years) {}
    • 减少或添加月:
public LocalDateTime minusMonths(long months) {}
    • 减少或添加日:
public LocalDateTime minusDays(long days) {}
    • 减少或添加小时:
public LocalDateTime minusHours(long hours) {}
    • 减少或添加分钟:
public LocalDateTime minusMinutes(long minutes) {}
    • 减少或添加秒:
public LocalDateTime minusSeconds(long seconds) {}
    • 减少或添加周:
public LocalDateTime minusWeeks(long weeks) {}
  • 比较两个时间的大小:

    • 是否在另一个时间之前:
public boolean isBefore(ChronoLocalDateTime<?> other) {}
    • 两个时间是否相等:
public boolean isEqual(ChronoLocalDateTime<?> other) {}
    • 是否在另一个时间之后:
public boolean isAfter(ChronoLocalDateTime<?> other) {}
  • 示例:
package top.open1024.date.jdk8.demo1;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 19:59
 */
public class Test {
    public static void main(String[] args) {
        LocalDate now = LocalDate.now();
        System.out.println("now = " + now); // now = 2021-09-26
        LocalTime now1 = LocalTime.now();
        System.out.println("now1 = " + now1); // now1 = 20:02:32.659
        LocalDateTime now2 = LocalDateTime.now();
        System.out.println("now2 = " + now2); // now2 = 2021-09-26T20:02:32.660
    }
}
  • 示例:
package top.open1024.date.jdk8.demo9;

import java.time.Instant;
import java.time.LocalDateTime;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-27 09:48
 */
public class Test {
    public static void main(String[] args) {
        Instant now = Instant.now(); 
        System.out.println("now = " + now); // now = 2021-09-27T01:54:39.351Z
        LocalDateTime now1 = LocalDateTime.now();
        System.out.println("now1 = " + now1); // now1 = 2021-09-27T09:54:39.401
    }
}
  • 示例:
package top.open1024.date.jdk8.demo3;

import java.time.LocalDateTime;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-26 20:10
 */
public class Test {
    public static void main(String[] args) {
        LocalDateTime of = LocalDateTime.of(2021, 11, 11, 11, 11, 11);
        System.out.println("of = " + of); // of = 2021-11-11T11:11:11
    }
}
  • 示例:
package top.open1024.date.jdk8.demo4;

import java.time.DayOfWeek;
import java.time.LocalDateTime;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-27 06:23
 */
public class Test {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        int year = now.getYear();
        System.out.println("获取年份:" + year);
        int monthValue = now.getMonthValue();
        System.out.println("获取月份:" + monthValue);
        int dayOfMonth = now.getDayOfMonth();
        System.out.println("获取天数:" + dayOfMonth);
        int dayOfYear = now.getDayOfYear();
        System.out.println("获取一年中的第" + dayOfYear + "天");
        DayOfWeek dayOfWeek = now.getDayOfWeek();
        System.out.println("获取星期" + dayOfWeek.getValue());
        int hour = now.getHour();
        System.out.println("获取小时:" + hour);
        int minute = now.getMinute();
        System.out.println("获取分钟:" + minute);
        int second = now.getSecond();
        System.out.println("获取秒:" + second);
        int nano = now.getNano();
        System.out.println("获取纳秒:" + nano);
    }
}
  • 示例:
package top.open1024.date.jdk8.demo5;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-27 08:17
 */
public class Test {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        // 转换为LocalDate
        LocalDate localDate = now.toLocalDate();
        System.out.println("localDate = " + localDate);
        // 转换为LocalTime
        LocalTime localTime = now.toLocalTime();
        System.out.println("localTime = " + localTime);
    }
}
  • 示例:
package top.open1024.date.jdk8.demo9;

import java.time.LocalDateTime;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-27 08:35
 */
public class Test {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.println("now = " + now); // now = 2021-09-27T08:41:04.197
        LocalDateTime localDateTime = now.withYear(2022);
        System.out.println("修改年 = " + localDateTime); // 修改年 = 2022-09-27T08:41:04.197
        LocalDateTime localDateTime1 = now.withMonth(10);
        System.out.println("修改月 = " + localDateTime1); // 修改月 = 2021-10-27T08:41:04.197
        LocalDateTime localDateTime2 = now.withDayOfMonth(28);
        System.out.println("修改日期(一个月中的第几天) = " + localDateTime2); // 修改日期(一个月中的第几天) = 2021-09-28T08:41:04.197
        LocalDateTime localDateTime3 = now.withDayOfYear(15);
        System.out.println("修改日期(一年中的第几天) = " + localDateTime3); // 修改日期(一年中的第几天) = 2021-01-15T08:41:04.197
        LocalDateTime localDateTime4 = now.withHour(10);
        System.out.println("修改小时 = " + localDateTime4); // 修改小时 = 2021-09-27T10:41:04.197
        LocalDateTime localDateTime5 = now.withMinute(15);
        System.out.println("修改分钟 = " + localDateTime5); // 修改分钟 = 2021-09-27T08:15:04.197
        LocalDateTime localDateTime6 = now.withSecond(10);
        System.out.println("修改秒 = " + localDateTime6); // 修改秒 = 2021-09-27T08:41:10.197
    }
}
  • 示例:
package top.open1024.date.jdk8.demo7;

import java.time.LocalDateTime;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-27 09:25
 */
public class Test {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.println("now = " + now); // now = 2021-09-27T09:30:21.527
        LocalDateTime localDateTime = now.plusYears(1);
        System.out.println("localDateTime = " + localDateTime); // localDateTime = 2022-09-27T09:30:21.527
        LocalDateTime localDateTime1 = now.plusYears(-1);
        System.out.println("localDateTime1 = " + localDateTime1); // localDateTime1 = 2020-09-27T09:30:21.527
        LocalDateTime localDateTime2 = now.plusMonths(1);
        System.out.println("localDateTime2 = " + localDateTime2); // localDateTime2 = 2021-10-27T09:30:21.527
        LocalDateTime localDateTime3 = now.plusDays(1);
        System.out.println("localDateTime3 = " + localDateTime3); // localDateTime3 = 2021-09-28T09:30:21.527
        LocalDateTime localDateTime4 = now.plusHours(1);
        System.out.println("localDateTime4 = " + localDateTime4); // localDateTime4 = 2021-09-27T10:30:21.527
        LocalDateTime localDateTime5 = now.plusMinutes(1);
        System.out.println("localDateTime5 = " + localDateTime5); // localDateTime5 = 2021-09-27T09:31:21.527
        LocalDateTime localDateTime6 = now.plusSeconds(1);
        System.out.println("localDateTime6 = " + localDateTime6); // localDateTime6 = 2021-09-27T09:30:22.527
        LocalDateTime localDateTime7 = now.plusWeeks(1);
        System.out.println("localDateTime7 = " + localDateTime7); // localDateTime7 = 2021-10-04T09:30:21.527
    }
}
  • 示例:
package top.open1024.date.jdk8.demo8;

import java.time.LocalDateTime;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-27 09:34
 */
public class Test {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.println("now = " + now); // now = 2021-09-27T09:39:01.406
        LocalDateTime localDateTime = now.minusYears(1);
        System.out.println("localDateTime = " + localDateTime); // localDateTime = 2020-09-27T09:39:01.406
        LocalDateTime localDateTime1 = now.minusMonths(1);
        System.out.println("localDateTime1 = " + localDateTime1); // localDateTime1 = 2021-08-27T09:39:01.406
        LocalDateTime localDateTime2 = now.minusDays(1);
        System.out.println("localDateTime2 = " + localDateTime2); // localDateTime2 = 2021-09-26T09:39:01.406
        LocalDateTime localDateTime3 = now.minusHours(1);
        System.out.println("localDateTime3 = " + localDateTime3); // localDateTime3 = 2021-09-27T08:39:01.406
        LocalDateTime localDateTime4 = now.minusMinutes(1);
        System.out.println("localDateTime4 = " + localDateTime4); // localDateTime4 = 2021-09-27T09:38:01.406
        LocalDateTime localDateTime5 = now.minusSeconds(1);
        System.out.println("localDateTime5 = " + localDateTime5); // localDateTime5 = 2021-09-27T09:39:00.406
        LocalDateTime localDateTime6 = now.minusWeeks(1);
        System.out.println("localDateTime6 = " + localDateTime6); // localDateTime6 = 2021-09-20T09:39:01.406
    }
}
  • 示例:
package top.open1024.date.jdk8.demo10;

import java.time.LocalDateTime;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-27 09:57
 */
public class Test {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime localDateTime = LocalDateTime.now().plusHours(1);
        System.out.println(now.isBefore(localDateTime)); // true
        System.out.println(now.isAfter(localDateTime)); // false
        System.out.println(now.isEqual(localDateTime)); // false
    }
}

6.2.3 指定时区日期时间ZonedDateTime

  • 常见的时区:

    • Asia/Shanghai。
    • UTC。
    • America/New_York。
  • 示例:

package top.open1024.date.jdk8.demo13;

import java.time.ZoneId;
import java.time.ZonedDateTime;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-27 13:46
 */
public class Test {
    public static void main(String[] args) {
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println("now = " + now); // 2021-09-27T13:46:28.445+08:00[Asia/Shanghai]
        ZonedDateTime now1 = ZonedDateTime.now(ZoneId.of("America/New_York"));
        System.out.println("now1 = " + now1); // 2021-09-27T01:47:18.093-04:00[America/New_York]
    }
}

6.2.4 持续日期/时间Period和Duration

  • Period:表示一段时间的区间,用来度量年、月、日和几天之间的时间值。

    • 获取Period对象:
public static Period between(LocalDate startDateInclusive, LocalDate endDateExclusive) {}
    • 获取区间相差的年份:
public int getYears() {}
    • 获取区间相差的月份:
public int getMonths() {}
    • 获取区间相差的天数:
public int getDays() {}
    • 获取区间相差总的月份:
public long toTotalMonths() {}
  • Duration:表示时间的区间,用来度量秒和纳秒之间的时间值。

    • 获取Duration对象:
public static Duration between(Temporal startInclusive, Temporal endExclusive) {}
    • 获取相差的天数:
public long toDays() {}
    • 获取相差的小时:
public long toHours() {}
    • 获取相差的分钟:
public long toMinutes() {}
    • 获取相差的毫秒:
public long toMillis() {}
    • 获取相差的纳秒:
public long toNanos() {}
  • 示例:
package top.open1024.date.jdk8.demo11;

import java.time.LocalDate;
import java.time.Period;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-27 11:23
 */
public class Test {
    public static void main(String[] args) {
        LocalDate now = LocalDate.now();
        System.out.println("now = " + now); // now = 2021-09-27
        LocalDate future = LocalDate.now().plusYears(1).plusDays(1).plusMonths(1);
        System.out.println("future = " + future); // future = 2022-10-28
        Period period = Period.between(now, future);
        int years = period.getYears();
        System.out.println("区间相差的年 = " + years); // 区间相差的年 = 1,其实就是 future 的year - now的year
        int months = period.getMonths();
        System.out.println("区间相差的月 = " + months); // 区间相差的月 = 1,其实就是 future 的month - now的month
        int days = period.getDays();
        System.out.println("区间相差的天 = " + days); // 区间相差的天 = 1,其实就是 future 的day - now的day
        long totalMonths = period.toTotalMonths();
        System.out.println("区间相差几个月 = " + totalMonths); // 区间相差几个月 = 13,实际相差的月
    }
}
  • 示例:
package top.open1024.date.jdk8.demo12;

import java.time.Duration;
import java.time.LocalDateTime;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-27 13:26
 */
public class Test {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.println("now = " + now); // now = 2021-09-27T13:29:56.105
        LocalDateTime feture = LocalDateTime.now().plusYears(1).plusMonths(1).plusDays(1).plusHours(1).plusMonths(1)
            .plusSeconds(1).plusNanos(1);
        System.out.println("feture = " + feture); // feture = 2022-11-28T14:29:57.106000001
        Duration duration = Duration.between(now, feture);
        long seconds = duration.getSeconds();
        System.out.println("seconds = " + seconds); // seconds = 36896401
        int nano = duration.getNano();
        System.out.println("nano = " + nano); // nano = 1000001
    }
}

6.2.5 日期时间格式化DateTimeFormat

  • 在JDK8中,使用DateTimeFormat类进行日期时间的格式化。

  • 获取DateTimeFormat:

public static DateTimeFormatter ofPattern(String pattern) {}
  • 格式化:
public String format(TemporalAccessor temporal) {}
  • 解析:
public TemporalAccessor parse(CharSequence text) {}
  • 示例:
package top.open1024.date.jdk8.demo14;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;

/**
 * @author open1024
 * @version 1.0
 * @since 2021-09-27 13:51
 */
public class Test {
    public static void main(String[] args) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format = df.format(LocalDateTime.now());
        System.out.println("format = " + format); // format = 2021-09-27 13:55:51
        TemporalAccessor parse = df.parse("2011-11-11 11:11:11");
        LocalDateTime from = LocalDateTime.from(parse);
        System.out.println("from = " + from); // from = 2011-11-11T11:11:11
    }
}
0

评论区