• Java基础----常用类


    0. Intellij Idea

    快捷键

    ALT+SHIFT+0:生成构造器或setter、getter

    IDEA的Debug

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    IDEA导入已有的模块

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    1 字符串相关的类

    1.1 String类

    String源码

    public final class String implements java.io.Serializable, Comparable<String>, CharSequence{
    	private final char value[];
    	private int hash;
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    String的实例化

    String s1="hello";//字面量实例化
    String s2=new String();//本质是this.value=new char[0];
    String s3=new String(String original);//本质是this.value=original.value;
    String s4=new String(char[] a);//this.value=Arrays.copyOf(value, value.length);
    String s5=new String(char[] a, int startIndex, int count);
    
    总体来说:
    String的实例化方式:
     * 方式1:通过字面量定义的方式:存放到方法区中的字符串常量池中
     * 方式2:通过new + 构造器的方式:存放到堆中
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    String:字符串,使用一对""引起来表示

    • 1.String声明为final的,不可被继承
    • 2.String实现Serializable接口:表示字符串是支持序列化的
      实现Comparable接口:表示字符串可以比较大小
    • 3.String内部定义了final char[] value用于存储字符串数据
    • 4.String代表不可变的字符序列。简称:不可变性
      体现:1.当对字符串重新赋值时,需要重新指定内存区域赋值,不能使用原有的value进行赋值。//见内存解析
      2.当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。s1+="def";则内存地址已经变了
      3.当调用String的replace()方法修改指定的字符或字符串时,也需要重新指定内存区域赋值。String s3="abc"; String s4=s3.replace('a', 'm');
    • 5.通过字面量的方式(如String s1=“abc”;)(区别于new的方式)给一个字符串赋值,此时的字符串值声明在方法区的字符串常量池中
    • 6.字符串常量池中是不会存储相同内容的字符串的

    面试题

    面试题:String s=new String(“abc”);方式创建对象,在内存中创建了几个对象?
    2个:1个是堆空间中new的String的结构value,另一个是char[]对应的字符串常量池中的数据,即"abc"

    内存解析1

    在这里插入图片描述

    内存解析2

    在这里插入图片描述

    内存解析3

    在这里插入图片描述

    内存解析4

    小结论

    1.常量与常量的拼接结果在常量池中,且常量池中不会存在相同内容的常量
    2.只要其中有一个是变量,结果就在堆中
    3.intern()方法可以返回字符串常量池中的地址值

    String s1="hello";
    String s2="world";
    String S3="helloworld";
    String s4="hello"+"world";
    String s5=s1+"world";
    String s6=s1+s2;
    String s7=s5.intern();//此时返回的s7是常量池中已经存在的"helloworld"的地址值
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    解析:
    在这里插入图片描述

    1.2 String的一些方法

    • 1.int length():返回字符串的长度
    • 2.char charAt(int index):返回某索引处的字符
    • 3.boolean isEmpty():判断是否是空字符串
    • 4.String toLowerCase():使用默认语言环境,将String中的所有字符转换为小写
    • 5.String toUpperCase():使用默认语言环境,将String中的所有字符转换为大写
    • 6.String trim():返回字符串的副本,忽略前导空白和尾部空白如" h ello "返回的是"h ello"
    • 7.boolean equals(Object obj):比较字符串的内容是否相等
    • 8.boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
    • 9.String concat(String str):将字符串str连接到此字符串的结尾。等价于”+“
    • 10.int compareTo(String anotherString):比较两个字符串的大小
      若返回是负数,则当前对象小;返回0,相等。对比是把字符串从前往后的每一个字符的ASCII码做对比
    • 11.String substring(int beginIndex):返回一个新的字符串,它是此字符串从beginIndex开始截取到最后一个的子字符串
    • 12.String substring(int beginIndex, int endIndex):返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串
      一般java中都是左闭右开的
    • 13.boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
    • 14.boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
    • 15.boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始//意思就是字符串中的第toffset个开始的字符串是否是prefix
    • 16.boolean contains(CharSequence s):当且仅当此字符串包含字符序列(字符串)s时,返回true
    • 17.int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的开头索引,若没有找到,则返回-1
    • 18.int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
    • 19.int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
    • 20.int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
      注:indexOf和lastIndexOf方法如果未找到都是返回-1。调用indexOf(str)和lastIndexOf(str)返回值相同的情况:存在唯一的str或不存在str
    • 21.String replace(char oldChar, char newChar):返回一个新的字符串,它是通过newChar替换此字符串中出现的所有oldChar得到的
    • 22.String replace(CharSequence target, CharSequence replacement):使用指定的字符序列替换所有的目标字符序列
    • 23.String replaceAll(String regex, String replacement):使用给定的replacement替换此字符串所有匹配给定的正则表达式的子字符串
    • 24.String replaceFirst(String regex, String replacement):使用给定的replacement替换此字符串匹配给定的正则表达式的第一个字符串
    • 25.boolean matches(String regex):告知此字符串是否匹配给定的正则表达式
    • 26.String[] split(String regex):(切片)根据正则表达式的匹配拆分此字符串
    • 27.String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。

    String与char[]之间的转换

    String—>char[]:调用String的一个方法toCharArray():char[] arr=str.toCharArray();
    char[]—>String:调用String的构造器:String str = new String(arr);

    String与byte[]之间的转换

    String—>byte[]:调用String的一个方法getBytes():byte[] b = str.getBytes();
    byte[]—>String:调用String的构造器:String str = new String(b);

    • 编码:字符集—>字节(看得懂—>看不懂的二进制数据)(String—>byte[])
    • 解码:编码的逆过程,字节—>字符串(看不懂的二进制数据—>看得懂)(byte[]—>String)
      说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码
    String s1="abc123中国";
    byte[] b = s1.getBytes();//使用默认的字符集进行转换编码,因为我们之前给idea设置的是utf-8,所以默认的是utf-8
    System.out.println(Arrays.toString(b));
    
    byte[] b2 = s1.getBytes("gbk");//使用gbk字符集来进行编码
    System.out.println(Arrays.toString(b2));
    //utf-8和gbk都可以把汉字编码成数字,前者用三个数字来表述一个汉字,后者用两个数字表述一个汉字;二者存放英文字符的编码都是一样的
    
    String s2 = new String(b);//使用默认的字符集进行解码,即使用utf-8来解码
    System.out.println(s2);
    
    String s3 = new String(b2, "gbk");//需要使用gbk来解码,若使用utf-8解码,则会出现乱码
    System.out.println(s3);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    1.3 StringBuffer和StringBuilder

    String,StringBuffer,StringBuilder三者的异同?

    • String:不可变的字符序列
    • StringBuffer:可变的字符序列:线程安全的(里面的方法都是同步方法),效率低
    • StringBuilder:可变的字符序列:线程不安全的,效率高
      三者底层都是使用char[]存储的,只不过String加了final,后面两个没加

    正是因为String是不可变的字符序列,所以它的对字符串操作的一些方法都有返回值类型,如String toUpperCase()
    而StringBuffer和StringBuilder是可变的字符序列,所以对字符串操作的一些方法虽然有返回值类型的,如StringBuffer append(xxx),但是一般不接受,如str.append(),因为str已经变了,很少用另一个字符串去接收

    String与StringBuffer、StringBuilder之间的转换

    • String—>StringBuffer,StringBuilder:调用StringBuffer,StringBuilder的构造器
    • StringBuffer,StringBuilder—>String:调用String的构造器或者调用StringBuffer,StringBuilder的toString()方法

    对比String,StringBuffer,StringBuilder的效率:
    从高到低排列:StringBuilder > StringBuffer > String

    String源码分析:
    String s=new String();/底层是char[] value=new char[0];
    String s=new String(“abc”);底层是char[] value=new char[]{'a', 'b', 'c'};
    StringBuffer源码分析(StringBuilder类似):
    StringBuffer s=new StringBuffer();char[] value=new char[16];底层创建了一个长度是16的char数组
    s.append(‘a’);value[0]='a';
    StringBuffer s=new StringBuffer(“abc”);char[] value=new char["abc".length()+16];底层创建了一个长度为3+16=19的char数组
    StringBuffer常见问题和错误(StringBuilder类似)

    • 问题1:System.out.println(s);//输出是3
    • 问题2:扩容问题:如果要添加的数据底层的数组存不下了,那就需要扩容底层的数组。默认情况下,扩容为原来容量的2倍+2,同时将原有数组中的元素复制到新的数组中。特殊情况见源码
    • 指导意义:开发中如果需要一个字符串经常变,如经常调用append(),则尽量用StringBuffer(当可能出现线程安全问题时)和StringBuilder(当没有线程安全问题时),而少使用String。开发中建议使用StringBuffer(int capacity)和StringBuilder(int capacity)构造器,尽量避免去扩容

    1.4 StringBuffer和StringBuilder的方法

    • 1.StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串的拼接s1.append(1);s1.append('1');
    • 2.StringBuffer delete(int start, int end):删除指定位置的内容s1.delete(2,4);
    • 3.StringBuffer replace(int start, int end, String str):把[start, end)位置替换为strs2.replace(2,4,"hello");
    • 4.StringBuffer insert(int offset, xxx):在指定位置插入xxxs3.insert(2,false);
    • 5.StringBuffer reverse():把当前字符序列反转s3.reverse();
    • 6.public int indexOf(String str):返回str在字符串中首次出现的位置
    • 7.public String subString(int start, int end):返回[start, end)的子字符串,此时此StringBuffer或StringBuilder的字符串没有改变,只是返回String类型的子串
    • 8.public int length()
    • 9.public char charAt(int n):返回第n个的字符
    • 10.public void setCharAt(int n, char ch):将第n个的字符换成ch

    由于append()等方法返回的是StringBuffer或StringBuilder字符串本身,因此可以使用方法链原理,即多次调用:s.append().append().append().append();
    总结

    • 增:append(xxx)
    • 删:delete(int start, int end)
    • 改:setCharAt(int n, char ch) 和 replace(int start, int end, String str)
    • 查:charAt(int n)
    • 插:insert(int offset, xxx)
    • 长度:length()
    • 遍历:直接sout输出,或sout输出toString()方法,或for循环+charAt(n)输出

    1.5 练习题:滑动窗口

    import org.junit.Test;
    
    import java.util.Arrays;
    
    /**
     * @author JiaMing
     * @create 08-22 18:05
     * @description 获取两个字符串中最大相同字串。比如:str1="abcwerthelloyuiodef12345",str="cvghellobnm12345"
     * 提示:将短的那个串进行长度依次递减的子串与较长串比较
     */
    public class Exer5 {
        public String maxSubString(String s1, String s2){
            //由于可能存在多个长度相同的最大相同子串,因此创建builder等会方便存进去,不用数组存是因为不知道有几个最大相同子串,所以不知道数组的长度该创建多大
            StringBuilder builder = new StringBuilder();
            //先选出哪个长哪个短
            String maxStr = s1.length() >= s2.length() ? s1 : s2;
            String minStr = s1.length() < s2.length() ? s1 : s2;
    
            //外层循环逐次加一
            for (int i = 0; i < maxStr.length(); i++) {
                //内层循环的意思是:第一次比较的是subStr即"cvghellobnm12345",maxStr不包含subStr
                //第二次比较的是:subStr="cvghellobnm1234","vghellobnm12345",maxStr不包含subStr
                //第三次比较的是:subStr="cvghellobnm123","vghellobnm1234","ghellobnm12345",maxStr不包含subStr
                //...这样依次循环
                for (int x=0,y=minStr.length()-i; y<=minStr.length(); x++,y++) {
                    String subStr=minStr.substring(x,y);
                    if(maxStr.contains(subStr)){
                        //如果maxStr包含subStr,则存到builder中,并且把此次循环继续执行,看看是否有多个长度相同的最大相同子串并存到builder中
                        builder.append(subStr+",");
                    }
                }
                //当这一次的内层循环结束并且builder中已经有最大子串时,则结束外层循环,不需要再找了
                if(builder.length()!=0){
                    break;
                }
            }
    
            //先把builder转换成String类型,再去掉最后的","   然后并切片成多份,命名到数组中
            String[] split = builder.toString().replaceAll(",$", "").split("\\,");
            return Arrays.toString(split);//将数组转换成String类型并返回
        }
    
        @Test
        public void test() {
            String str1="abcwerthelloyuiodef12345";
            String str2="cvghellobnm12345";
            String maxSubString = maxSubString(str1, str2);
            System.out.println(maxSubString);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    2 JDK8 之前日期和时间的API测试

    2.1 java.lang.System类

    System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差

    2.2 java.util.Date类

    ①两个构造器的使用
    ->空参构造器:Date():创建一个对应当前时间的Date对象。Date d1 = new Date();
    ->参数为long型整数的构造器:Date(long date):创建指定毫秒数的Date对象,参数中的date是与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。Date d2 = new Date(1661156872226L); System.out.println(d2.toString());//输出是Mon Aug 22 16:27:52 CST 2022
    ②两个方法的使用
    ->toString():显式当前的年、月、日、星期几、时、分、秒。
    ->getTime():获取当前Date对象对应的毫秒数(时间戳),和java.lang.System.currentTimeMillis()功能一致。System.out.println(d1.getTime());

    2.3 java.sql.Date类

    java.sql.Date类是对应数据库中的日期类型的变量,只有在和数据库交互中才会使用这个(注:java.sql.Date是java.util.Date的子类)
    ->创建java.sql.Date对象。java.sql.Date d3 = new java.sql.Date(135646872313L);
    java.sql.Date也可以调用toString()方法
    ->如何将java.util.Date对象转换为java.sql.Date对象。

    java.util.Date d1 = new java.util.Date();
    java.sql.Date d4 = new java.sql.Date(d1.getTime());
    
    • 1
    • 2

    2.4 java.text.SimpleDateFormat类

    SimpleDateFormat的使用:SimpleDateFormat是对日期Date类的格式化和解析的类
    ①当使用默认构造器进行SimpleDateFormat的实例化,按照默认的方式格式化和解析:SimpleDateFormat sdf = new SimpleDateFormat();
     两个操作:
     ->格式化:日期—>字符串

    Date d1 = new Date();
    String s2 = sdf.format(d1);
    System.out.println(s2);//输出的是中文:2022/8/22 下午7:42
    
    • 1
    • 2
    • 3

      ->解析:格式化的逆过程,字符串—>日期

    String s3="2022/9/27 上午11:20";//字符串必须是这种格式,如果不是这种格式,会抛"ParseException"异常
    Date d2=sdf.parse(s3);
    System.out.println(d2);//此时输出的就又是Tue Sep 27 11:20:00 CST 2022
    
    • 1
    • 2
    • 3

    ②当调用带参构造器进行SimpleDateFormat的实例化,按照指定的方式格式化和解析:SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    其中,yyyy代表4位数是年份,MM代表2位数的月份,dd代表2位数的日期,hh代表2位数的小时,mm代表2位数的分钟,ss代表2位数的秒
    当然构造器的参数还有其他格式,如"yyyyy.MMMMM.dd GGG hh:mm:aaa"输出的格式是"02001.July.04 AD 12:08 PM"等等,具体可见java API
     两个操作:
     ->格式化:日期—>字符串

    String s4 = sdf2.format(d1);//输出2022-08-22 07:55:07,
    //这个格式和构造器中的参数类型是相同的
    
    • 1
    • 2

     ->解析:格式化的逆过程,字符串—>日期

    Date d3 = sdf2.parse("2021-05-05 2:12:12");//要求字符串必须符合
    //SimpleDateFormat的构造器的参数格式,否则会抛异常,
    //输出为Wed May 05 02:12:12 CST 2021
    
    • 1
    • 2
    • 3

    2.5 java.util.Calendar类(日历类)

    java.util.Calendar类是一个抽象类,主要用于完成日期字段之间相互操作的功能
    ①实例化
     方式一:创建其子类(GregorianCalendar)的对象
     方式二:调用其静态方法getInstance()

    Calendar c1 = Calendar.getInstance();//因为Calendar是抽象类,
    //所以getInstance得到的不是Calendar类,而是其子类GregorianCalendar,
    //这是一个匿名子类的非匿名对象
    
    • 1
    • 2
    • 3

    ②常用方法

    • int get(int field):获取想得到的时间信息;field可取YEAR,MONTH,DAY_OF_WEEK,DAY_OF_YEAR,HOUR_OF_DAY,MINUTE,SECOND,即获取年份、月份、这一周的第几天、这一年的第几天,这一天的第几个小时,分钟,秒。int days = c1.get(Calendar.DAY_OF_MONTH);//本月的第几天:此时为8月22日,所以是第22天
    • void set(int field, int value):修改日历中field为value,c1.set(Calendar.DAY_OF_MONTH,23);//修改本月的第几天为第23天
    • void add(int field, int amount):把日历中filed加上amount。c1.add(Calendar.DAY_OF_MONTH,3);//把本月的第几天加上3即23+3=26 c1.add(Calendar.DAY_OF_MONTH,-1);//把本月的第几天减去1天即25
    • final Date getTime():日历类转换成Date,Date d1 = c1.getTime();
    • final void setTime(Date date):Date转换成日历类,Date d2 = new Date(); c1.setTime(d2);//没有返回值,直接把d2的时间赋给c1

    注意:Calendar有偏移量
    即获取月份时:一月是0,二月是1…十二月是11。
    获取星期时,周日是1,周一是2…周六是7

    2.6 练习题:”三天打鱼两天晒网“

    /**
     * @author JiaMing
     * @create 08-22 21:50
     * @description 练习二:从1990-01-01开始”三天打鱼两天晒网“,在2022年5月15日是打鱼还是晒网
     * 分析:可知五天一循环,则可以求这一天是五天中的第几天(总天数%5==1,2,3:打鱼,总天数%5==4,0:晒网),即求出2022-05-15与1990-01-01中间隔了多少天
     */
    public class DaYu480 {
        @Test
        public void test() throws ParseException {
            String s1="1990-01-01";
            String s2="2022-05-15";
    
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    
            Date d1 = sdf.parse(s1);
            Date d2 = sdf.parse(s2);
    
            long time=d2.getTime()-d1.getTime();//两个时间段中间隔了多少毫秒
    
            long days=0;//两个时间段中间隔了多少天
            //一天有24*60*60*1000毫秒
            if(time%(24*60*60*1000)==0){
                //当全部除尽时,那么中间隔了天就是算出来的商
                days=time/(24*60*60*1000);
            }else {
                //当除不尽时就向上取整
                days=time/(24*60*60*1000)+1;
            }
    
            long doWhat=days%5;//五天循环中的第几天
    
            if(doWhat==1 || doWhat==2 || doWhat==3){
                System.out.println("打鱼");
            }else System.out.println("晒网");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    上述几个时间类之间的关系
    在这里插入图片描述

    3 JDK8 中新日期时间API

    引出

    由于JDK8之前的关于时间的包、类等具有可变性(如Calendar可以设置改变)、偏移性(如Date中的年份是从1900开始算的,月份是从0开始的,这和生活中不符)、格式化麻烦、线程不安全、不能处理闰秒等,因此JDK8之后有了更合适的关于时间操作的API:java.time,java.time.chrono,java.time.format,java.time.temporal,java.time.zone等

    • java.time:包含值对象的基础包
    • java.format:格式化和解析时间和日期
    • java.time.temporal:包含底层框架和扩展特性
    • java.time.zone:包含时区支持的类

    3.1 java.time.LocalDateTime类

    java.time使用的最频繁,包含本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)、持续时间(Duration)、时间线上的瞬时点(Instant)。其中LocalDateTime使用的频率更高,以下以LocalDateTime为例使用其方法,LocalDate、LocalTime类似

    • now():(静态方法)获取当前的日期+时间,即实例化
    LocalDateTime ldt = LocalDateTime.now(); 
    System.out.println(ldt);//2022-08-23T10:32:54.146038400
    
    • 1
    • 2
    • of():(静态方法)设置指定的年、月、日、时、分、秒;并且没有偏移量。也属于实例化
    LocalDateTime ldt2 = LocalDateTime.of(2022, 8, 23, 10, 6, 23);
    //也可以只设置时分秒,具体选择of()方法中的参数
    
    • 1
    • 2
    • getXxx():获取相关属性;并且没有偏移量.
    System.out.println(ldt.getDayOfMonth());//获取本月的第几天:23
    System.out.println(ldt.getMinute());//获取现在是这个小时的几分:11
    System.out.println(ldt.getMonth());//获取月份:AUGUST
    System.out.println(ldt.getMonthValue());//获取月份的的数字:8
    System.out.println(ldt.getDayOfWeek());//获取星期几:TUESDAY
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • withXxx():设置相关属性;具有不可变性
    LocalDateTime ldt3 = ldt.withDayOfMonth(30);
    //此时ldt是今天的日期23,ldt3是返回修改过的日期30,因为ldt没有变,
    //所以是不可变性
    
    • 1
    • 2
    • 3
    • plusXxx(),minusXxx():加减相关属性,具有不可变性
    LocalDateTime ldt5 = ldt.plusMonths(3);//ldt5是ldt月份往后推3个月的日期
    LocalDateTime ldt6 = ldt.minusDays(6);//ldt6是ldt往前推6天的日期
    
    • 1
    • 2

    3.2 Instant类

    Instant:时间线上的一个瞬时点。Instant的使用类似于java.util.Date类

    • now():(静态方法)获取此时本初子午线的标准时间,属于实例化
      Instant i1 = Instant.now();System.out.println(i1);//2022-08-23T02:50:28.259934400Z----输出的是此时本初子午线那的时间
    • ofEpochMilli(long milli):(静态方法)通过给定的毫秒数,获取Instant实例,和Data(long milli)类似;属于实例化
      Instant i3 = Instant.ofEpochMilli(1661223459724L);
    • atOffset(ZoneOffset offset):结合时区的偏移量来创建一个 OffsetDateTime
    OffsetDateTime i2 = i1.atOffset(ZoneOffset.ofHours(8));//我们这是东八区,所以参数是ZoneOffset.ofHours(8)
    System.out.println(i2);//输出2022-08-23T10:53:49.070431400+08:00`
    
    • 1
    • 2
    • toEpochMilli():获取自1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳,和Date.getTime()类似。long l = i1.toEpochMilli();

    由以上可知,一般实例化的方法都是静态的,其他的方法都是非静态的

    3.3 java.time.format.DateTimeFormatter类

    格式化或解析日期、时间的类,类似于SimpleDateFormat
    该类提供了三种格式化方法:

    • 方式一:预定义的标准格式。如ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
      DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
      ①格式化:日期—>String
      LocalDateTime ldt = LocalDateTime.now();String s1 = dtf.format(ldt);
      ②解析:String—>日期
      TemporalAccessor p1 = dtf.parse("2022-08-23T11:32:22.6186321");//标准格式实例化的解析只能是这种格式,否则会抛异常
    • 方式二:本地化相关的格式。如:ofLocalizedDateTime(参数),参数可选择:FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT。(类似可知ofLocalizedDate和ofLocalizedTime)
    DateTimeFormatter dtf2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);//格式化之后输出2022/8/23 上午11:41
    DateTimeFormatter dtf2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);//2022年8月23日 上午11:41:14
    DateTimeFormatter dtf2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);//2022年8月23日 上午11时41分14秒
    格式化和解析的操作:
    String s2 = dtf2.format(ldt);
    TemporalAccessor p2 = dtf2.parse("2022/8/23 上午11:45");//实例化时参数是SHORT时的格式
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 方式三:自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”) (重点)
    DateTimeFormatter dtf3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
    ①格式化
    String s3 = dtf3.format(LocalDateTime.now());//输出2022-08-23 11:50:21
    ②解析
    TemporalAccessor p3 = dtf3.parse("2022-08-23 11:50:21");
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.4 其他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 的实现。

    3.5 与传统日期处理的转换

    在这里插入图片描述

    4 Java比较器

    4.1 Comparable接口

    一、说明:java中的对象,正常情况下,只能进行比较地址(==、!=),不能使用 > 或 < 。但是在开发中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。如何实现?使用两个接口中的任何一个:Comparable或Comparator
    二、Comparable接口的使用(自然排序:强行对实现它的每个类的对象进行整体排序)

    • 1.像String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式
    • 2.像String、包装类重写compareTo(obj)方法以后,进行了从小到大的排列
      String和Character:按照字符串/字符中字符的Unicode值进行比较
      Date、Time等:后面的日期时间比前面的日期时间大
      Boolean:true 对应的包装类实例大于 false 对应的包装类实例
    • 3.重写compareTo(obj)的规则:
      如果当前对象this大于形参obj,则返回正整数
      如果当前对象this小于形参obj,则返回负整数
      如果当前对象this等于形参obj,则返回零
    • 4.对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法,在compareTo(obj)方法中指明如何排序
    • 5.实现Comparable接口的对象列表(和数组)可以通过 Collections.sort 或 Arrays.sort 进行自动排序
    public class CompareTest488 {
        @Test
        public void test1(){
            String[] arr=new String[]{"AA","MM","GG","DD","KK","CC"};
            Arrays.sort(arr);
            System.out.println(Arrays.toString(arr));
        }
    
        @Test
        public void test2(){
            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("microsoftMouse",43);
    
            Arrays.sort(arr);
            System.out.println(Arrays.toString(arr));
        }
    }
    
    
    class Goods implements Comparable{
        private String name;
        private double price;
    
        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) {
            //指明按照什么方式进行排序:如按照价格从低到高排序,如果价格相等,则按照产品名称从低到高排序
            //方式1:自己写个方法进行排序
            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 this.name.compareTo(goods.name);//调用name(String类型)的compareTo()方法进行比较
                    //return -this.name.compareTo(goods.name);//前面加一个"-"号,则是按照产品名称从高到低排序
                }
    
                //方式2:使用包装类中的比较方法compare
                //return Double.compare(this.price, goods.price);
            }
           throw new RuntimeException("传入的数据类型不一致");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    4.2 Comparator接口

    三、Comparator接口的使用(定制排序)

    • 1.当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序
    • 2.重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2
    • 3.可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。
    public class CompareTest491 {
        @Test
        public void test1(){
            String[] arr=new String[]{"AA","MM","GG","DD","KK","CC"};
            //将上述字符串数组从大到小排
            //由于默认的Arrays.sort()是调用String的compareTo()方法的(String实现了Comparable接口),而String的compareTo()方法是从小到大的,
            //要想临时进行一次从大到小的排序,可以在参数里面写一个Comparator的匿名实现类的匿名对象,然后重写compare方法,进而设置从大到小排
            Arrays.sort(arr, new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                        return -o1.compareTo(o2);
                }
            });
            System.out.println(Arrays.toString(arr));
        }
    
        @Test
        public void test2(){
            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("microsoftMouse",43);
    
            //这时如果想按照名称从低到高排序,再按照价格从高到低排序
            //由于Goods类中的compareTo()方法的排序和想要的排序方式不一样,因此我们可以使用定制的排序
            //因此在Arrays.sort()参数中new一个Comparator并重写compare()方法,实现想要的排序方式
            Arrays.sort(arr, new Comparator<Goods>() {
                @Override
                public int compare(Goods o1, Goods o2) {
                    if(o1.getName().equals(o2.getName())){
                        return -Double.compare(o1.getPrice(),o2.getPrice());//前面有个负号,表示从高到低排序
                        //一般情况下,String、包装类等重写的compareTo()或compare()方法都是从小到大排序的,所以想要从大到小排序的话需要在前面加"-"
                    }else{
                        return o1.getName().compareTo(o2.getName());
                    }
                }
            });
    
            System.out.println(Arrays.toString(arr));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    四、Comparable接口与Comparator接口使用的对比

    • 1.Comparable是需要对比的类去实现接口,一旦设置好之后,可以保证Comparable接口实现类的对象在任何位置都可以比较大小
      Comparator是临时设置的排序方式,什么时候需要比较,就临时创建一个Comparator的实现类
    • 2.调用Comparable中的compareTo()方法是用其实现类的对象(如Goods的对象goods)去调用的,参数是另一个需要对比的对象。name1.compareTo(name2);
      调用Comparator中的compare()方法是用其实现类(如Double)去调用的,参数是两个需要对比的对象。Double.compare(d1,d2);

    5 System类

    • 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的属性对应的值。系统中常见
      的属性名以及属性的作用如下表所示:
      在这里插入图片描述
    String javaVersion = System.getProperty("java.version");
    System.out.println("java的version:" + javaVersion);
    
    • 1
    • 2

    6 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)------>角度转换为弧度
    向上取整------>ceil(单词意思:天花板)
    向下取整------>floor(单词意思:地板)

    7 BigInteger与BigDecimal

    7.1 BigInteger类

    Integer类作为int的包装类,能存储的最大整型值为231-1,Long类也是有限的,最大为263-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。
    java.math包的BigInteger可以表示不可变的任意精度的整数。BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。
    构造器:BigInteger(String val):根据字符串构建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。

    7.2 BigDecimal类

    一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中,要求数字精度比较高,故用到java.math.BigDecimal类。
    BigDecimal类支持不可变的、任意精度的有符号十进制定点数。

    构造器

    public BigDecimal(double val)
    public BigDecimal(String val)
    
    • 1
    • 2

    常用方法

    public BigDecimal add(BigDecimal augend)
    public BigDecimal subtract(BigDecimal subtrahend)
    public BigDecimal multiply(BigDecimal multiplicand)
    public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
    
    • 1
    • 2
    • 3
    • 4
    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));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    微服务架构之:基于Redis的分布式锁优化(Redisson)
    复盘:智能座舱系列文三- 它背后的5种交互技术之触觉
    London Dock丨伦敦一区的房产明星,拥揽泰晤士河美景,尽享都市奢华生活
    linux 常用命令笔记
    Java基础 - 重写(Override)与重载(Overload)
    C++智能指针
    conda 复制系统环境
    六、表空间管理
    安卓经验分享——图片加载
    重构Transformer神经网络:优化的自注意力机制和前馈神经网络
  • 原文地址:https://blog.csdn.net/qq_57780419/article/details/126494978