Java常用工具类汇总 附示例代码


Posted in Java/Android onJune 26, 2021

Java常用类

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

String类

  • 概述
  • String类:代表字符串。Java程序中的所有字符串字面值(如:”abc“)都作为子类的实例实现
  • String是一个final类,代表不可变的字符序列
  • 字符串是常量,用双引号引起来表示。他们的值在创建之后不能更改
  • String对象的字符内容是存储在一个字符数组value[]中的
public final class String
    implements java.io.Serializable,Comparable<String>,CharSequence{
    /** The value is used for character storage*/
    private final char value[]; //String 的底层就是放在char型数组当中(字符构成的串) //final:value是引用类型 其指向的地址不可以被修改
    /*Cache the hash code for the string*/
    private int hash; //Default to 0
}
/*
    String:字符串:使用一对“”引起来表示
    1. String声明为final的,不可被继承
    2. String
        实现了Serializable接口:表示字符串是可序列化的
    (对象默认不可以通过网络传输,但是如果是可序列化的,那么就可以通过网络传输给对方 IO流部分知识)
        实现了Comparable接口,表示String是可以比较大小的
    3. String在内部定义了final的char型数组:final char value[] value用与存储字符串数据
    4. 通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中
    5. 字符串常量池中是不会存储相同内容的字符串的
     */
  • String不可变性
  • 说明以及代码
/*4. final:数组引用变量不能在指向别的数组,且数组对象内的元素也不能改变
      即const int* const p; p是常量指针,且不能通过p对所指向的变量进行修改
    体现
        1)当对字符串重新赋值是,需要重写指定内存区域赋值,不能使用原有的value进行赋值
        2) 当对现有的字符串进行连接操作时,也需要重新制定内存区域赋值,不能使用原有的字符串*/
@Test
    public void test(){
        String s1 = "abc";//字面量的定义方式
        String s2 = "abc";
        System.out.println(s1==s2);//true
        //        s1="hello";
        String s3 = "abc";
        s3+="def";//并没有改变“abc” 而是新造了一个
        System.out.println(s3); //abcdef  并没有改变“abc” 而是新造了一个
        System.out.println(s2);//abc
        System.out.println("******************");
        String s4 = "abc";
        String s5 = s4.replace('a','z');
        System.out.println(s5);
        System.out.println(s4);
        System.out.println(s2);
    }

Java常用工具类汇总 附示例代码

//String 实例化的方式
  //  方式一:通过字面量定义的方式
  //  方式二:通过new+构造器的方式
@Test
    public void test2(){
        //通过字面量的方式 这个abc声明在方法区的字符串常量池种
        String s1 = "abc";
        String s2 = "abc";
        //通过new+构造器的方式:此时的s3,s4保存的地址值,是数据在堆空间中开辟空间以后堆空间中地址值
        String s3 = new String("abc");
        String s4 = new String("abc");
        System.out.println(s1==s2); //true
        System.out.println(s1==s3); //false
        System.out.println(s3==s2); //false
        System.out.println("********************");
        Person p1 = new Person("shc");
        Person p2 = new Person("shc");
        System.out.println(p1.name.equals(p2.name));//true
        System.out.println(p1.name==p2.name);//true 因为在Person的对象中,生成String字符串的方式也是通过字面量 this.name="shc"
        //如果在Peron的构造器中用this.name=new String("shc"); 的方式,那么就是false
    }

面试题

面试题:!!!常考 String s = new String("abc"); 方式创建对象,在内存中创建了几个对象 两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:"abc";

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

  • 字符串拼接方式的对比
/*
    1. 常量与与常量的拼接结果在常量池中,且常量池中不会存在相同内容的常量
    2. 只要其中有一个是变量,结果就在堆中
    3. 如果拼接的结果调用intern()方法,返回值就在常量池中
     */
@Test
    public void test3(){
        String s1 = "abc";
        String s2 = "hhh";
        String s3 = "abchhh"; //字面量
        String s4 = "abc"+"hhh"; //两个字面量的连接 还是字面量 在常量池中
        String s5 = s1+"hhh";
        String s6 = "abc" + s2;
        String s7 = s1+s2;
        System.out.println(s3==s4); //true
        System.out.println(s3==s5); //false
        System.out.println(s3==s6); //false
        System.out.println(s3==s7); //false
        System.out.println(s5==s6); //false
        System.out.println(s5==s7); //false
        System.out.println(s6==s7); //false
        String s = s5.intern();
        System.out.println(s==s3);//true
    }
  • String用方法
/**
 *  int length():返回字符串的长度: return value.length
 *  char charAt(int index): 返回某索引处的字符return value[index]
 *  boolean isEmpty():判断是否是空字符串:return value.length == 0
 *  String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写
 *  String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
 *  String trim():返回字符串的副本,忽略前导空白和尾部空白
 *  boolean equals(Object obj):比较字符串的内容是否相同
 *  boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
 *  String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
 *  int compareTo(String anotherString):比较两个字符串的大小
 *  String substring(int beginIndex):返回一个新的字符串,它是此字符串的从
 * beginIndex开始截取到最后的一个子字符串。
 *  String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字
 * 符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
 *
 *  boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
 *  boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
 *  boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的
 * 子字符串是否以指定前缀开始
 *
 *  boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
 *  int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
 *  int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出
 * 现处的索引,从指定的索引开始
 *  int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
 *  int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
 * 注:indexOf和lastIndexOf方法如果未找到都是返回-1
 *
 *  String replace(char oldChar, char newChar):返回一个新的字符串,它是
 * 通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
 *  String replace(CharSequence target, CharSequence replacement):使
 * 用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
 *  String replaceAll(String regex, String replacement) : 使 用 给 定 的
 * replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
 *  String replaceFirst(String regex, String replacement) : 使 用 给 定 的
 * replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
 *
 * boolean matches(String regex):告知此字符串是否匹配给定的正则表达式
 *
 *  String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
 *  String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此
 * 字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
 * @author shc
 * @create 2021-05-20 15:06
 */
  • String与其他结构的转换
    • 与基本数据类型,包装类之间的转换
/*
    String与基本数据类型,包装类之间的转换
    String --> 基本数据类型,包装类 :调用基本数据类型的 parseXxx(str);
    基本数据类型,包装类 ---> String :调用String类重载的valueOf(xxx); 或者直接+""
    */
@Test
  public void test(){
      String str = "123";
//        int num = (int) str; //必须是子父类的关系才可以强转
      int num = Integer.parseInt(str); //注意str中不能有数字 否则NumberFormatException
      System.out.println(num);
      String str1 = String.valueOf(num);
      String str2 = num+"";
      System.out.println(str1+" "+str2);
  }

String与字符数组之间的转换

/*
  String与char[]之间的转换
  String -->char[] 调用String的toCharArray()
  char[] -->String 调用String的构造器
   */
@Test
  public void test2(){
      String str1 = "abc123";
      char[] charArray = str1.toCharArray();
      for(int i=0;i<charArray.length;i++){
          System.out.print(charArray[i]+" ");
      }
      char[] arr = new char[]{'h','e','l','l','o'};
      String str = new String(arr);
      System.out.println(str);
  }

String与字节数组之间的转换

/*
  String与byte[]之间的转换
  编码:String --> byte[]:调用String的getBytes()
  解码:byte[] --> String
  编码:字符串 --> 字节 (看得懂 --> 看不懂)
  解码:编码的逆过程 字节 --> 字符串 (看不懂的二进制 --> 看得懂)
  说明:要求编码时使用的字符集和解码时使用的字符集必须一致
   */
@Test
  public void test3() throws UnsupportedEncodingException {
      String str1 = "abc123中国";
      byte[] bytes = str1.getBytes();//使用默认的字符集。进行转换
      System.out.println(Arrays.toString(bytes));
      byte[] gbks = str1.getBytes("gbk");//使用gbk字符集进行编码
      System.out.println(str1);
      System.out.println(Arrays.toString(gbks));
      System.out.println("****************");
      String str2 = new String(bytes);//使用默认字符集进行解码
      System.out.println(str2);
      String gbks1 = new String(gbks);
      System.out.println(gbks1);//乱码
  }

与StringBuilder,StringBuffer之间的转换

String --> StringBuffer、StringBuilder:调用StringBuffer、StringBuilder构造器
StringBuffer、StringBuilder --> String:
  		①调用String构造器
  		②StringBuffer、StringBuilder的toString()
/*
  String、StringBuilder、StringBuffer三者异同?
  String:不可变的字符序列 ,char型数组存储
  StringBuffer:可变的字符序列:线程安全,效率偏低,char型数组存储
  StringBuilder:可变的字符序列:jdk5.0新增 线程不安全,效率高,char型数组存储
  三者效率:StringBuilder > StringBuffer > String
  源码分析:
  String str = new String(); //char[] value = new char[0];
  String str1 = new String("abc);//char[] value = new char[]={'a','b','c'};
  StringBuffer sb1 =  new StringBuffer();//char[] value = new char[16];//底层创建了一个长度为16的字符串数组
  sb1.append('a');//value[0]='a';
  sb1.append('b');//value[1]='b';
  StringBuffer sb2 = new String("abc"); //char[] value = new char["abc".length()+16];
    QUESTION 1:sout(sb2.length()); //"abc".length;
             2:扩容问题:如果要添加的数据底层数组撑不下了,就要扩容底层的数组
             默认情况下,扩容为原来容量的2倍+2,同时将原有数组中的元素复制到新的数组中。
             指导意义:开发中建议大家使用:StringBuffer(int capacity)或者(StringBuilder(int capacity) 尽量避免扩容,影响效率
   */
  @Test
  public void test(){
      StringBuffer str1 = new StringBuffer("abc");
      str1.setCharAt(0,'n');
      System.out.println(str1);
  }

JVM中字符常量池存放位置说明:

  • jdk 1.6(jdk 6.0,java 6.0):字符串常量池储存在方法区(永久区)
  • jdk 1.7:字符串常量池存储在堆空间
  • jdk 1.8:字符

StringBuilder,StringBuffer

public class StringBuilderBufferTest {
    /*
    String、StringBuilder、StringBuffer三者异同?
    String:不可变的字符序列 ,char型数组存储
    StringBuffer:可变的字符序列:线程安全,效率偏低,char型数组存储
    StringBuilder:可变的字符序列:jdk5.0新增 线程不安全,效率高,char型数组存储
    三者效率:StringBuilder > StringBuffer > String
    源码分析:
    String str = new String(); //char[] value = new char[0];
    String str1 = new String("abc);//char[] value = new char[]={'a','b','c'};
    StringBuffer sb1 =  new StringBuffer();//char[] value = new char[16];//底层创建了一个长度为16的字符串数组
    sb1.append('a');//value[0]='a';
    sb1.append('b');//value[1]='b';
    StringBuffer sb2 = new String("abc"); //char[] value = new char["abc".length()+16];
      QUESTION 1:sout(sb2.length()); //"abc".length;
               2:扩容问题:如果要添加的数据底层数组撑不下了,就要扩容底层的数组
               默认情况下,扩容为原来容量的2倍+2,同时将原有数组中的元素复制到新的数组中。
               指导意义:开发中建议大家使用:StringBuffer(int capacity)或者(StringBuilder(int capacity) 尽量避免扩容,影响效率
     */
    @Test
    public void test(){
        StringBuffer str1 = new StringBuffer("abc");
        str1.setCharAt(0,'n');
        System.out.println(str1);
    }
}
/*
* StringBuffer类不同于String,其对象必须使用构造器生成。有三个构造器:
    StringBuffer():初始容量为16的字符串缓冲区
    StringBuffer(int size):构造指定容量的字符串缓冲区
    StringBuffer(String str):将内容初始化为指定字符串内容
常用方法
    StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
    StringBuffer delete(int start,int end):删除指定位置的内容
    StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
    StringBuffer insert(int offset, xxx):在指定位置插入xxx
    StringBuffer reverse() :把当前字符序列逆转
*   public int indexOf(String str)
    public String substring(int start,int end)
    public int length()
    public char charAt(int n )
    public void setCharAt(int n ,char ch)
*
* 总结
    * 增 append(x)
    * 删 delete(int start,int end)
    * 改 setCharAt(int n,char ch) / repalce(int start,int end,String str)
    * 查 charAt(int n)
    * 插 insert(int offset,xxx)
    * 长度 length()
    * 遍历 for()+charAt() / toString()
*
 */

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

面试题

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

JDK8之前的时间API

获取当前系统时间java.lang.System类中的currentTimeMillis()

long time = System.currentTimeMillis();
//返回时间为当前时间与1970年1月1日00:00之间以ms为单位的时间差,称为时间戳
System.out.println(time);
//1621602510493

java.util.Datejava.sql.Date

java.sql.Date extends java.util.Date

/*
    2. java.util.Date类
    ① 两个构造器的使用
        >构造器一:Date()创建一个对应当前时间的Date对象
        >构造器二:创建指定毫秒数(指定时间戳)的Date对象
    ② 两个方法的使用
        >toString():显示当前的年、月、日、时、分、秒
        >getTime();获取当前Date对象的时间戳
    ③  java.sql.Date类 extends java.util.Date
        >如何实例化
        >如何将java.util.Date对象转化为java.sql.Date对象
     */
    @Test
    public void test2(){
        //构造器一:Date()创建一个对应当前时间的Date对象
        Date date1 = new Date();
        System.out.println(date1.toString());//Fri May 21 21:07:33 CST 2021
        System.out.println(date1.getTime());//1621602495849
        //构造器二:创建指定毫秒数的Date对象
        Date date2 = new Date(1621602495849L);
        System.out.println(date2.toString());//FriMay 21 21:08:15 CST 2021
        //或者直接date2也一样,因为sout就是会调用toString啊。
        //这可不是把Date类对象转化成String类对象了!!!!!!!
        System.out.println("*****************");
        //创建java.sql.Date对象
        java.sql.Date date3 = new java.sql.Date(323156136L);
        System.out.println(date3);//1970-01-05
        //如何将java.util.Date对象转化为java.sql.Date对象
        //情况1:(Java多态)
        Date date4 = new java.sql.Date(1235346456L);
        java.sql.Date date5 = (java.sql.Date)date4;
        //情况2:
        Date date6 = new Date();
        java.sql.Date date7 = new java.sql.Date(date6.getTime());
        //而不能是java.sql.Date date7 = (java.sql.Date)date6;
    }

java.text.SimpleDateFormat

用处:SimpleDateFormat对日期Date类的 格式化和 解析(Date里还有很多方法被@Deprecated了)(JDK8建议用Calendar)

  • (1)两个操作
    • 1.1: 格式化:日期(Date) --> 字符串(String)
    • 1.2: 解析:格式化的逆过程:字符串(String) --> 日期(Date)
  • (2)SimpleDateFormat的实例化:new+构造器.
    • 基本操作
//1. 实例化SimpleDateFormat
    SimpleDateFormat sdf = new SimpleDateFormat();
    //2. 格式化:日期 (Date)--> 字符串(String)
    Date date = new Date(); //Date()创建一个对应当前时间的Date对象
    System.out.println(date);// Sat May 22 19:50:32 CST 2021
    String format = sdf.format(date); // SimpleDateFormat对Date进行解析,获得字符串:21-5-22 下午7:50
    System.out.println(format); // 输出解析后得到的字符串 21-5-22 下午7:50
    //解析:格式化的逆过程。字符串(String) ---> 日期(Date)
    String str = "21-5-22 下午7:49";
    Date date1 = sdf.parse(str);//可能导致编译异常原因:字符串格式不对
    System.out.println(date1);//Sat May 22 19:49:00 CST 2021

(3)以下为开发中主要方式 --> 按照指定方式格式化和解析 :调用带参构造器

//开发中通常不用默认构造器,而是用指定的构造器来确定格式化方式
        //SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa");
        //年 yyyy -- 月 MM (大写是为了和分钟mm区分开) -- 天 dd -- 时 hh -- 分钟 mm -- 秒 ss
        //1. 实例化    
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd ---- hh:mm:ss");
		//2. 格式化
        String format2 = sdf2.format(date);//以我们制定的yyyy-MM-dd ---- hh:mm:ss格式来进行转化
        System.out.println(format2);//2021-05-23 ---- 01:22:21
		//3. 解析:
		//要求字符串必须是符合SimpleDateFormat识别的格式(通过构造器参数体现),否则就会抛出异常
        Date date2 = sdf2.parse("2021-05-23 ---- 01:22:21");
        System.out.println(date2);//Sun May 23 01:22:21 CST 2021

Calendar类:日历类,抽象类

/*
    Calendar日历类(抽象类)的使用
     */
    @Test
    public void testCalendar(){
        //1.实例化
        //方式一:创建其子类(GregorianCalendar)的对象
        //方式二:调用其静态方法getInstance();
        Calendar calendar = Calendar.getInstance();
        System.out.println(calendar.getClass());//class java.util.GregorianCalendar
        //2.常用方法
        //get()
        System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//23
        System.out.println(calendar.get(Calendar.DAY_OF_YEAR));//143
        //set()
        //Calendar劣势:可变性
        calendar.set(Calendar.DAY_OF_MONTH,7);//void set() 把Calendar本身给改了
        System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//7
        //add()
        calendar.add(Calendar.DAY_OF_MONTH,-3);//4
        System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
        //getTime():日历类 ---> Date
        Date date = calendar.getTime();
        System.out.println(date);//Tue May 04 13:45:07 CST 2021
        System.out.println("****************");
        //setTime():Date --> 日历类
        Date date1 = new Date();
        calendar.setTime(date1);
        System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//23
  • JDK8中新的API
    • 日期时间API的迭代
    • 第一代:jdk 1.0 Date类
    • 第二代:jdk 1.1 Calendar类,一定程度上替换Date类
    • 第三代:jdk1.8提出了新的一套API(最终版)
  • 前两代存在的问题
    • 可变性:像日期和时间这样的类应该是不可变的。
    • 偏移性:Date中的年份是从1900开始的,而月份都从0开始。
    • 格式化:格式化只对Date有用,Calendar则不行。
    • 此外,它们也不是线程安全的;不能处理闰秒等。

Java常用工具类汇总 附示例代码

本地日期、本地时间、本地日期时间的使用:LocalDate、LocalTime、LocalDateTime

  • 说明:
    • LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。
    • LocalTime表示一个时间,而不是日期。
    • LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一。
  • 常用方法:

Java常用工具类汇总 附示例代码

时间点:Instant

  • 说明:
    • Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。 概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒 数。
    • 类似于java.util.Date类
  • 常用方法

Java常用工具类汇总 附示例代码

  • 日期时间格式化类:DateTimeFormatter

说明

  • 格式化、解析日期,时间
  • 类似于SimpleDateFormat

常用方法

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

Java常用工具类汇总 附示例代码

特别的,自定义格式,如:如:ofPattern(“yyyy-MM-dd hh:mm:ss”)*

//方式三:自定义的格式。如: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-22 11:07:16
        //解析:
        TemporalAccessor accessor = formatter3.parse("2021-05-22 03:06:09");
        System.out.println(accessor);
        //{NanoOfSecond=0, MilliOfSecond=0, MinuteOfHour=6, SecondOfMinute=9, MicroOfSecond=0, HourOfAmPm=3},ISO resolved to 2021-05-22
    }

其他常用类

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码

Java常用工具类汇总 附示例代码Java常用工具类汇总 附示例代码Java常用工具类汇总 附示例代码

package com.shc.java1;
import org.junit.Test;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
 * 1. System
 * 2. Math
 * 3. BigInteger BigDecimal
 * @author shc
 * @create 2021-05-23 12:29
 */
public class OtherTest {
    @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);
    }
    @Test
    public void test2(){
        BigInteger bi = new BigInteger("12433241123");
        BigDecimal bd = new BigDecimal("12435.351");
        BigDecimal bd2 = new BigDecimal("10");
        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, 20, BigDecimal.ROUND_HALF_UP)); //scale:小数位位数 支持任意精度的小数位
    }
}

Java比较器·

引入

* 说明:Java中的对象中,正常情况下,只能进行比较:== 或者 != 不能使用>或者<的
 *      但是在开发场景中,我们需要对多个对象进行排序,言外之意,就是要比较对象的大小
 *      如何实现? 使用两个接口中的任何一个:Comparable 或 Compare任意一个

自然排序Comparable

说明

/*
    Comparable接口使用举例:自然排序
    1. 像String、包装类等实现了Comparable接口,重写compareTo()方法,给出比较两个对象大小的方式
    2. 像String、包装类重写了compareTo方法以后,进行了从小到大的排列
    3. 重写compareTo()的规则
    如果当前对象this大于形参对象obj,则返回正整数,
    如果当前对象this小于形参对象obj,则返回负整数,
    如果当前对象this等于形参对象obj,则返回零。
    4. 对于自定义类来说,如果需要排序,我们可以自定义类实现Comparable接口,重写compareTo方法,
        在compareTo(obj)指明如何排序。
     */

代码举例

/**
 * 商品类
 * @author shc
 * @create 2021-05-23 10:57
 */
public class Goods implements Comparable{
    private String name;
    private double price;
    //指明商品比较方式,先按照价格递增,再按照名字递增
    @Override
    public int compareTo(Object o){
        System.out.println("==================");
        if(o instanceof Goods){
            Goods good = (Goods) o;
            if(good.price<this.price){
                return 1;
            }else if(good.price>this.price){
                return -1;
            }else{
                return this.name.compareTo(good.name); //再按照名字排序
//                return 0;
            }
            //方式二
//            return Double.compare(this.price,((Goods)o).price);
        }
         throw new RuntimeException("传入数据类型不一致错误");
    }
}
    @Test
    public void test2(){
        Goods[] goods = new Goods[5];
        int x = goods.length;
        System.out.println(goods.length);//5 是数组本身的长度
        goods[0] = new Goods("shubiao",12);
        goods[1] = new Goods("diannao",78);
        goods[2] = new Goods("erji",10);
        goods[3] = new Goods("xianshiqi",1);
        goods[4] = new Goods("xian",1);
        Arrays.sort(goods,0,goods.length);
        for(int i=0;i<goods.length;i++){
            System.out.println(goods[i]);
        }
    }
/*sort方法时回调用compareTo*/
==================
==================
==================
==================
==================
==================
==================
==================
==================
Goods{name='xian', price=1.0}
Goods{name='xianshiqi', price=1.0}
Goods{name='erji', price=10.0}
Goods{name='shubiao', price=12.0}
Goods{name='diannao', price=78.0}

定制排序 Comparator

引入

  • 当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码, 或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排 序的比较。
    • 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返 回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示 o1小于o2。 l 可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort), 从而允许在排序顺序上实现精确控制。
    • 还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的 顺序,或者为那些没有自然顺序的对象 collection 提供排序。
  • 代码
Arrays.sort(goods,new Comparator(){//接口可以new吗?
            @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());
                    }
                }
                throw new RuntimeException(o1+"输入数据类型错误");
                //如果有一个数组元素为空的话也会走到这里 因为null instanceof Goods 为false 不会进入if
                //如果用的是o1.toString()的话则会是NullPointerException 因为在throwRuntimeException的时候会走到toString()这一步 而null调用toString()则是空指针异常
            }
        });

两种排序方式对比

/* 二、Comparable接口与Comparator的使用的对比
 *  Comparable接口的方式一旦设定,保证了Comparable接口实现类的对象在任意位置都可以比较大小
 *  Comparator接口属于临时性的比较
 */

每日一考

画出如下几行代码的内容结构

String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
s1+="world";   <--->    s1 = s1+"hello"; 右则有变量s1参与,所以拼接结果在堆中

Java常用工具类汇总 附示例代码

  • 如何理解String类的不可变性
  • String类是否可以被继承?为什么?
  • String、StringBuffer、StringBuilder三者对比
  • String的常用方法有哪些?(至少7个)

length()/charAt()/equals()/compareTo()...

  • 每日一考将字符串“2017-08-16”转化为对应的java.sql.Date类的对象(把页面传入的字符串存入数据库中)(是一个解析过程) //其实也可以直接塞进去(但我们一定要会手动转化)
  • 字符串-->java.util.Date date --> longms时间戳- -->java.sql.Date
SimpleDateFormat    
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy--MM--dd");
//	解析(字符串String-->日期Date):
    java.util.Date utilDate = sdf.parse("2021-02-23");
//	再用date来getTime()(返回的是longms),再放入构造器中
	java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
DateTimeFormatter   
    DateTimeFormatterdtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
	..............
实例化方式:
    new +构造器
    单例模式(private构造器)
    Calendar.getInstance()//Calendar是一个抽象类,获取的是他的子类(private构造器)

解释何为编码?解码?何为日期时间的格式化,解析?

编码:字符串 -> 字节

解码:字节 -> 字符串

格式化(format):日期 ->字符串

解析(parse):字符串 -> 日期

自定义Person类如下,如何实现自然排序?(按照名字从小到大)

class Person implements Comparable{
    private String name;
    @Override
    public int compareTo(Object o){
        if(o instanceof Person){
            Person p = (Person) o;
            return this.name.compareTo(p.name);
        }
        throw new Exception("");
    }
}

提供定制排序涉及到的接口的实现类对象,并按Person类的年龄从大到小排序

Comparator cp = new Comparator(){
    @Override
    public int compare(Object obj1,Object obj2){
        if(..)
    }
}

JDK8 之前和 JDK8 中与日期、时间相关的类分别有哪些?

JDK8之前								JDK8
java.util.Date 和 java.sql.Date ---> instant			 (本初子午线的时间)
SimpleDateFormat				--->DateTimeFormatter
Calendar						--->LocalDate,LocalTime,LocalDateTime

IDEA常识

  • 如何删除Module?
    • Remove ---然后-- > Delete
  • 如何导入Module?
    • File--->ProjectStructure--->'+'--->导入
  • IDEA生成构造器
    • Alt+insert
  • 快速查询当前类中某个方法
    • ctrl+F12 再输入方法名
  • 快速查询某个类
    • double shift

总结

这篇文章就到这里了,希望能给大家带来帮助,也希望您能多多关注三水点靠木的更多内容!

Java/Android 相关文章推荐
详解java如何集成swagger组件
Jun 21 Java/Android
SpringBoot集成Redis,并自定义对象序列化操作
Jun 22 Java/Android
详解Spring Boot使用系统参数表提升系统的灵活性
Jun 30 Java/Android
Java Spring 控制反转(IOC)容器详解
Oct 05 Java/Android
关于@OnetoMany关系映射的排序问题,使用注解@OrderBy
Dec 06 Java/Android
Java 获取Word中所有的插入和删除修订的方法
Apr 06 Java/Android
Java设计模式之代理模式
Apr 22 Java/Android
Java 多线程协作作业之信号同步
May 11 Java/Android
Java异常体系非正常停止和分类
Jun 14 Java/Android
Mybatis-plus配置分页插件返回统一结果集
Jun 21 Java/Android
SpringBoot项目部署到阿里云服务器的实现步骤
Jun 28 Java/Android
volatile保证可见性及重排序方法
Aug 05 Java/Android
Java多条件判断场景中规则执行器的设计
Java基于字符界面的简易收银台
springboot集成flyway自动创表的详细配置
idea搭建可运行Servlet的Web项目
Java Dubbo框架知识点梳理
Java实现多线程聊天室
eclipse创建项目没有dynamic web的解决方法
You might like
php IP及IP段进行访问限制的代码
2008/12/17 PHP
用php实现选择排序的解决方法
2013/05/04 PHP
php中apc缓存使用示例
2013/12/25 PHP
PHP中构造函数和析构函数解析
2014/10/10 PHP
PHP检测字符串是否为UTF8编码的常用方法
2014/11/21 PHP
Laravel中使用FormRequest进行表单验证方法及问题汇总
2016/06/19 PHP
php新建文件的方法实例
2019/09/26 PHP
PHPUnit + Laravel单元测试常用技能
2019/11/06 PHP
jQuery 性能优化指南(2)
2009/05/21 Javascript
javascript实现的像java、c#之类的sleep暂停的函数代码
2010/03/04 Javascript
在多个页面使用同一个HTML片段的代码
2011/03/04 Javascript
SuperSlide2实现图片滚动特效
2014/06/20 Javascript
JavaScript中的标签语句用法分析
2015/02/10 Javascript
js 获取本地文件及目录的方法(推荐)
2016/11/10 Javascript
Bootstrap基本插件学习笔记之模态对话框(16)
2016/12/08 Javascript
微信小程序自定义头部导航栏和导航栏背景图片 navigationStyle问题
2019/07/26 Javascript
微信自定义分享链接信息(标题,图片和内容)实现过程详解
2019/09/04 Javascript
基于JS实现简单滑块拼图游戏
2019/10/12 Javascript
Python中不同进制互相转换(二进制、八进制、十进制和十六进制)
2015/04/05 Python
python实现的简单文本类游戏实例
2015/04/28 Python
python检查序列seq是否含有aset中项的方法
2015/06/30 Python
pandas.loc 选取指定列进行操作的实例
2018/05/18 Python
Django中使用Celery的教程详解
2018/08/24 Python
python3使用QQ邮箱发送邮件
2020/05/20 Python
python3.6编写的单元测试示例
2019/08/17 Python
python 使用建议与技巧分享(四)
2020/08/18 Python
TripAdvisor西班牙官方网站:全球领先的旅游网站
2018/01/10 全球购物
美国知名的旅游网站:OneTravel
2018/10/09 全球购物
印尼第一大家居、生活和家具电子商务:Ruparupa
2019/11/25 全球购物
十八大闭幕感言
2014/01/22 职场文书
联谊活动策划书
2014/01/26 职场文书
法律六进活动方案
2014/03/13 职场文书
省文明单位申报材料
2014/05/08 职场文书
2015欢度元旦标语口号
2014/12/09 职场文书
开会迟到检讨书范文
2015/05/06 职场文书
机械原理课程设计心得体会
2016/01/15 职场文书