javaSE-day04(常用API三)

发布时间 2023-03-22 21:11:41作者: 王小子

1.为什么JDK8要新增日期类

/**
 *  目标:搞清楚为什么要用JDK 8开始新增的时间类。
 */
public class Test {
    public static void main(String[] args) {
        // 传统的时间类(Date、SimpleDateFormat、Calendar)存在如下问题:
        // 1、设计不合理,使用不方便,很多都被淘汰了。
        Date d = new Date();
        //System.out.println(d.getYear() + 1900);

        Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        System.out.println(year);

        // 2、都是可变对象,修改后会丢失最开始的时间信息。

        // 3、线程不安全。

        // 4、不能精确到纳秒,只能精确到毫秒。
        // 1秒 = 1000毫秒
        // 1毫秒 = 1000微妙
        // 1微妙 = 1000纳秒
    }
}

image

2.JDK8日期、时间、日期时间

JDK8新增的日期类分得更细致一些,比如表示年月日用LocalDate类、表示时间秒用LocalTime类、而表示年月日时分秒用LocalDateTime类等;除了这些类还提供了对时区、时间间隔进行操作的类等。它们几乎把对日期/时间的所有操作都通过了API方法,用起来特别方便。
image
先学习表示日期、时间、日期时间的类;有LocalDate、LocalTime、以及LocalDateTime类。仔细阅读代码,你会发现这三个类的用法套路都是一样的。

  • LocalDate类的基本使用

      public class Test1_LocalDate {
      	public static void main(String[] args) {
      		// 0、获取本地日期对象(不可变对象)
      		LocalDate ld = LocalDate.now(); // 年 月 日
      		System.out.println(ld);
    
          // 1、获取日期对象中的信息
          int year = ld.getYear(); // 年
          int month = ld.getMonthValue(); // 月(1-12)
          int day = ld.getDayOfMonth(); // 日
          int dayOfYear = ld.getDayOfYear();  // 一年中的第几天
          int dayOfWeek = ld.getDayOfWeek().getValue(); // 星期几
          System.out.println(year);
          System.out.println(day);
          System.out.println(dayOfWeek);
    
          // 2、直接修改某个信息: withYear、withMonth、withDayOfMonth、withDayOfYear
          LocalDate ld2 = ld.withYear(2099);
          LocalDate ld3 = ld.withMonth(12);
          System.out.println(ld2);
          System.out.println(ld3);
          System.out.println(ld);
    
          // 3、把某个信息加多少: plusYears、plusMonths、plusDays、plusWeeks
          LocalDate ld4 = ld.plusYears(2);
          LocalDate ld5 = ld.plusMonths(2);
    
          // 4、把某个信息减多少:minusYears、minusMonths、minusDays、minusWeeks
          LocalDate ld6 = ld.minusYears(2);
          LocalDate ld7 = ld.minusMonths(2);
    
          // 5、获取指定日期的LocalDate对象: public static LocalDate of(int year, int month, int dayOfMonth)
          LocalDate ld8 = LocalDate.of(2099, 12, 12);
          LocalDate ld9 = LocalDate.of(2099, 12, 12);
    
          // 6、判断2个日期对象,是否相等,在前还是在后: equals isBefore isAfter
          System.out.println(ld8.equals(ld9));// true
          System.out.println(ld8.isAfter(ld)); // true
          System.out.println(ld8.isBefore(ld)); // false
      }
    

    }

  • LocalTime类的基本使用

      public class Test2_LocalTime {
      	public static void main(String[] args) {
      		// 0、获取本地时间对象
      		LocalTime lt = LocalTime.now(); // 时 分 秒 纳秒 不可变的
      		System.out.println(lt);
    
          // 1、获取时间中的信息
          int hour = lt.getHour(); //时
          int minute = lt.getMinute(); //分
          int second = lt.getSecond(); //秒
          int nano = lt.getNano(); //纳秒
    
          // 2、修改时间:withHour、withMinute、withSecond、withNano
          LocalTime lt3 = lt.withHour(10);
          LocalTime lt4 = lt.withMinute(10);
          LocalTime lt5 = lt.withSecond(10);
          LocalTime lt6 = lt.withNano(10);
    
          // 3、加多少:plusHours、plusMinutes、plusSeconds、plusNanos
          LocalTime lt7 = lt.plusHours(10);
          LocalTime lt8 = lt.plusMinutes(10);
          LocalTime lt9 = lt.plusSeconds(10);
          LocalTime lt10 = lt.plusNanos(10);
    
          // 4、减多少:minusHours、minusMinutes、minusSeconds、minusNanos
          LocalTime lt11 = lt.minusHours(10);
          LocalTime lt12 = lt.minusMinutes(10);
          LocalTime lt13 = lt.minusSeconds(10);
          LocalTime lt14 = lt.minusNanos(10);
    
          // 5、获取指定时间的LocalTime对象:
          // public static LocalTime of(int hour, int minute, int second)
          LocalTime lt15 = LocalTime.of(12, 12, 12);
          LocalTime lt16 = LocalTime.of(12, 12, 12);
    
          // 6、判断2个时间对象,是否相等,在前还是在后: equals isBefore isAfter
          System.out.println(lt15.equals(lt16)); // true
          System.out.println(lt15.isAfter(lt)); // false
          System.out.println(lt15.isBefore(lt)); // true
    
      }
    

    }

  • LocalDateTime类的基本使用

      public class Test3_LocalDateTime {
      	public static void main(String[] args) {
      		// 0、获取本地日期和时间对象。
      		LocalDateTime ldt = LocalDateTime.now(); // 年 月 日 时 分 秒 纳秒
      		System.out.println(ldt);
    
          // 1、可以获取日期和时间的全部信息
          int year = ldt.getYear(); // 年
          int month = ldt.getMonthValue(); // 月
          int day = ldt.getDayOfMonth(); // 日
          int dayOfYear = ldt.getDayOfYear();  // 一年中的第几天
          int dayOfWeek = ldt.getDayOfWeek().getValue();  // 获取是周几
          int hour = ldt.getHour(); //时
          int minute = ldt.getMinute(); //分
          int second = ldt.getSecond(); //秒
          int nano = ldt.getNano(); //纳秒
    
          // 2、修改时间信息:
          // withYear withMonth withDayOfMonth withDayOfYear withHour
          // withMinute withSecond withNano
          LocalDateTime ldt2 = ldt.withYear(2029);
          LocalDateTime ldt3 = ldt.withMinute(59);
    
          // 3、加多少:
          // plusYears  plusMonths plusDays plusWeeks plusHours plusMinutes plusSeconds plusNanos
          LocalDateTime ldt4 = ldt.plusYears(2);
          LocalDateTime ldt5 = ldt.plusMinutes(3);
    
          // 4、减多少:
          // minusDays minusYears minusMonths minusWeeks minusHours minusMinutes minusSeconds minusNanos
          LocalDateTime ldt6 = ldt.minusYears(2);
          LocalDateTime ldt7 = ldt.minusMinutes(3);
    
    
          // 5、获取指定日期和时间的LocalDateTime对象:
          // public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour,
          //                                  int minute, int second, int nanoOfSecond)
          LocalDateTime ldt8 = LocalDateTime.of(2029, 12, 12, 12, 12, 12, 1222);
          LocalDateTime ldt9 = LocalDateTime.of(2029, 12, 12, 12, 12, 12, 1222);
    
          // 6、 判断2个日期、时间对象,是否相等,在前还是在后: equals、isBefore、isAfter
          System.out.println(ldt9.equals(ldt8));
          System.out.println(ldt9.isAfter(ldt));
          System.out.println(ldt9.isBefore(ldt));
    
          // 7、可以把LocalDateTime转换成LocalDate和LocalTime
          // public LocalDate toLocalDate()
          // public LocalTime toLocalTime()
          // public static LocalDateTime of(LocalDate date, LocalTime time)
          LocalDate ld = ldt.toLocalDate();
          LocalTime lt = ldt.toLocalTime();
          LocalDateTime ldt10 = LocalDateTime.of(ld, lt);
       }
      }
    

3.JDK8日期(时区)

接着,我们学习代表时区的两个类。由于世界各个国家与地区的经度不同,各地区的时间也有所不同,因此会划分为不同的时区。每一个时区的时间也不太一样。

image

public class Test4_ZoneId_ZonedDateTime {
    public static void main(String[] args) {
        // 目标:了解时区和带时区的时间。
        // 1、ZoneId的常见方法:
        // public static ZoneId systemDefault(): 获取系统默认的时区
        ZoneId zoneId = ZoneId.systemDefault();
        System.out.println(zoneId.getId());
        System.out.println(zoneId);

        // public static Set<String> getAvailableZoneIds(): 获取Java支持的全部时区Id
        System.out.println(ZoneId.getAvailableZoneIds());

        // public static ZoneId of(String zoneId) : 把某个时区id封装成ZoneId对象。
        ZoneId zoneId1 = ZoneId.of("America/New_York");

        // 2、ZonedDateTime:带时区的时间。
        // public static ZonedDateTime now(ZoneId zone): 获取某个时区的ZonedDateTime对象。
        ZonedDateTime now = ZonedDateTime.now(zoneId1);
        System.out.println(now);

        // 世界标准时间了
        ZonedDateTime now1 = ZonedDateTime.now(Clock.systemUTC());
        System.out.println(now1);

        // public static ZonedDateTime now():获取系统默认时区的ZonedDateTime对象
        ZonedDateTime now2 = ZonedDateTime.now();
        System.out.println(now2);

        // Calendar instance = Calendar.getInstance(TimeZone.getTimeZone(zoneId1));
    }
}

4.JDK8日期(Instant类)

Instant这个类。通过获取Instant的对象可以拿到此刻的时间,该时间由两部分组成:从1970-01-01 00:00:00 开始走到此刻的总秒数+不够1秒的纳秒数。
image

该类提供的方法如下图所示,可以用来获取当前时间,也可以对时间进行加、减、获取等操作。

image

作用:可以用来记录代码的执行时间,或用于记录用户操作某个事件的时间点。

/**
 * 目标:掌握Instant的使用。
 */
public class Test5_Instant {
    public static void main(String[] args) {
       // 1、创建Instant的对象,获取此刻时间信息
        Instant now = Instant.now(); // 不可变对象

        // 2、获取总秒数
        long second = now.getEpochSecond();
        System.out.println(second);

        // 3、不够1秒的纳秒数
        int nano = now.getNano();
        System.out.println(nano);

        System.out.println(now);

        Instant instant = now.plusNanos(111);

        // Instant对象的作用:做代码的性能分析,或者记录用户的操作时间点
        Instant now1 = Instant.now();
        // 代码执行。。。。
        Instant now2 = Instant.now();

        LocalDateTime l = LocalDateTime.now();
    }
}

5.JDK8日期(格式化器)

新增的日期格式化类,叫DateTimeFormater。它可以从来对日期进行格式化和解析。它代替了原来的SimpleDateFormat类。
image
需要用到的方法,如下图所示
image
用代码来演示一下

/**
 *  目标:掌握JDK 8新增的DateTimeFormatter格式化器的用法。
 */
public class Test6_DateTimeFormatter {
    public static void main(String[] args) {
        // 1、创建一个日期时间格式化器对象出来。
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");

        // 2、对时间进行格式化
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);

        String rs = formatter.format(now); // 正向格式化
        System.out.println(rs);

        // 3、格式化时间,其实还有一种方案。
        String rs2 = now.format(formatter); // 反向格式化
        System.out.println(rs2);

        // 4、解析时间:解析时间一般使用LocalDateTime提供的解析方法来解析。
        String dateStr = "2029年12月12日 12:12:11";
        LocalDateTime ldt = LocalDateTime.parse(dateStr, formatter);
        System.out.println(ldt);
    }
}

6.JDK8日期(Period类)

JDK8还补充了两个类,一个叫Period类、一个叫Duration类;这两个类可以用来对计算两个时间点的时间间隔。
其中Period用来计算日期间隔(年、月、日),Duration用来计算时间间隔(时、分、秒、纳秒)
image

先来演示Period类的用法,它的方法如下图所示。可以用来计算两个日期之间相隔的年、相隔的月、相隔的日。只能两个计算LocalDate对象之间的间隔

image

/**
 * 目标:掌握Period的作用:计算机两个日期相差的年数,月数、天数。
 */
public class Test7_Period {
    public static void main(String[] args) {
        LocalDate start = LocalDate.of(2029, 8, 10);
        LocalDate end = LocalDate.of(2029, 12, 15);

        // 1、创建Period对象,封装两个日期对象。
        Period period = Period.between(start, end);

        // 2、通过period对象获取两个日期对象相差的信息。
        System.out.println(period.getYears());
        System.out.println(period.getMonths());
        System.out.println(period.getDays());
    }
}

7.JDK8日期(Duration类)

Duration类。它是用来表示两个时间对象的时间间隔。可以用于计算两个时间对象相差的天数、小时数、分数、秒数、纳秒数;支持LocalTime、LocalDateTime、Instant等时间
image

public class Test8_Duration {
    public static void main(String[] args) {
        LocalDateTime start = LocalDateTime.of(2025, 11, 11, 11, 10, 10);
        LocalDateTime end = LocalDateTime.of(2025, 11, 11, 11, 11, 11);
        // 1、得到Duration对象
        Duration duration = Duration.between(start, end);

        // 2、获取两个时间对象间隔的信息
        System.out.println(duration.toDays());// 间隔多少天
        System.out.println(duration.toHours());// 间隔多少小时
        System.out.println(duration.toMinutes());// 间隔多少分
        System.out.println(duration.toSeconds());// 间隔多少秒
        System.out.println(duration.toMillis());// 间隔多少毫秒
        System.out.println(duration.toNanos());// 间隔多少纳秒

    }
}

8.Arrays类

Arrays基本使用
Arrays是干什么用的,Arrays是操作数组的工具类,它可以很方便的对数组中的元素进行遍历、拷贝、排序等操作。

下面我们用代码来演示一下:遍历、拷贝、排序等操作。需要用到的方法如下

image

/**
 * 目标:掌握Arrays类的常用方法。
 */
public class ArraysTest1 {
    public static void main(String[] args) {
        // 1、public static String toString(类型[] arr): 返回数组的内容
        int[] arr = {10, 20, 30, 40, 50, 60};
        System.out.println(Arrays.toString(arr));

        // 2、public static 类型[] copyOfRange(类型[] arr, 起始索引, 结束索引) :拷贝数组(指定范围,包前不包后)
        int[] arr2 = Arrays.copyOfRange(arr, 1, 4);
        System.out.println(Arrays.toString(arr2));

        // 3、public static copyOf(类型[] arr, int newLength):拷贝数组,可以指定新数组的长度。
        int[] arr3 = Arrays.copyOf(arr, 10);
        System.out.println(Arrays.toString(arr3));

        // 4、public static setAll(double[] array, IntToDoubleFunction generator):把数组中的原数据改为新数据又存进去。
        double[] prices = {99.8, 128, 100};
        //                  0     1    2
        // 把所有的价格都打八折,然后又存进去。
        Arrays.setAll(prices, new IntToDoubleFunction() {
            @Override
            public double applyAsDouble(int value) {
                // value = 0  1  2
                return prices[value] * 0.8;
            }
        });
        System.out.println(Arrays.toString(prices));

        // 5、public static void sort(类型[] arr):对数组进行排序(默认是升序排序)
        Arrays.sort(prices);
        System.out.println(Arrays.toString(prices));
    }
}

Arrays操作对象数组
使用Arrays操作数组时,数组中存储存储的元素是int类型、double类型,是可以直接排序的,而且默认是升序排列。

如果数组中存储的元素类型是自定义的对象,如何排序呢?接下来,我们就学习一下Arrays如何对对象数组进行排序。

首先我们要准备一个Student类,代码如下:

public class Student implements Comparable<Student>{
    private String name;
    private double height;
    private int age;
	
    public Student(String name, double height, int age) {
        this.name = name;
        this.height = height;
        this.age = age;
    }

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

然后再写一个测试类,往数组中存储4个学生对象,代码如下。此时,运行代码你会发现是会报错的。

public class ArraysTest2 {
    public static void main(String[] args) {
        // 目标:掌握如何对数组中的对象进行排序。
        Student[] students = new Student[4];
        students[0] = new Student("蜘蛛精", 169.5, 23);
        students[1] = new Student("紫霞", 163.8, 26);
        students[2] = new Student("紫霞", 163.8, 26);
        students[3] = new Student("至尊宝", 167.5, 24);

        // 1、public static void sort(类型[] arr):对数组进行排序。
		Arrays.sort(students);
		System.out.println(Arrays.toString(students));
    }
}

image

上面的代码为什么会报错呢?因为Arrays根本就不知道按照什么规则进行排序。为了让Arrays知道按照什么规则排序,我们有如下的两种办法。

  • 排序方式1:让Student类实现Comparable接口,同时重写compareTo方法。Arrays的sort方法底层会根据compareTo方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。代码如下:

      public class Student implements Comparable<Student>{
      	private String name;
      	private double height;
      	private int age;
    
      	//...get、set、空参数构造方法、有参数构造方法...自己补全
    
      	// 指定比较规则
      	// this  o
      	@Override
      	public int compareTo(Student o) {
      		// 约定1:认为左边对象 大于 右边对象 请您返回正整数
      		// 约定2:认为左边对象 小于 右边对象 请您返回负整数
      		// 约定3:认为左边对象 等于 右边对象 请您一定返回0
      		/* if(this.age > o.age){
      			return 1;
      		}else if(this.age < o.age){
      			return -1;
      		}
      		return 0;*/
    
          //上面的if语句,也可以简化为下面的一行代码
          return this.age - o.age; // 按照年龄升序排列
          // return o.age - this.age; // 按照年龄降序排列
      }
      
      @Override
      public String toString() {
          return "Student{" +
                  "name='" + name + '\'' +
                  ", height=" + height +
                  ", age=" + age +
                  '}';
      }
    

    }

  • 排序方式2:在调用Arrays.sort(数组,Comparator比较器);时,除了传递数组之外,传递一个Comparator比较器对象。Arrays的sort方法底层会根据Comparator比较器对象的compare方法方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。代码如下

      public class ArraysTest2 {
      	public static void main(String[] args) {
      		// 目标:掌握如何对数组中的对象进行排序。
      		Student[] students = new Student[4];
      		students[0] = new Student("蜘蛛精", 169.5, 23);
      		students[1] = new Student("紫霞", 163.8, 26);
      		students[2] = new Student("紫霞", 163.8, 26);
      		students[3] = new Student("至尊宝", 167.5, 24);
    
      	// 2、public static <T> void sort(T[] arr, Comparator<? super T> c)
          // 参数一:需要排序的数组
          // 参数二:Comparator比较器对象(用来制定对象的比较规则)
          Arrays.sort(students, new Comparator<Student>() {
              @Override
              public int compare(Student o1, Student o2) {
                  // 制定比较规则了:左边对象 o1   右边对象 o2
                  // 约定1:认为左边对象 大于 右边对象 请您返回正整数
                  // 约定2:认为左边对象 小于 右边对象 请您返回负整数
                  // 约定3:认为左边对象 等于 右边对象 请您一定返回0
      //                if(o1.getHeight() > o2.getHeight()){
      //                    return 1;
      //                }else if(o1.getHeight() < o2.getHeight()){
      //                    return -1;
      //                }
      //                return 0; // 升序
      				 return Double.compare(o1.getHeight(), o2.getHeight()); // 升序
      				// return Double.compare(o2.getHeight(), o1.getHeight()); // 降序
      			}
      		});
      		System.out.println(Arrays.toString(students));
      	}
      }