Java常用类(基础)

今天的努力只为更好的明天。

String类

一、概述

String:

  1. String 声明为 fianl的,不可被继承。
  2. String实现了Serializable接口,表示字符串是支持序列化的。实现了Comparable接口,表示String可以进行比较大小。
  3. String 内部定义的fianl char[ ] value 用于储存字符串数据。
  4. 通过字面量的方式(区别new给一个字符串赋值,此时得到字符串声明在字符串常量池中)。
  5. 字符串常量池是不会存储相同的内容(使用String类的equals()比较,返回true)的字符串的。

二、String的不可变性

说明:
① 当对字符串重新赋值,需要重写指定内存中区域赋值,不能使用原有的value进行赋值
② 当对现有的字符串进行操作时,也需要重新指定内存区域的赋值,不能使用原有的value进行赋值。
③ 当调用String的replace()方式修改指定字符串时,也需要重新指定区域赋值,不能使用原有的value进行赋值。

 @Test
    public void test(){
        // 字面量的定义
        String s1 = "abc";
        String s2 = "abc";
        //比较s1和s2的地址值
        System.out.println(s1 == s2); // true

		System.out.println("*****************");
	
		String s4 = "abc";
		String s5 = s4.replace('a', 'm');
		System.out.println(s4);//abc
		System.out.println(s5);//mbc
    }
    

三、String实例化的不同方式

方式说明:
方式一:通过字面量定义的方式
方式二:通过new+构造器的方式

 @Test
    public void test1(){
        // 通过字面定义的方式:此时的s1和s2的数据javaEE声明在方法区中字符串常量池
        String  s1 = "JavaEE";
        String  s2 = "JavaEE";
        // 通过new + 构造器的方式:此时的s3和s4保存地址,是数据在堆空间以后对应的地址值。
        String s3 = new String("javaEE");
        String s4 = new String("javaEE");

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

图示:
String实例化
问题:

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

四、字符串拼接方式赋值的对比

说明:
1.常量与常量的拼接结果在常量池,且常量池中不会存在相同的常量
2.只要其中一个是变量,结果就在堆中。
3.如果拼接的结果调用 **intern()**方法,返回值就是在常量池中。

代码示例:

  @Test
    public void test2(){
        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;

        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

        System.out.println("**********************************");
        String s8 = s6.intern(); // 返回值得到的s8使用的常量值中已经存在的"javaEEhadoop";
        System.out.println(s3 == s8); // true

    }
 @Test
    public void test3(){
        String s1 = "javaEEhadoop";
        String s2 = "javaEE";
        String s3 = s2 + "hadoop";
        System.out.println(s1 == s3);// false

        final String s4 = "javaEE"; // s4:常量
        String s5 = s4 + "hadoop";
        System.out.println(s1 == s5); // true
    }

五、常用方法

  • int length():返回字符串的长度: return value.length
  • char charAt(int index): 返回某索引处的字符return value[index]
  • boolean isEmpty():判断是否是空字符串:return value.length == 0
 String str = "abc";
 System.out.println(str.length());// 3
 System.out.println(str.charAt(2));// c
 System.out.println(str.isEmpty());// false
  • String toLowerCase():使用默认语言环境,将 String 中的所字符转换为小写
  • String toUpperCase():使用默认语言环境,将 String 中的所字符转换为大写
  • String trim():返回字符串的副本,忽略前导空白和尾部空白
 String str1 = "abcdefg";
 String str2 = "   abcdefg   ";
 System.out.println(str1.toLowerCase());// abcdefg
 System.out.println(str1.toUpperCase());// ABCDEFG
 System.out.println(str2.trim());// abcdefg
  • boolean equals(Object obj):比较字符串的内容是否相同
  • boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
  • String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
 String str3 = "abcdefg"; 
 String str4 = "ABCDEFG"; 
 String str5 = "abcd";
 String str6 = "efg";
 System.out.println(str3.equals(str4)); // false
 System.out.println(str3.equalsIgnoreCase(str4)); // true
 System.out.println(str5.concat(str6));// abcdefg
  • int compareTo(String anotherString):比较两个字符串的大小
  • String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
  • String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
  • int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
        String str7 = "abcdefg";
        String str8 = "abcdefg";
        String str9 = "abcd";
        System.out.println(str7.compareTo(str8)); // 0 表示相等
        System.out.println(str7.substring(2));// cdefg
        System.out.println(str7.substring(0,5)); // abcde
        System.out.println(str7.indexOf("d",0)); // 3
  • boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
  • boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
  • boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
 String str1 = "helloworld";
 boolean b1 = str1.endsWith("rld");
 boolean b2 = str1.startsWith("hel");
 boolean b3 = str1.startsWith("ll",2);
 System.out.println(b1); //ture
 System.out.println(b2); //ture
 System.out.println(b3); //ture
  • boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
        String str1 = "helloworld";
        String str2 = "wor";
        System.out.println(str1.contains(str2)); // true
  • int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
System.out.println(str1.indexOf("ll")); // 2
System.out.println(str1.indexOf("lo",5));// -1
  • int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
  • int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
        String str3 = "hellorworld";
        System.out.println(str3.lastIndexOf("or")); // 7
        System.out.println(str3.lastIndexOf("or",2)); // -1

注: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 替换此字符串匹配给定的正则表达式的第一个子字符串。
String str1 = "中国湖南";
        //   String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
        String str2 = str1.replace("湖南","湖北");
        System.out.println(str2); // 中国湖北
        System.out.println("*********************************************");
        //   String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
        String str3 = "12hello34world5java7891mysql456";
        String str4 = str3.replaceAll("\\d+", ",").replaceAll("^,|,$", "");
        System.out.println(str4); // hello,world,java,mysql

匹配:

  • boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
		String str5 = "12345";
        //判断str字符串中是否全部有数字组成,即有1-n个数字组成
        boolean matches = str5.matches("\\d+");
        System.out.println(matches); // true

切片:

  • String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
  • String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
		String str6 = "hello|world|java";
        String[] strs = str6.split("\\|");
        for (int i = 0; i < strs.length; i++) {
            System.out.println(strs[i]); // hello world java
        }
        System.out.println();
        String str7 = "hello.world.java";
        String[] strs2 = str7.split("\\.");
        for (int i = 0; i < strs.length; i++) {
            System.out.println(strs2[i]); // hello  world java
        }

String与其他结构的替换

  • ① 与基本的数据类型、包装类之间的装换

String ---- 基本数据类型、包装类:调用包装类的静态方法:parseXXX(str)
基本数据类型、包装类 — String:调用String重载的valueof(XXX)

代码示例

public void test1(){
        String str = "123";
        int num = Integer.parseInt(str);
        System.out.println(num);
        String str1 = String.valueOf(num);
        System.out.println(str1);
    }

String ====》char[ ]: 调用String的toCharArray();
char[ ] ===》 String :调用String的构造器

代码示例

 public void test2(){
//        String --> char[] :调用String的toCharArray();
        String str = "abc123";
        char[] ch = str.toCharArray();
       for(int i = 0; i < ch.length; i++){
           System.out.println(ch[i]);
       }
        System.out.println("***************************");
//        char[] --> String:调用String的构造器
       char[] arr = new char[]{'h','l','l'};
       String str2 = new String(arr);
        System.out.println(str2);
    }
  • ② 与字数组之间的转换

编码:String ===》 byte[ ]:调用String的getBytes();
解码:byte[ ] ===》 String :调用String的构造器
编码:字符串 ===》 字节(二进制)
解码:编码的逆过程,字节 ===》 字符串
说明:解码时,要求解码的使用的字符集必须与编码的字符集一致,否则会出现乱码。

代码示例:

 public void test3() throws UnsupportedEncodingException {
        String str = "abc";
        byte[] bytes = str.getBytes(); // 使用默认字符集,进行编码
        System.out.println(bytes);
        byte[] gbks = str.getBytes("gbk");
        System.out.println(Arrays.toString(gbks));
    }

运行结果:

补充:
与 StringBuffer、StringBuilder之间的转换
String === 》 StringBuffer、StringBuilder:调用StringBuffer、StringBuilder构造器;
StringBuffer、StringBuilder ===》 String: ① 调用String 构造器 ② StringBuffer、StringBuilder的toString();

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

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

StringBuffer、StringBuilder

一、String、String、StringBuilder三者的对比

String:不可变的字符序列:底层使用char[] 储存
StringBuffer: 可变的字符序列:线程安全的,效率低:底层使用char[]存储
StringBuilder: 可变的字符序列:jdk5.0:新增的,线程不安全,效率高;底层使用char[] 存储

可变类型:

 比如列表:列表名(或称为列表引用)指向堆空间中的一个列表。列表引用当中存储的内容为地址,可以指向堆内存中的具体对象.

一方面,该列表可以保证在地址不变的前提下,改变列表内容;另一方面,该引用也可以直接指向堆空间中的另外一个列表..

不可变序列:

比如数字、字符、(元祖):对于基础数据类型,变量地址即变量本身,所以值发生变化了,内存地址就一定也变了。

比如字符串:被称为不可变的字符序列,每个字符底层均有规范的Unicode码对应,内存规定无法对单一的一个字符进行修改,要修改字符串必须重新指向一个全新的字符串

二、StringBuffer 与 StringBuilder的内存解析

以Stringuffer为例:
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的数组。
System.out.println(sb1.length());//
sb1.append('a');//value[0] = 'a';
sb1.append('b');//value[1] = 'b';

StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length() + 16];

扩容问题:如果添加的数组底层数组盛不下,那就需要扩容底层的数组
默认的情况,扩容为原来的2倍+2;同时将原来的数组复制到新数组中。
在开发中优先使用:StringBuffer、StringBuilder

三、对比String、StringBuffer 、StringBuilder 三者的执行效率

从高到低排序:StringBuiler > StringBuffer > String

四、StringBuffer、StringBuilder中常用的方法

增:oppend(XXX)
删:delete(int start, int end)
改:setCharAt(int n , char ch) / replance(int start, int end , Sting str)
查:charAt(int n)
插: insert(int offset , XXX);
长度:Lenght();
*遍历:for() + charAt() / toString()

JDK 8之前日期时间API

一、获取系统之前当前时间

System类中的CurrentTimeMills()

long time = Sysem.cuurenTimeMillis()
//返回当前时间与1970年1月1日0时0分之间以毫秒为单位的时间差。
//称为时间戳
System.out.println(time);

二、java.util.Date类与java.sql.Date类

java.util.Date类
	|---java.sql.Date类
1.两个构造器的使用
	>构造器一:Date()创建一个对应当前时间的Date对象
	>构造器二:创建指定毫秒数的Date对象
2.两个方法的使用
	>toString() 显示当前的年、月、日、分、秒
	>getTime() 获取当前Date对象对应的毫秒数。(时间戳)
3.java.sql.Date对应着数据中日期类型的变量
	> 实例化
	> 将java.util.Date 转为 java.sql.Date			

代码示例:

	@Test
    public void test1(){
        long time = System.currentTimeMillis();
        System.out.println(time);
    }
    @Test
    public void test2(){
        // 构造器一:Date():创建一个对应当前时间的Date对象
        Date date = new Date();
        System.out.println(date.toString()); // Sat Jun 13 17:07:02 CST 2020

        System.out.println(date.getTime()); // 1592039273009
    }
    @Test
    public void test3(){
        // 构造器二:创建指定毫秒数的Date对象
        Date date = new Date(1592039273009L);
        System.out.println(date.toString()); // Sat Jun 13 17:07:53 CST 2020
        System.out.println("***********************");
        // 创建java.sql.Date对象
        java.sql.Date date1 = new java.sql.Date(1592039273009L);
        System.out.println(date1); // 2020-06-13
    }
    
    @Test
    /**
     * 将java.util.Date对象转换为java.sql.Date对象
     */
    public void test4(){
        // 情况一:
        Date date = new java.sql.Date(1592039273009L);
        java.sql.Date date1 = (java.sql.Date) date;
        
        // 情况二:
        Date date2 = new Date();
        java.sql.Date date3 = new java.sql.Date(date2.getTime());
    }

三、java.text.SimpleDateFormat类

simpleDateFormat 对日期Date类的格式化和解析
1.两个操作
	1.1 格式化:日期 --> 字符串
	1.2 解析: 格式化的逆过程,字符串 --> 日期
2.SimpleDateFormat	
 @Test
    public void test5() throws ParseException {
//        照指定的方式格式化和解析:调用带参的构造器
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd  hh:mm aaa");
        // 格式化
        Date date = new Date();
        String format = sdf.format(date);
        System.out.println(format); // 2020-06-13  05:23 下午

        //解析:要求字符串必须是符合SimpleDateFormat识别的格式(通过构造器参数体现),
        //否则,抛异常
        Date parse = sdf.parse("2020-06-13  05:23 下午");
        System.out.println(parse); // Sat Jun 13 17:23:00 CST 2020
    }

四、Calendar类:日历类、抽象类

@Test
    public void test6(){
        //1.实例化
        //方式一:创建其子类(GregorianCalendar的对象
        //方式二:调用其静态方法getInstance()
        Calendar calendar = Calendar.getInstance();
//        System.out.println(calendar);

        //2 常用方法
        // get
        int days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days);// 13
        System.out.println(calendar.get(Calendar.DAY_OF_YEAR)); // 165

        // set()
        calendar.set(Calendar.DAY_OF_MONTH,22);
        int days1 = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days1); // 22

        //add()
        calendar.add(Calendar.DAY_OF_MONTH,-3);
        days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days); // 19

        // getTime() 日历类 ---> Date
        Date time = calendar.getTime();
        System.out.println(time);// Fri Jun 19 17:41:29 CST 2020

        //setTime():Date ---> 日历类
        Date date = new Date();
        calendar.setTime(date);
        days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days); // 13
    }

JDK8中新日期时间API

一、日期时间的迭代

第一代:jdk 1.0 Date类
第二代:jdk 1.1 Calender类,一定的程度上替代了Date类
第三代:jdk 1.8 提出了新的一套API

二、前两代存在的问题举例:

可变性:像时间和日期这样的类应该是吧不可变的。
偏移性:Date中的年份是从1900年开始的,月份是从0开始的。
格式化:格式话只对Date有用,calender则不行。
此外,它们也不是线程安全的,不能处理闰秒等。

三、java 8 中新的日期时间API涉及到的包

新日期API包

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

  • 一、说明

① 分别表示使用ISO-8601日历系统的日期、时间、和时间。它们提供了简单的本地时间信息,也不包含当前的时间信息,也不包含与时区相关的信息。
② LocalDatetime相较于LocalDate、LocalTIme,使用频率高
③ 类似于Calender

  • 二、常用方法

五 时间点:Instant

  • 一、说明

① 时间线上的一个瞬时点,概念上讲。它只是简单的表示自1970年1月1日0时0秒(UTC开始的秒数)
② 类似于java.util.Date类

  • 二、常用方法

六、时间日期格式化类:DateTimeFormatter

  • 一、说明

① 格式化或解析日期、时间
② 类似于SimpleDateFormat

  • 二、常用方法
    ① 实例化方式:

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

② 常用方法
在这里插入图片描述

 public void test1(){

      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
      // 格式化
      String str = formatter.format(LocalDateTime.now());
      System.out.println(str); // 2020-06-20 03:38:37

      // 解析
      TemporalAccessor accessor = formatter.parse("2020-06-20 03:38:37");
      System.out.println(accessor); // {MinuteOfHour=38, HourOfAmPm=3, MilliOfSecond=0, MicroOfSecond=0, NanoOfSecond=0, SecondOfMinute=37},ISO resolved to 2020-06-20
   }

七、其他

  • 带时区的日期时间:ZonedDateTime / ZoneId
 /**
    * ZoneId:类中包含的失去信息
    */
   @Test
   public void test3(){
      // getAvailableZoneIds():获取所有的ZoneId
      Set<String> zoneIds = ZoneId.getAvailableZoneIds();
      for (String s : zoneIds) {
         System.out.println(s);
      }
      System.out.println("***********************");
      LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
      System.out.println(localDateTime); // 2020-06-20T16:53:34.885
   }

   /**
    * ZonedDateTime: 带时区的时间
    */
   @Test
   public void test4(){
      // now() 获取本时区的ZoneDateTime对象
      ZonedDateTime now = ZonedDateTime.now();
      System.out.println(now); // 2020-06-20T15:57:00.163+08:00[Asia/Shanghai]

      // now(ZoneId id) 获取指定时区的ZonedTime对象
      ZonedDateTime zonedDateTiem = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
      System.out.println(zonedDateTiem);
   }
  • 时间间隔:Duration–用于计算两个“时间”间隔,以秒和纳秒为基准
 public void test5(){
      LocalTime localTime = LocalTime.now();
      LocalTime localTime2 = LocalTime.of(15, 23, 32);
      // between() 静态方法,返回Duration对象,表示两个时间间隔
      Duration between = Duration.between(localTime, localTime2);
      System.out.println(between);

      System.out.println(between.getSeconds());
      System.out.println(between.getNano());

      LocalDateTime localdatetime = LocalDateTime.of(2016, 6, 12, 15, 23, 32);
      LocalDateTime localdatetime1 = LocalDateTime.of(2017, 6, 12, 15, 23, 32);
      Duration between1 = Duration.between(localdatetime, localdatetime1);
      System.out.println(between1.toDays()); // 365
   }
  • 日期间隔:Period --用于计算两个“日期”间隔,以年、月、日衡量

在这里插入图片描述

public void test6(){
      LocalDate localdate = LocalDate.now();
      LocalDate localdate1 = LocalDate.of(2028, 3, 18);

      Period period = Period.between(localdate, localdate1);
      System.out.println(period); // P7Y8M27D

      System.out.println(period.getYears()); // 7
      System.out.println(period.getMonths()); // 8
      System.out.println(period.getDays()); // 27

      Period period1 = period.withYears(2);
      System.out.println(period1); // P2Y8M27D
   }
  • 日期时间校正器:TemporalAdjuster
 public void test7(){
      // 获取当前日期的下一个周日是哪天?
      TemporalAdjuster temporalAdjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);
      LocalDateTime localDateTime = LocalDateTime.now().with(temporalAdjuster);
      System.out.println(localDateTime); // 2020-06-21T16:42:13.229

      // 获取下一个工作日食哪天
      LocalDate localDate = LocalDate.now().with(new TemporalAdjuster() {
         @Override
         public Temporal adjustInto(Temporal temporal) {
            LocalDate date = (LocalDate) temporal;
            if (date.getDayOfWeek().equals(DayOfWeek.FRIDAY)) {
               return date.plusDays(3);
            } else if (date.getDayOfWeek().equals(DayOfWeek.SATURDAY)) {
               return date.plusDays(2);
            } else {
               return date.plusDays(1);
            }
         }
      });
      System.out.println("下一个工作日是:"+localDate);
   }

Java比较器

一、java比较器的使用背景

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

二、自然排序:使用comparable接口

  • 说明

① 像 String、包装类等实现了Comparable接口,重写了comparaTo(obj)方法,给出了比较两个对象大小的方式。
② String、包装类重写了comparaTo()的规则:
如果当前的对象this大于形参对象obj,则返回正整数.
如果当前对象this小于形参obj,则返回负整数
如果当前对象this等于形对象obj,则返回零。
③ 对于自定义类来说,如果需要排序,我们可以自定义类实现Comparablej接口,重写comparaTo(obj)方法。在comparaTo()方法中指明如何排序

public class Goods implements Comparable{
    private Sting name;
    private double price;
    //指明商品比较大小的方式:照价格从低到高排序,在照产品名称从高到低排序
      @Override
    public int compareTo(Object o) {
//        System.out.println("**************");
        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);
        }
//        return 0;
        throw new RuntimeException("传入的数据类型不一致!");
    }
// getter、setter、toString()、构造器:省略
}

        
    }
}

三、定制排序:使用Comparator接口

说明:

① 背景:

当元素的类型没实现java.lang.comparable接口而又不方便修改代码,或实现了java.lang.Comparable
接口的排序规则不适合当前的操作,那么可以考虑使用Comparator的对象类排序

② 重写comparator(Object o1, Object o2)方法,比较o1和o2的大小:

重写方法返回正整数,则表示o1大于o2
如果返回0,表示相等
返回负整数,表示o1小于o2

代码示例:

Comparator com = 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());
            }
        }
        throw new RuntimeException("输入的数据类型不一致");
    }
}
  • 使用:
Arrays.sort(goods,com);
Collections.sort(coll,com);
new TreeSet(com);
 public void test3(){
        Goods[] arr = new Goods[6];
        arr[0] = new Goods("lenovoMouse",34.0);
        arr[1] = new Goods("dellMouse",43.0);
        arr[2] = new Goods("xiaomiMouse",12.0);
        arr[3] = new Goods("huaweiMouse",65.0);
        arr[4] = new Goods("huaweiMouse",224.0);
        arr[5] = new Goods("microsoftMouse",43.0);

        Arrays.sort(arr);
        System.out.println("Comparable排序"+Arrays.toString(arr));
        
       // 使用匿名内部类,可以在一定的程度上优化代码 new Comparator<T>(){}
        Arrays.sort(arr, new Comparator<Goods>() {
            @Override
            public int compare(Goods o1, Goods o2) {
            // name 相同 就比较 价格(降序)
               if(o1.getName().equals(o2.getName())){
                   return -Double.compare(o1.getPrice(),o2.getPrice());
               }else{
                   return o1.getName().compareTo(o2.getName());
               }
            }
        });
        System.out.println("Comparator:"+Arrays.toString(arr));
    }
}

其他类

一、System类

① System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
② 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,所以也可以很方便的进行调用。

  • 方法:
native long currentTimeMillis()
void exit(int status)
void gc() 
String getProperty(String key) 

二、Math 类

java.lang.Math提供了一系列静态方法用于科学计算。其方法的参数和返回值类型一般为double型。

三、BigInteger类、BigDecimal类

说明:

① java.math包的BigInteger可以表示不可变的任意精度的整数。
② 要求数字精度比较高,用到java.math.BigDecimal类

public class BigIntegerTest {
    @Test
    public void test1(){
        BigInteger bi = new BigInteger("12323443544535");
        BigDecimal bd = new BigDecimal("233434.35445");
        BigDecimal bd2 = new BigDecimal("2113");
        System.out.println(bi); // 12323443544535

        System.out.println(bd.divide(bd2,BigDecimal.ROUND_HALF_UP)); // 110.47532
        System.out.println(bd.divide(bd2,15,BigDecimal.ROUND_HALF_UP)); // 110.475321557027922
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值