Java中的常用类

Java 中的常用类

1. 字符串相关的类

1.1 String的特性

  1. String代表字符串。Java程序中通常用""来表示一串字符串。
  2. String声明为final类型,表示String类不可被继承。
  3. String实现了Serializable接口:表示String是可序列化的。
  4. String实现了Comparable接口:表示String是可以被比较的。
  5. String内部定义了final char[] value用来存储字符串数据。代表了不可变的字符序列,简称不可变性。
  6. 通过字面量的方式(区别于new)给一个字符串赋值,此时字符串的值声明在常量池中
  7. 字符串常量池中是不会存储内容相同的字符串的。

部分源码:

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
String类的部分源码

1.2 String不可变性

  1. 当对字符串重新赋值时,需要重新指定内存区域赋值,不能使用原有的value进行赋值操作。
  2. 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行连接操作。
  3. 当调用String的replace()方法来替换字符或者字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行替换操作
package com.summer.java;

import org.junit.Test;

/**
 * string 的使用
 * @Author 安宁侯
 * @create 2021-03-06 18:06
 */
public class StringTest {

    @Test
    public void test1(){
        String s1="abc";//字面量方式赋值(区别于new方法),此时字符串的值声明在字符串窜常量池中,
        // 字符串常量池不会出现两个相同的字符串的值(通过equals比较为true)
        String s2="abc";
        System.out.println(s1 == s2);
        s1="hello";//此时重新在常量池中创建了一个“hello”的值,
        // 同时改变了s1的地址值。不能在原有的地址值上进行修改
        System.out.println(s1);
        System.out.println(s2);

        System.out.println("**************");
        String s3="abc";
        s3+="def";//此时在常量池中新造了一个abcdef的值。体现为s2的值没有改变
        System.out.println(s2);
        System.out.println(s3);

        System.out.println("**************");
        String s4="abc";
        String s5 = s4.replace("ab", "mm");
        System.out.println(s4);
        System.out.println(s5);
    }
}
String不可变性的代码体现

1.3  String不同实例化方式的比较

String创建时有多种构造器,功能比较丰富,详细信息可以查看一下源码或者API。此处主要比较通过字面量和new String()两种方式。

package com.summer.java;

import org.junit.Test;

/**
 * string 的使用
 * @Author 安宁侯
 * @create 2021-03-06 18:06
 */
public class StringTest {

    @Test
    public void test1(){
        String s1="abc";//字面量方式赋值(区别于new方法),此时字符串的值声明在字符串窜常量池中,
        // 字符串常量池不会出现两个相同的字符串的值(通过equals比较为true)
        String s2="abc";
        System.out.println(s1 == s2);
        s1="hello";//此时重新在常量池中创建了一个“hello”的值,
        // 同时改变了s1的地址值。不能在原有的地址值上进行修改
        System.out.println(s1);
        System.out.println(s2);

        System.out.println("**************");
        String s3="abc";
        s3+="def";//此时在常量池中新造了一个abcdef的值。体现为s2的值没有改变
        System.out.println(s2);
        System.out.println(s3);

        System.out.println("**************");
        String s4="abc";
        String s5 = s4.replace("ab", "mm");
        System.out.println(s4);
        System.out.println(s5);
    }

    @Test
    public void test2(){
        //此时的s1,s2存储的是定义在方法区的字符串常量池中的地址值。
        String s1="javaEE";
        String s2="javaEE";
        //此时s3,s4保存的是在堆空间中开辟出的新空间的地址值
        String s3=new String("javaEE");
        String s4=new String("javaEE");

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

        Person p1 = new Person("Tom", 12);//使用的是字面量的方式定义的name
        Person p2 = new Person("Tom", 12);//此时p1,p2的name都存储的是常量池中tom的地址值
        System.out.println(p1.name.equals(p2.name));//true
        System.out.println(p1.name==p2.name);//true
        p1.name="Jeery";
        System.out.println(p2.name);//Tom
    }
}
class Person{
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

}
String不同实例化的代码体现

面试题一:String s1 = "abc" 与String s2=new String("abc")的区别?

此时s1存储的是字符串常量池中"abc"的地址值,s2存储的是堆空间中新开辟出的空间的地址值,s2对象中的value(也就是char[])中存的才是字符串常量池中"abc"的地址值。

面试题二:String s2=new String("abc")创建了几个对象?

两个:一个是堆空间new出的对象,另一个是char[]数组对应的常量池中的数据"abc"

1.4 String类中不同拼接方式的区别

  1. 常量与常量拼接的结果在常量池,且常量池中不会存在相同内容的常量。
  2. 只要有一个变量参与拼接,结果就在堆空间中。
  3. 如果拼接的结果调用了intern()方法,返回值在常量池中。
 @Test
    public void test3(){
        String s1="javaEE";
        String s2="hadoop";
        String s3="javaEEhadoop";
        String s4="javaEE"+"hadoop";
        String s5=s1+"hadoop";
        String s6="javaEE"+s2;
        String s7=s1+s2;
        String s8=(s1+s2).intern();
        System.out.println(s3 == s4);//true
        System.out.println(s3 == s5);//false
        System.out.println(s3 == s6);//false
        System.out.println(s5 == s6);//false
        System.out.println(s3 == s7);//false
        System.out.println(s5 == s7);//false
        System.out.println(s3 == s8);//true
    }
String不同拼接方式的代码体现

经典例题:

package com.summer.java;

/**
 * @Author 安宁侯
 * @create 2021-03-06 19:41
 */
public class StringTest1 {
    String str=new String("good");//此时str的地址值是指向good的
    char ch[]={'t','e','s','t'};
    public void exchange(String str,char[] ch){
        str="test ok";//此时该str1的地址值是指向test ok
        ch[0]='b';
    }

    public static void main(String[] args) {
        StringTest1 test1=new StringTest1();
        /*
        在值传递中,基本数据类型传的是数据,引用数据类型传的是地址值。
        此时将str的地址值作为参数传递给形参str,由于String类的不可变性,此时实参str的地址值并没有改变
        */
        test1.exchange(test1.str,test1.ch);
        System.out.println(test1.str);//good
        System.out.println(test1.ch);//best
    }
}
值传递和String特性的考察

1.5 String类中的常用方法

  1. int length():返回字符串长度。return value.length
  2. char charAt(int index):返回指定索引处的字符。return value[index]
  3. boolean isEmpty():判断是否是空字符串窜。return value.length==0
  4. String toLowerCase():使用默认语言环境,将String中的所有字符转化成小写
  5. String toUpperCase():使用默认语言环境,将String中的所有字符转化成大写
  6. String trim():返回String的副本,忽略前导空白和尾部空白
  7. boolean equals(Object obj):比较字符串的内容是否相同
  8. boolean equalslgnoreCase(String anotherString):与equals类似,忽略了大小写
  9. String concat(String str):将指定的字符串连接到此字符串的尾部,等价于”+“
  10. int compareTo(String str):比较两个字符串的大小
  11. String subString(int beginIndex):将此字符串从下标beginIndex开始截取到尾部并返回
  12. String subString(int beginIndex,int endIndex):将此字符串从beginIndex到endIndex(不包含)截取并返回
  13. boolean endsWith(String suffix):测试当前字符串是否以指定的后缀结束
  14. boolean startsWith(String prefix):测试当前字符串是否以指定的前缀开始
  15. boolean startsWith(String prefix,int toffset):测试当前字符串是否从指定索引处开始以指定前缀开始
  16. boolean contains(CharSequence s):当且仅当此字符串包含指定的char值序列时,返回true。判断当前字符串是否包含指定字符串
  17. int indexOf(String str):返回子字符串第一次在当前字符串出现的索引。
  18. int indexOf(String str,int fromIndex):从指定索引开始,返回子字符串第一次在当前字符串出现的索引
  19. int lastIndexOf(String str):返回指定子字符串在当前字符串在最右边出现的索引
  20. int lastIndexOf(String str,int fromIndex):从指定索引处反向搜索子字符串最后一次出现的位置。
  21. String replace(char oldChar,char newChar):将newChar替换了oldChar之后(替换所有oldChar),返回一个新的字符串
  22. String replace(CharSequence target,CharSequence replaceMent):(类似replace)将指定的字面值序列替换此字符串所有匹配字面值的子字符串,返回一个新字符串
  23. Strng 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个,如果超过,则全部放在最后一个元素中
 @Test
    public void stringMethods(){
        String s1="  helloWorld  ";
        System.out.println(s1.length());
        System.out.println(s1.charAt(5));
        System.out.println(s1.isEmpty());
        System.out.println(s1.toLowerCase());
        System.out.println(s1.toUpperCase());
        /*compare源码
        public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }
         */
        System.out.println(s1.compareTo("HELLOWORLD"));
        System.out.println(s1.trim());
        System.out.println(s1.equals("HELLOWORLD"));//区分大小写
        System.out.println(s1.equalsIgnoreCase("  HELLOWorld  "));
        System.out.println(s1.concat(" Java"));
        System.out.println(s1.substring(5));
        System.out.println(s1.substring(1, 8));
        System.out.println("***********************");
        System.out.println(s1.endsWith("ld  "));
        System.out.println(s1.startsWith("he"));
        System.out.println(s1.startsWith("he", 2));
        System.out.println(s1.contains("ello"));
        System.out.println(s1.indexOf("he"));
        System.out.println(s1.indexOf("he",2));
        System.out.println(s1.lastIndexOf("Wo"));
        System.out.println(s1.lastIndexOf("Wo", 3));
        System.out.println("***************");
        System.out.println(s1.replace("hello", "你好"));
        //正则表达式以后再写....
    }
String常用方法的测试

1.6 String与基本数据类型的转换

字符串类型转成基本数据类型、包装类:

Integer包装类的public static int parseInt(String str)可以将由”数字“字符组成的字符串转成整形。类似的,使用Java.Lang包中的Byte、Short、Long、Float、Double类调用相应的类方法可以将由”数字“字符组成的字符串转成相应的基本数据类型。(int sum=Integer.parseInt(String str))

基本数据类型、包装类转成字符串类型:

调用String类型的public String valueOf(int number)可以将int类型转成字符串。相应的valueOf(byte b)、valueOf(long l)、valueOf(short s)、valueOf(float f)、valueOf(double d)、valueOf(boolean b)可以由参数的相应类型转换成字符串

 

 @Test
    public void test4(){
        String str="123";
        int sum=Integer.parseInt(str);
        System.out.println(sum);

        String str1=String.valueOf(sum);
        String str2=sum+"";

        System.out.println(str == str2);

    }
String与基本数据类型的转换

 

1.7 String与char[]之间的转换

  1. string-->char[]:调用string的toCharArray()方法
  2. char[]-->string:调用string的构造器
@Test
    public void test5(){
        String str="abc123";
        //string转换成char数组
        char[] chars = str.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            System.out.println(chars[i]);
        }
        //char数组转换成string
        char[] chars1=new char[]{'h','e','l','l','o'};
        String s = new String(chars1);
        System.out.println(s);
    }
String与char数组之间的转换

1.8 String与字节数组byte[]之间的转换

编码:string转成bytes数组,将看的懂的字符串转成看不懂的二进制,调用string的getBytes方法

解码:bytes数组转成string,将看不懂的二进制转成看得懂的字符串,调用string的构造器

 @Test
    public void test6() throws UnsupportedEncodingException {
        String str = "aabc北京欢迎您";
        //编码:string转换成byte数组.调用String的getBytes()方法
        //此时不带参数,中文转成字节使用了默认的编码集(我的是utf-8),在utf-8中,一个汉字占三个字节
        byte[] bytes = str.getBytes();
            /*
            编码:字符串-->字节(看得懂-->看不懂的二进制)
            解码:编码的逆过程(看不懂的二进制-->看得懂)
            * */
        //gbk中一个汉字占两个字节
        byte[] gbks = str.getBytes("gbk");  //使用指定的编码集进行编码
        System.out.println(Arrays.toString(gbks));

        System.out.println(Arrays.toString(bytes));
        System.out.println("*************************");
        //解码:byte数组转换成String:调用String的构造器
        String string = new String(bytes);//使用默认的字符集解码
        System.out.println(string);
        String s = new String(gbks);//此时由于编码时的字符集和解码时的字符集不同,所以会出现乱码
        System.out.println(s);
        String s1 = new String(gbks,"gbk");//指定解码集进行解码
        System.out.println(s1);
    }
编码解码

注意:编码和解码时使用的字符集要做保证一致,否则会出现乱码的情况

1.9 String中常见的一些算法题目

1.10 StringBuffer和StringBuilder

二者类似,区别在于StringBuffer的内部方法是同步的,因此是线程安全的,但是效率较低,StringBuilder的内部方法不是同步的,线程不安全,但是效率较高。

关于扩容问题:StringBuffer和StringBuilder是一样的,底层源码中,如果开发者没有定义StringBuffer的长度,默认为16,当开发者append后的数据长度大于16,此时会扩容到原有长度的2倍+2.同时将原数组的元素复制到新的数组中,如果还不够会继续扩容。StringBuffer中的构造器有多个,详情请看源码,这里不一一举例。

 public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
//**********************************
private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }
//**********************************
private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }
部分源码

 

1.11 String、StringBuffer、StringBuilder(jdk5.0新增的)三者的异同

  1. String:是不可变的,底层使用被final定义的char[]数组来存储数据
  2. StringBuffer:是可变的序列,底层使用char[]数组来存储数据,但是StringBuffer中的方法都是使用synchronized修饰的,因此是线程安全的,但是效率比较低
  3. StringBuilder:是可变序列,与StringBuffer类似,唯一的区别是StringBuilder中的方法不是同步方法,因此是线程不安全的,但是效率较高

在不涉及线程安全的情况下,尽量使用StringBuilder,可以提高效率

 1.12 StringBuffer中的常用方法(StringBuilder同样)

  1. StringBuffer append(xxx):提供了很多append方法,用于进行字符串拼接
  2. StringBuffer delete(int start,int end):(左闭右开)删除指定位置的字符串
  3. StringBuffer replace(int start,int end,String str):(左闭右开)替换指定位置的字符串
  4. StringBuffer insert(int offset,xxx):在指定位置插入xxx
  5. StringBuffer reverse():反转当前字符串
  6. public int indexOf(String str):返回指定字符串首次出现的位置
  7. public String substring(int start,int end):截取指定位置的字符串(左闭右开)
  8. public int length():返回当前字符串的长度(不是底层的char[]长度,是已经存储数据的长度)
  9. public char charAt(int n):返回指定索引处的字符
  10. public void setCharAt(int n,char ch):将指定索引处的字符替换

2. JDK8之前的时间日期API

java.lang.System:

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

java.util.Date:

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

构造器:

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

Date(long date):创建指定毫秒数的date对象

常用方法:

getTime():返回自1970年...以来此date对象表示的毫秒数

toString():将此Date对象转换成String:dow mon dd hh:mm:ss zzz yyy(dow是一周中的某一天,zzz是时间标准)

还有一些其他方法,不过大多都过时了。

java.text.SimpleDateFormat:

该类允许进行格式化:日期-》文本,解析:文本-》日期。

格式化:

SimpleDateFormat():默认的环境和语言创建对象。

public SimpleDateFormate(String pattern):该构造方法可以使用参数pattern指定的格式创建一个对象

public String format(Date date):方法格式化时间对象。

解析:

public Date parse(String source):从给定字符串的开始解析文本,生成一个日期。

java.util.Calendar:

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

实例化:

方式一:使用Calendar.getInstance()方法。

方式二:使用子类GregorianCalendar的构造器。

常用方法:

public int get(int filed):获取一些常用的属性信息,比如当前时间使本月第几天、本年第几个月第几天....

public void set(int filed,int value):可以将指定的属性设置为一个新的值

public void add(int filed,int amount):在原有的基础上增加amount天

public final Date getTime():把一个日历类转成一个date对象。

public final void setTime(Date date):将date对象转成日历类。

注意:获取月份时,一月为0,二月为1...十二月为11。获取星期时,周日为1,周一为二...周六为7.

 

package com.summer.java;

import org.junit.Test;

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

/**
 * @Author 安宁侯
 * @create 2021-03-07 17:56
 */
public class MyDate {
    //system中的currentTimeMillis()
    @Test
    public void test1(){
        long l = System.currentTimeMillis();
        //时间戳:返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差
        System.out.println(l);
    }
    /*
    java.util.Date类
        |:java.sql.Date类(子类)
    1.两个构造器的使用
    2.两个方法的使用
        >toString:显示当前年月日时分秒
        >getTime:获取当前时间距离70年的毫秒数
     */
    @Test
    public void test2(){
        //构造器一:返回的是当前时间的date的对象
        Date date1 = new Date();
        System.out.println(date1.getTime());//1615111914016
        System.out.println(date1.toString());//Sun Mar 07 18:10:20 CST 2021Sun Mar 07 18:10:20 CST 2021
        //构造器二:创建指定毫秒数的date对象
        Date date = new Date(1615111914016l);
        System.out.println(date);
    }
    /*
    java.text.SimpleDateFormat类
    两个操作
    1.格式化:从date转成String
    2.解析:格式化的逆过程,从String转成date
     */
    @Test
    public void test3() throws ParseException {
        //类的实例化:使用默认的构造器
        SimpleDateFormat format = new SimpleDateFormat();

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

        //解析:字符串-->日期(要求字符串格式为:21-3-7 下午8:08)
        String str="21-3-7 下午8:08";
        Date date1 = format.parse(str);
        System.out.println(date1);

        System.out.println("**********按照指定方式格式化*****************");
        //实例化二:带参构造器,指定格式(年-y,月-M,天-d,时-h,分-m,秒-s)
        SimpleDateFormat format1 = new SimpleDateFormat("GGG yyyy-MM-dd aaa hh:mm:ss ");
        String s1 = format1.format(new Date());
        System.out.println(s1);

        //解析:要求字符串必须符合format1的格式(通过构造器体现的)否则就会抛异常
        Date date2 = format1.parse(s1);
        System.out.println(date2);
    }
    /*
    练习一:将字符串“2020-08-09”转成java.sql.Date
     */
    @Test
    public void test4() throws ParseException {
        String birth="2020-08-09";
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = format.parse(birth);
        java.sql.Date date1 = new java.sql.Date(date.getTime());
        System.out.println(date1);
    }
    /*
    练习二:三天打鱼两天晒网,从1990-01-01开始,问2019-08-04渔夫在干什么?
     */
    @Test
    public void test5() throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = format.parse("1990-01-01");
        long time = date.getTime();
        Date date1 = format.parse("2019-08-04");
        long time1 = date1.getTime();

       // System.out.println(time1-time);
        int days= (int)((time1-time)/(1000*60*60*24)+1);

       // System.out.println(1000*60*60*24);
       // System.out.println(days);
        if (days%5==1||days%5==2||days%5==3)
            System.out.println("打鱼");
        else
            System.out.println("晒网");
    }
    /*
    calendar
     */
    @Test
    public void test6(){
        //实例化方式一:调用getInstance()方法
        Calendar instance = Calendar.getInstance();
        //get()
        int i = instance.get(Calendar.DAY_OF_MONTH);
        System.out.println(i);
       //set()
        instance.set(Calendar.DAY_OF_MONTH,22);
        i=instance.get(Calendar.DAY_OF_MONTH);
        System.out.println(i);
       //add()
        instance.add(Calendar.DAY_OF_MONTH,11);//加上负数相当于减去几天
        i=instance.get(Calendar.DAY_OF_MONTH);
        System.out.println(i);
        //getTime()
        Date time = instance.getTime();
        System.out.println(time);
        //setTime()
        Date date = new Date();
        instance.setTime(date);
        i=instance.get(Calendar.DAY_OF_MONTH);
        System.out.println(i);
        //实例化方式二:使用子类GregorianCalendar
//        GregorianCalendar calendar = new GregorianCalendar();
    }
}
JDK8之前日期API代码

 

3. JDK8中的时间日期API

LocalDate、LocalTime、LocalDateTime:

其中LocaclDateTime的使用频率要比另外两个类的使用频率高

三种类的实例化:now(),of()

一些常用方法:

getXxx():获取相关属性...

withXxx():设置相关属性(需要注意的是,此时只是返回结果改变了,本身并没有改变,体现了不可变习性,与Calendar类不同)...

plusXxx():在原有基础上添加了多少(同样是返回值改变,也体现了不可变性)...

minusXxx():在原有基础上减少了多少(与plusXxx一样体现了不可变性)...

Instant类:

时间线上的一个时间点。可能被用来记录应用程序中某个事件的时间戳。类似于java.util.Date类。

java.time.format.DateTimeFormatter:

日期时间格式化的类,类似于SimpleDateFormat。

 

 /*
    LocalDate,LocalTime,LocalDateTime
     */
    @Test
    public void test7(){
      //now():获取当前的的日期,时间,日期+时间
        LocalDate now = LocalDate.now();
        LocalTime time = LocalTime.now();
        LocalDateTime dateTime = LocalDateTime.now();
        System.out.println(now);
        System.out.println(time);
        System.out.println(dateTime);

        //of():设置指定的年月日时分秒,没有偏移量
        LocalDateTime localDateTime = LocalDateTime.of(2021, 3, 7, 23, 23, 23);
        System.out.println(localDateTime);

        //getXxx()
        System.out.println(dateTime.getDayOfMonth());
        System.out.println(dateTime.getDayOfWeek());
        //with
    }
    @Test
    public void test8(){
        //now()获取的是本初子午线的便准时间
        Instant now = Instant.now();
        System.out.println(now);//2021-03-07T16:13:22.828Z(本初子午线的时间,与北京相差八个小时)
       //添加偏移量
        OffsetDateTime time = now.atOffset(ZoneOffset.ofHours(8));
        System.out.println(time);//2021-03-08T00:16:51.963+08:00
        //获取对应毫秒数(与1970年01月01日对比)
        long l = now.toEpochMilli();
        System.out.println(l);
        //通过给定的毫秒数,获取一个instant实例
        Instant instant = Instant.ofEpochMilli(1883247479l);
        System.out.println(instant);
    }
    @Test
    public void test9(){
        //实例化方式一:预定义的标准格式
       DateTimeFormatter date= DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        LocalDateTime now = LocalDateTime.now();
        String format = date.format(now);//格式化:日期-->字符串
        System.out.println(now);
        System.out.println(format);
        //解析
        TemporalAccessor parse = date.parse(format);
        System.out.println(parse);
        //实例化方式二:
       // DateTimeFormatter time = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
        //DateTimeFormatter time = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
        DateTimeFormatter time = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
        String format1 = time.format(now);
        System.out.println(format1);
        //实例化方式三:重点:使用的比较多
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
        String format2 = pattern.format(now);
        System.out.println(format2);
        TemporalAccessor parse1 = pattern.parse(format2);
        System.out.println(parse1);

    }
相关代码

4. Java 比较器

Java中的对象,正常情况下只能进行比较:==或者!=,不能使用>、<。但是在开发场景中,往往涉及到需要对对象进行排序,比如电商网站中对商品的排序。这个时候就需要我们对对象进行比较大小的操作,这个要如何实现呢?

Java 中涉及对象排序的方式有两种:

自然排序:Java.lang.Comparable

定制排序:Java.util.Comparator

Comparable的使用:自然排序

像String、包装类等实现了Comparable接口,重写了compareTo()方法,默认情况下是从小到大排列的,给出了比较两个对象大小的方式。

重写compareTo(Object obj)方法的规则:

如果当前对象this大于形参对象obj,返回正整数。

如果当前对象this小于形参对象obj,返回负整数。

如果当前对象this等于形参对象obj,返回0。

对于自定义类来说,如果想实现对象的排序,可以通过实现comparable接口,重写compareTo()方法来实现。在compareTo()方法中指定如何排序

 

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;
            return Double.compare(this.price,goods.price);
        }
        throw new RuntimeException("传入的数据类型不一致!");
    }
}
重写comparable接口

 

Comparator的使用:定制排序

当元素的类型没有实现Java.lang.Comparable接口又不方便修改代码,或者实现了Comparable接口但是对排序方式不太满意,这个时候可以考虑使用java.util.Comparator的对象来进行定制排序。重写compare(Object obj1,Object obj2)方法。如果方法返回正整数,说明obj1大于obj2,如果方法返回负整数,说明obj1小于obj2,如果方法返回0,说明obj1等于obj2。

//定制排序
        Arrays.sort(myGoods,new Comparator(){

            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Goods && o2 instanceof Goods){
                    Goods goods1= (Goods) o1;
                    Goods goods2= (Goods) o2;
                    if (goods1.getName().equals(goods2.getName())){
                        return -Double.compare(goods1.getPrice(),goods2.getPrice());
                    }else
                        return goods1.getName().compareTo(goods2.getName());
                }
               throw new RuntimeException("数据类型不一致!");
            }
        });
        System.out.println(Arrays.toString(myGoods));
重写compare方法

Comparable接口与Comparator使用的对比:

Comparable接口一旦指定,可以保证实现类的对现象可以在任何位置都进行比较。Comparator属性临时性的定义,每次使用都需要定义。

public class CompareTest {
    @Test
    public void test(){
        //comparable的使用举例:自然排序
        //像String、包装类等继承了Comparable类,重写了compareTo()方法,按照从小到大排列
        /*
        重写compareTo的规则:
            如果当前对象this大于系形参obj,则返回正数,小于返回负数,等于返回0。
        对于自定义类的对象需要排序,需要重写compareTo方法,并指明如何排序
         */
        String[] str=new String[]{"aa","cc","mm","gg","jj","dd","zz","kk"};

        Arrays.sort(str);
        System.out.println(Arrays.toString(str));
    }
    @Test
    public void goodsTest(){
        Goods[] myGoods=new Goods[4];
        myGoods[0]=new Goods("戴尔",4999);
        myGoods[1]=new Goods("华硕",7999);
        myGoods[2]=new Goods("联想",5999);
        myGoods[3]=new Goods("苹果",14999);
//自然排序
//        Arrays.sort(myGoods);
//        System.out.println(Arrays.toString(myGoods));
       //定制排序
        Arrays.sort(myGoods,new Comparator(){

            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Goods && o2 instanceof Goods){
                    Goods goods1= (Goods) o1;
                    Goods goods2= (Goods) o2;
                    if (goods1.getName().equals(goods2.getName())){
                        return -Double.compare(goods1.getPrice(),goods2.getPrice());
                    }else
                        return goods1.getName().compareTo(goods2.getName());
                }
               throw new RuntimeException("数据类型不一致!");
            }
        });
        System.out.println(Arrays.toString(myGoods));
    }
    /*
    定制排序:comparator
     */
    @Test
    public void test1(){
        String[] str=new String[]{"aa","cc","mm","gg","jj","dd","zz","kk"};
        Arrays.sort(str, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return -o1.compareTo(o2);
            }
        });
        System.out.println(Arrays.toString(str));
    }
}
代码总结

 

 

posted @ 2020-06-08 20:12  云入山涧  阅读(272)  评论(0编辑  收藏  举报