九. 常用类(2)—— 时间相关的类及其他

三. 日期时间API

3.1 System类中获取时间戳的方法

九. 常用类(2)—— 时间相关的类及其他_第1张图片

// 1. System类中的public static long currentTimeMillis()返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
    //计算世界时间的主要标准有:
    //UTC(Coordinated Universal Time)
    //GMT(Greenwich Mean Time)
    //CST(Central Standard Time)
    @Test
    public void test(){
        long time = System.currentTimeMillis();
        // 返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
        System.out.println(time); // 称为时间戳  如参与到订单里
    }

3.2 java中两个Date类的使用

java.util.Date类

表示特定的瞬间,精确到毫秒

构造器:

  • Date():使用无参的构造器创建的对象可以获取本地当前时间。
  • Date(long time)

常用方法

  • getTime():返回自1970年1月1日00:00:00GMT以来此Date对象表示的毫秒数。
  • toString():把此Date对象转换为以下形式的String:dow mon dd hh::mm::ss zzz yyyy其中:dow是一周中的某一天(Sun,Mon,Tue,Wed, Thu, Fri, Sat),zzz是时间标准
/*
    java.utl.Date类
            | --- java.sql.Date类  (子父类的关系) 对应的是数据库中的日期类对象
    1. 两个构造器的使用
    2. 两个方法的使用
        >toString():显示当前的年月日时分秒
        >getTime():获取时间戳毫秒数
    3. java.sql.Date
    >实例化:java.sql.Date date3 = new java.sql.Date(long time)
    >如何将java.util.Date对象转换为java.sql.Date类对象

     */
    @Test
    public  void test2(){
        // 构造器1:空参Date()
        Date date1 = new Date(); // 创建当前时间Date对象
        System.out.println(date1.toString());// Tue Apr 27 16:01:32 CST 2021

        System.out.println(date1.getTime()); //1619510560440返回距1970年以来的时间差

        // 构造器2:创建指定毫秒数的Date对象
        Date date2 = new Date(1619510560440L);
        System.out.println(date2.toString());  // Tue Apr 27 16:02:40 CST 2021

        java.sql.Date date3 = new java.sql.Date(1619510560440L);
        System.out.println(date3);  // 2021-04-27

        //情况1
//        Date date4 = new java.sql.Date(1619510560440L);
//        java.sql.Date date5 = (java.sql.Date) date4;
        //情况2
        Date date6 = new Date();
        //java.sql.Date date7 = (java.sql.Date) date6; // 运行报错,new的父类不能强转为子类
        java.sql.Date date7 = new java.sql.Date(date6.getTime());
    }

3.3 回顾字符串,String类

jdk6中,常量池放在方法区(永久区)中;

jdk7,常量池放在了堆中;

jdk8,常量池放在了元空间。(永久区改名)

四. String 课后算法题目2

题目一已在博客上…

/*
获取一个字符串在另一个字符串中出现的次数
比如:获取"ab"在"abkkcadkabkebfkabkskab"中出现的次数
思路1:indexOf获取第一次出现的下标,count++;然后下标+2,再次进行匹配
 */

public class StringDemo01 {

    public int getCount(String mainStr, String subStr){
        int mainLength = mainStr.length();
        int subLength = subStr.length();
        int count = 0;
        int index = 0;
        if (mainLength >= subLength){
            //方法一
//            while ((index = mainStr.indexOf(subStr)) != -1){
//                count++;
//                //截取子串作为新的主串 ,这里不断修改mainStr,效率稍低
//                mainStr = mainStr.substring(index + subStr.length());
//            }
            //方式二,对方式一的改进,没有不断创建字符串,只在原先的主串上查找
            while((index = mainStr.indexOf(subStr, index)) != -1){
                count ++;
                index += subLength;
            }
            return count;
        }else{

            return 0;
        }
    }

    @Test
    public void test(){
        String mainStr = "abkkcadkabkebfkabkskab";
        String subStr = "ab";
        System.out.println(getCount(mainStr, subStr));// 4
    }
}

五. String课后算法题目3

获取两个字符串中最大相同子串。比如: str1 = "abcwerthelloyuiodef“;str2 = “cvhellobnm” 提示:将短的那个串进行长度依次递减的子串与较长的串比较。

/*
获取两个字符串中最大相同子串。比如:
str1 = "abcwerthelloyuiodef“;str2 = "cvhellobnm"
提示:将短的那个串进行长度依次递减的子串与较长的串比较。
 */
public class StringDemo02 {
    public String getMaxSameString(String str1, String str2){
        if (str1 != null && str2 != null){
            //1.拿短的匹配长的
            String maxStr = (str1.length() >= str2.length())? str1 : str2;
            String minStr = (str1.length() < str2.length())? str1 : str2;
            int length = minStr.length();  // 对于小的串的外层的几大轮数
            for (int i = 0; i < length; i++){

                for (int x = 0,y = length - i; y <= length; x++,y++){
                    String subStr = minStr.substring(x, y);
                    if (maxStr.contains(subStr)){
                        return subStr;
                    }
                }
            }
        }
        return null;
    }
    @Test
    public void test(){
        String str1 = "abcwerthelloyuiodef";
        String str2 = "cvhellobnm";
        System.out.println(getMaxSameString(str1, str2));// hello
    }
}
本题解法的前提是两个字符串只有一个最大相同字串

六. String课后算法题目三拓展

str1 = "abcwerthello1yuiodefabcdef";str2 = "cvhello1bnmabcdef"

出现两个最大相同字串的情况,哪个最先出现就是哪个。

出现多个时,采用集合存储,无需确定长度.

这里没用集合时采用如下处理:

如果存在多个长度相同的最大相同子串,此时先返回String[],后面可以用集合中的ArrayList替换,较方便

//如果存在多个长度相同的最大相同子串
    //此时先返回String[],后面可以用集合中的ArrayList替换,较方便
    public String[] getMaxSameString1(String str1, String str2){
        if (str1 != null && str2 != null){
            StringBuffer sBuffer = new StringBuffer();
            String maxStr = (str1.length() >= str2.length())? str1 : str2;
            String minStr = (str1.length() < str2.length())? str1 : str2;
            int length = minStr.length();  // 对于小的串的外层的几大轮数
            for (int i = 0; i < length; i++){

                for (int x = 0,y = length - i; y <= length; x++,y++){
                    String subStr = minStr.substring(x, y);
                    if (maxStr.contains(subStr)){
                        sBuffer.append(subStr + ",");
                    }
                }
                System.out.println(sBuffer);
                if (sBuffer.length() != 0){//一旦找到了就退出,不再遍历其他
                    break;
                }
            }
            String[] split = sBuffer.toString().replaceAll(",$", "").split("\\,");
            return split;
        }
        return null;
    }
@Test
    public void testGetMaxSameString(){
        String str1 = "abcwerthelloyuiodef";
        String str2 = "cvhellobnm";
        String[] maxSameStrings = getMaxSameString1(str1, str2);
        System.out.println(Arrays.toString(maxSameStrings));
    }

七. IDEA中Debug调试

public class IDEADebug {
    @Test
    public void testStringBuffer(){
        String str = null;
        StringBuffer sb = new StringBuffer();
        sb.append(str); // "null"  且没有抛异常

        System.out.println(sb.length());  // 4

        System.out.println(sb); // "null"

        StringBuffer sb1 = new StringBuffer(str); //抛异常
        System.out.println(sb1); //执行不到
    }
}

八. SimpleDateFormat的使用

JDK8之前的时间日期API

/*
    SimpleDateFormat的使用:SimpleDateFormat对日期和Date类的格式化和解析
    1. 两个操作:
    1.1 格式化:日期 --> 字符串
    1.2 解析: 格式化的逆过程  字符串 --> 日期

    2. SimpleDateFormat的实例化
     */
    @Test
    public void testSimpleDateFormat() throws ParseException {
        //实例化,使用默认构造器
        SimpleDateFormat sdf = new SimpleDateFormat();

        //格式化:日期 --> 字符串
        Date date = new Date();
        System.out.println(date);

        String format = sdf.format(date);
        System.out.println(format);  // 2021/5/10 下午3:30

        //解析:格式化的逆过程  字符串 --> 日期
        String str = "19/08/05 上午11:55";  //格式有了要求,否则无法识别,会抛异常
        Date date1 = sdf.parse(str);
        System.out.println(date1);   // Mon Aug 05 11:55:00 CST 2019

//*****************按照指定方式格式化和解析************************//
        System.out.println("*******************");

        //带参构造器
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa");
        String format1 = sdf1.format(date);
        System.out.println(format1); //  02021.五月.10 公元 03:30 下午

        // 开发中常用时间字符
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//HH是24小时计时制
        String format2 = sdf2.format(date);
        System.out.println(format2);  // 2021-05-10 03:33:57
        //解析
        System.out.println("******解析******");
        Date date2 = sdf1.parse(format1);
        System.out.println(date2);
        Date date3 = sdf2.parse(format2);
        System.out.println(date3);
    }

九. 课后练习1

@Test
    public void testExer() throws ParseException {
        String birth = "2020-09-08";
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
        Date date = sdf1.parse(birth);
        java.sql.Date birthDate = new java.sql.Date(date.getTime());
        System.out.println(birthDate);
    }

十. 课后练习2

/*
练习二:"三天打鱼两天晒网"   1990-01-01  开始按照这个逻辑执行
问:xxxx-xx-xx  打鱼还是晒网?
举例:2020-09-08 这一天是打鱼还是晒网

计算总天数,  总天数 % 5 == 1, 2, 3 是在打渔;  4,0在晒网
总天数的计算:
方式一:(date2.getTime() - date1.getTime()) / (1000 * 60 * 60 * 24) + 1

方式二:1990-01-01   --> 2019-12-31   -->  * 365 + 闰年数
--> + 2020-01-01  --> 2020-09-08
 */

十一. Calendar日历类的使用

java.util.Calendar(日历)类

  • Calendar是一个抽象基类,主要用于完成日期字段之间相互操作的功能

  • 获取Calendar实例的方法

    • 使用Calendar.getInstance()方法
    • 调用它的子类GregorianCalendar的构造器
  • 一个Calendar的实例时系统时间的抽象表示,通过get(int filed)方法来取得想要的时间信息。比如YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY、MINUTE、SECOND

  • set(int filed, int value)

    add(int filed, int amount)

    final Date getTime()

    finale void setTime(Date date)

注意:

  • 获取月份时,一月是0,以此类推;
  • 获取星期时,周日是1,以此类推。
/*
    Calendar日历类的使用
     */
    @Test
    public void testCalendar(){
        //1. 实例化
        Calendar cal = Calendar.getInstance();
        // System.out.println(cal.getClass());  也是new的子类对象

        // 2. 常用方法
        //  get()
        int days = cal.get(Calendar.DAY_OF_MONTH);
        System.out.println(days); // 10   5/10  这个月的第几天
        System.out.println(Calendar.WEEK_OF_YEAR); // 默认是3
        System.out.println(cal.get(Calendar.WEEK_OF_YEAR)); // 20
        //  set()
        System.out.println("****************");
        cal.set(Calendar.DAY_OF_MONTH, 22);
        days = cal.get(Calendar.DAY_OF_MONTH);
        System.out.println(days);  // 22

        // add()
        System.out.println("****************");
        cal.add(Calendar.DAY_OF_MONTH, 3);
        days = cal.get(Calendar.DAY_OF_MONTH);
        System.out.println(days); // 25号

        //  getTime()
        System.out.println("****************");
        Date date = cal.getTime();
        System.out.println(date); // Tue May 25 18:11:47 CST 2021

        //  setTime()
        System.out.println("****************");
        Date date1 = new Date();
        cal.setTime(date1);
        days = cal.get(Calendar.DAY_OF_MONTH);
        System.out.println(days); // 10
    }

十二. JDK8中日期时间API的介绍

出现背景:

​ 如果我们可以跟别人说:“我们在1502643933071见面,别晚了!”那么就再简单不 过了。但是我们希望时间与昼夜和四季有关,于是事情就变复杂了。JDK 1.0中包含了 一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用 了。而Calendar并不比Date好多少。它们面临的问题是:

可变性:像日期和时间这样的类应该是不可变的。

偏移性:Date中的年份是从1900开始的,而月份都从0开始。

格式化:格式化只对Date有用,Calendar则不行。 此外,它们也不是线程安全的;不能处理闰秒等。

总结:对日期和时间的操作一直是Java程序员最痛苦的地方之一。

@Test
    public void testDate(){
        Date date1 = new Date(2021, 5, 11);
        System.out.println(date1); // Sat Jun 11 00:00:00 CST 3921  这里就涉及到偏移量的问题了
        // 要想正确表示时间,需要减去偏移量,使用不方便
        Date date2 = new Date(2021 - 1900, 5 - 1, 11);
        System.out.println(date2); // Tue May 11 00:00:00 CST 2021
    }
  • Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。 新的 java.time 中包含了所有关于本地日期(LocalDate)、本地时间 (LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime) 和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 方法, 用于把 Date 转换成新的表示形式。这些新增的本地化时间日期 API 大大简 化了日期时间和本地化的管理。

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

大多数开发者只用到1,3,4这几个包。

十三. LocalDate、Localtime、LocalDateTime的使用

  • LocalDate、LocalTime、LocalDateTime 类是其中较重要的几个类,它们的实例 是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。 它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区 相关的信息。
    • LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。
    • LocalTime表示一个时间,而不是日期
    • LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一。

注:ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示 法,也就是公历。

/*
    LocalDate、Localtime、LocalDateTime的使用
    1. LocalDateTime使用频率更高
    2. 类似于jdk8之前的Calendar
     */
    @Test
    public void test1(){
        //now():获取当前日期、时间、日期和时间
        LocalDate localDate = LocalDate.now();
        LocalTime localTime = LocalTime.now();
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDate);
        System.out.println(localTime);
        System.out.println(localDateTime);

        // of():设置指定的年、月、日、时、分 、秒,没有偏移量
        LocalDateTime localDateTime1 = LocalDateTime.of(2021, 5, 11, 10, 53, 45);
        System.out.println(localDateTime1);

        // getXXX():获取指定的时间
        System.out.println(localDateTime.getDayOfMonth());
        System.out.println(localDateTime.getDayOfWeek());
        System.out.println(localDateTime.getMinute());

        //体现不可变性,localDate本身不可变
        // withXxx():设置相关的属性
        LocalDate localDate1 = localDate.withDayOfMonth(22);
        System.out.println(localDate); // 2021-05-11
        System.out.println(localDate1); // 2021-05-22

        //加: plusXxx():时间增加设置
        LocalDateTime localDateTime3 = localDateTime.plusMonths(3); //加3个月
        System.out.println(localDateTime3); // 2021-08-11T11:05:03.550015700

        //减:minusXxx():
        LocalDateTime localDateTime4 = localDateTime.minusDays(10);
        System.out.println(localDateTime4); // 2021-05-01T11:08:35.197461500
    }

十四. Instant类的使用

  • Instant:时间线上的一个瞬时点,这可能被用来记录应用程序中的事件时间戳
  • 在处理时间和日期的时候,我们通常会想到年,月,日,时,分,秒。然而,这只是时间的一个模型,是面向人类的。第二种通用模型是面向机器的。或者说是连续的。在此模型中,时间线中的一个点表示伟一个很大的数,这有利于计算机处理。在UNIX中,这个数从1970年开始,以秒为单位;同样的,在Java中,也是从1970年开始,但以毫秒为单位。
  • java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间单位。Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲,它只是简单的表示自1970年1月1日0时0 分0秒(UTC)开始的秒数。因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳秒级。
  • (1 ns = 10^-9 s)1秒 = 1000 毫秒 = 10^6 微秒 = 10^9 纳秒
/*
    Instant的使用
    类似于 java.util.Date类
     */
    @Test
    public void testInstant(){
        // now():获取本初子午线对应标准时间
        Instant instant = Instant.now();
        System.out.println(instant); // 2021-05-11T03:34:19.552126400Z  时区加减8小时才是我们正确的时间

        // atOffset:处理时间偏移量得到正确时间
        OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
        System.out.println(offsetDateTime); // 2021-05-11T13:29:55.415261100+08:00

        // toEpochMilli():获取自1970年1月1日0时0分0秒开始的毫秒数
        long milli = instant.toEpochMilli();
        System.out.println(milli); // 1620711388924

        //ofEpochMilli:通过给定毫秒数,获取Instant实例  -->DAte(Long millis)
        Instant instant1 = Instant.ofEpochMilli(1620711388924L);
        System.out.println(instant1); // 2021-05-11T05:36:28.924Z
    }

十五. DateTimeFormatter类的使用

java.time.format.DateTimeFormatter 类:该类提供了三种格式化方法:

  • 预定义的标准格式。如: ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
  • 本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
  • 自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)

方 法 描 述

ofPattern(String pattern) 静态方法 , 返 回 一 个 指 定 字 符 串 格 式 的 DateTimeFormatter

format(TemporalAccessor t) 格式化一个日期、时间,返回字符串

parse(CharSequence text) 将指定格式的字符序列解析为一个日期、时间

/*
    DateTimeFormatter:格式化或解析日期、时间
    类似于SimpleDateFormat
     */
    @Test
    public void test3(){
        //方式1:预定义的标准格式。用的较少,如: ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
        DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        //格式化
        LocalDateTime localDateTime = LocalDateTime.now();
        String str1 = formatter.format(localDateTime);
        System.out.println(localDateTime);
        System.out.println(str1); //2021-05-11T13:50:10.4618191
        //解析:字符串 --> 日期
        TemporalAccessor parse = formatter.parse("2021-05-11T13:50:10.4618191");
        System.out.println(parse); // {},ISO resolved to 2021-05-11T13:50:10.461819100

        //方式二:本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
        //FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT:适用于LocalDateTime
        DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
        // 格式化
        String str2 = formatter1.format(localDateTime);
        System.out.println(str2);  // 2021/5/11 下午2:11   short的情况下
        // 2021年5月11日 下午7:51:49  medium的情况下

        //本地化相关的格式。如:ofLocalizedDate()
        //FormatStyle.Full / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT:适用于LocalDate
        DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
        String str3 = formatter2.format(LocalDate.now());
        System.out.println(str3); // 2021年5月11日星期二

        //方式三:自定义格式,如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
        DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
        String str4 = formatter3.format(LocalDateTime.now());
        System.out.println(str4); // 2021-05-11 08:00:34

        //解析
        TemporalAccessor accessor = formatter3.parse("2021-05-11 08:00:34");
        System.out.println(accessor);
        //{MilliOfSecond=0, MicroOfSecond=0, SecondOfMinute=34, NanoOfSecond=0, MinuteOfHour=0, HourOfAmPm=8},ISO resolved to 2021-05-11
    }

十六. 其他时期时间相关API的使用

  • ZoneId:该类中包含了所有的时区信息,一个时区的ID,如 Europe/Paris
  • ZonedDateTime:一个在ISO-8601日历系统时区的日期时间,如 2007-12- 03T10:15:30+01:00 Europe/Paris。 其中每个时区都对应着ID,地区ID都为“{区域}/{城市}”的格式,例如: Asia/Shanghai
  • Clock:使用时区提供对当前即时、日期和时间的访问的时钟。
  • 持续时间:Duration,用于计算两个“时间”间隔
  • 日期间隔:Period,用于计算两个“日期”间隔
  • TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整 到“下一个工作日”等操作。
  • TemporalAdjusters : 该类通过静态方法 (firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用 TemporalAdjuster 的实现。

十七. idea使用:导入module

ProjectStructure ——>Modules导入

十八.重要!!! Java比较器概述

  • 在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间 的比较问题。
  • Java实现对象排序的方式有两种:
    • 自然排序:java.lang.Comparable
    • 定制排序:java.util.Comparator
一:说明:java中的对象,正常情况下只能进行比较: ==或!=  不能使用 > 或 <
但在开发中,需要对多个对象进行排序,言外之意,需要比较对象的大小。
如何实现呢? 使用两个接口中的任何一个:Comparable 或 Comparator

二. Comparable接口的使用
@Test
    public void test1(){
        /*
        1. 像String、包装类等实现了Comparable接口,重写了compareTo()方法,给出了比较两个对象的大小
        2. 像String、包装类重写compareTo()的方法以后,进行了从小到大的排列。
        3. 重写compareTo()的规则:
            如果当前对象this大于形参对象obj,则返回正整数,
            如果当前对象this小于形参对象obj,则返回负整数,
            如果当前对象this等于形参对象obj,则返回零。
         */
        String[] arr = new String[]{"AA", "BB", "CC", "GG", "MM", "DD"};

        //排序
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr)); // [AA, BB, CC, DD, GG, MM]
        // 原理:String实现了Comparable方法

十九. 自定义类实现Comparable自然排序

  • Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称 为类的自然排序。

  • 实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即 通过 compareTo(Object obj) 方法的返回值来比较大小。如果当前对象this大 于形参对象obj,则返回正整数,如果当前对象this小于形参对象obj,则返回 负整数,如果当前对象this等于形参对象obj,则返回零

  • 实现Comparable接口的对象列表(和数组)可以通过 Collections.sort 或 Arrays.sort进行自动排序。实现此接口的对象可以用作有序映射中的键或有 序集合中的元素,无需指定比较器。

  • 对于类 C 的每一个 e1 和 e2 来说,当且仅当 e1.compareTo(e2) == 0 与 e1.equals(e2) 具有相同的 boolean 值时,类 C 的自然排序才叫做与 equals 一致。建议(虽然不是必需的)最好使自然排序与 equals 一致。

  • Comparable 的典型实现:(默认都是从小到大排列的)

    • String:按照字符串中字符的Unicode值进行比较
    • Character:按照字符的Unicode值来进行比较
    • 数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值 大小进行比较
    • Boolean:true 对应的包装类实例大于 false 对应的包装类实例
    • Date、Time等:后面的日期时间比前面的日期时间大

商品类:

/*
商品类:要想对对象排序,就得调用arrays.sort()方法,涉及到comparable比较器,则该类需要实现Comparable接口

 */
public class Goods implements Comparable{
    private String name;
    private double price;

    public Goods(){
    }

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

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

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

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

    //指明商品比较大小的方式:价格从低到高,产品名称从低到高
    @Override
    public int compareTo(Object o) {
        if (o instanceof Goods){
            Goods goods = (Goods) o;
            //方式一
            if (this.price > goods.price){
                return 1;
            }else if (this.price < goods.price){
                return -1;
            }else{
                //return 0;
                return this.name.compareTo(goods.name);//加-号从高到低
            }

            //方式二:
            //return Double.compare(this.price,goods.price);
        }
        throw new RuntimeException("传入的数据类型不一致!");
    }
}

测试类:

@Test
    public void test2(){
        Goods[] arr = new Goods[4];
        arr[0] = new Goods("lenovoMouse", 34);
        arr[1] = new Goods("dellMouse", 43);
        arr[2] = new Goods("xiaomiMouse", 12);
        arr[3] = new Goods("huaweiMouse", 65);
        //排序
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
        //[Goods{name='xiaomiMouse', price=12.0}, Goods{name='lenovoMouse', price=34.0}, Goods{name='dellMouse', price=43.0}, Goods{name='huaweiMouse', price=65.0}]
    }

二十. 定制排序——使用Comparator实现

方式二:定制排序:java.util.Comparator

  • 当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码, 或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那 么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排 序的比较。
  • 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返 回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示 o1小于o2。
  • 可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort), 从而允许在排序顺序上实现精确控制。
  • 还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的 顺序,或者为那些没有自然顺序的对象 collection 提供排序。
 /*
    Comparator接口的使用:定制排序
    1. 背景:
        当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,
        或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,
        那么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排 序的比较。

    2. 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
    如果方法返 回正整数,则表示o1大于o2;
    如果返回0,表示相等;返回负整数,表示 o1小于o2。

     */
    @Test
    public void test3(){
        String[] arr = new String[]{"AA", "BB", "CC", "GG", "MM", "DD"};
        Arrays.sort(arr, new Comparator<String>() {
            //指定定制规则,字符串按照从大到小排序
            @Override
            public int compare(String o1, String o2) {
                if (o1 instanceof String && o2 instanceof String){
                    String s1 = (String) o1;
                    String s2 = (String) o2;
                    return -s1.compareTo(s2);
                }
                //return 0;
                throw new RuntimeException("输入的数据类型不一致");
            }
        });

        //排序
        System.out.println(Arrays.toString(arr));// [MM, GG, DD, CC, BB, AA]
    }

    @Test
    public void test4(){
        Goods[] arr = new Goods[5];
        arr[0] = new Goods("lenovoMouse", 34);
        arr[1] = new Goods("dellMouse", 43);
        arr[2] = new Goods("xiaomiMouse", 12);
        arr[3] = new Goods("huaweiMouse", 65);
        arr[4] = new Goods("huaweiMouse", 224);
        //排序
        Arrays.sort(arr, new Comparator() {
            //指定先按产品名称从低到高,然后按价格从高到低排序
            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Goods && o2 instanceof Goods){
                    Goods g1 = (Goods) o1;
                    Goods g2 = (Goods) o2;
                    if (g1.getName().equals(g2.getName())){
                        return -Double.compare(g1.getPrice(), g2.getPrice());
                    }else{
                        return g1.getName().compareTo(g2.getName());
                    }
                }
                //return 0;
                throw new RuntimeException("传入的数据类型不一致!");
            }
        });
        System.out.println(Arrays.toString(arr));
        // [Goods{name='dellMouse', price=43.0}, Goods{name='huaweiMouse', price=224.0}, Goods{name='huaweiMouse', price=65.0}, Goods{name='lenovoMouse', price=34.0}, Goods{name='xiaomiMouse', price=12.0}]
    }

二十一. System、Math、BigInteger、BigDecimal的使用

一. System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。 该类位于java.lang包。

  • 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实 例化该类。其内部的成员变量和成员方法都是static的,所以也可以很方便 的进行调用。
  • 成员变量
    • System类内部包含in、out和err三个成员变量,分别代表标准输入流 (键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
  • 成员方法
    • native long currentTimeMillis(): 该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时 间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
    • void exit(int status): 该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表 异常退出。使用该方法可以在图形界面编程中实现程序的退出功能等。
    • void gc(): 该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则 取决于系统中垃圾回收算法的实现以及系统执行时的情况。
    • String getProperty(String key): 该方法的作用是获得系统中属性名为key的属性对应的值。系统中常见 的属性名以及属性的作用如下表所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UzWYfHpW-1622533996466)(C:\Users\caiyunlai\AppData\Roaming\Typora\typora-user-images\image-20210511225332590.png)]

@Test
    public void test1(){
        String javaVersion = System.getProperty("java.version");
        System.out.println("java的version:" + javaVersion);
        String javaHome = System.getProperty("java.home");
        System.out.println("java的home:" + javaHome);
        String osName = System.getProperty("os.name");
        System.out.println("os的name:" + osName);
        String osVersion = System.getProperty("os.version");
        System.out.println("os的version:" + osVersion);
        String userName = System.getProperty("user.name");
        System.out.println("user的name:" + userName);
        String userHome = System.getProperty("user.home");
        System.out.println("user的home:" + userHome);
        String userDir = System.getProperty("user.dir");
        System.out.println("user的dir:" + userDir);
    }

输出:

java的version:11.0.8
java的home:D:\Java\jdk-11.0.8
os的name:Windows 10
os的version:10.0
user的name:caiyunlai
user的home:C:\Users\caiyunlai
user的dir:D:\Java\JavaProjects\JavaSE\基础语法

二. Math类

java.lang.Math提供了一系列静态方法用于科学计算。其方法的参数和返回
值类型一般为double型。
abs 绝对值
acos,asin,atan,cos,sin,tan 三角函数
sqrt 平方根
pow(double a,doble b) a的b次幂
log 自然对数
exp e为底指数
max(double a,double b)
min(double a,double b)
random() 返回0.0到1.0的随机数
long round(double a) double型数据a转换为long型(四舍五入)
toDegrees(double angrad) 弧度—>角度
toRadians(double angdeg) 角度—>弧度

三. BigInteger 和 BigDecimal

  • Integer类作为int的包装类,能存储的最大整型值为2 31-1,Long类也是有限的, 最大为2 63-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类 都无能为力,更不用说进行运算了。

  • java.math包的BigInteger可以表示不可变的任意精度的整数。BigInteger 提供 所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。 另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、 位操作以及一些其他操作。

  • 构造器

    • BigInteger(String val):根据字符串构建BigInteger对象
  1. BigInteger类

 常用方法
 public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger。
 BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger
 BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger
 BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger
 BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。整数
相除只保留整数部分。
 BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的 BigInteger。
 BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟
(this % val) 的两个 BigInteger 的数组。
 BigInteger pow(int exponent) :返回其值为 (thisexponent) 的 BigInteger。

  1. BigDecimal类
  • 一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中, 要求数字精度比较高,故用到java.math.BigDecimal类。
  • BigDecimal类支持不可变的、任意精度的有符号十进制定点数。
  • 构造器
    • public BigDecimal(double val)
    • public BigDecimal(String val)
  • 常用方法
    • public BigDecimal add(BigDecimal augend)
    • public BigDecimal subtract(BigDecimal subtrahend)
    • public BigDecimal multiply(BigDecimal multiplicand)
    • public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
public void testBigInteger() {
BigInteger bi = new BigInteger("12433241123");
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bi);
// System.out.println(bd.divide(bd2));
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2, 15, BigDecimal.ROUND_HALF_UP));
}

你可能感兴趣的:(#,Java学习笔记整理,Java学习,常用类第二部分)