java常用类(下)

1. String常见算法题目

  • 模拟一个 trim方法,去除字符串两端的空格

  • 将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转成为“abfedcg”

  • 获取一个字符串在另一个字符串中出现的次数。 比如:获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数

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

  • 对字符串中字符进行自然顺序排序。提示: 1)字符串变成字符数组。 2)对数组排序,选择,冒泡,Arrays.sort(); 3)将排序后的数组变成字符串

2. IDEA中Debug调试

  1. /*
  2. 面试题:程序输出
  3. */
  4. String str = null;
  5. StringBuffer sb = new StringBuffer();
  6. sb.append(str);
  7. System.out.println(sb.length());//4
  8. System.out.println(sb);//"null"
  9. StringBuffer sb1 = new StringBuffer(str);//抛空指针异常
  10. System.out.println(sb1);//

3. JDK8中新日期时间API

3.1. 新日期时间API出现的背景

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

可变性:像日期和时间这样的类应该是不可变的。 偏移性:Date中的年份是从1900开始的,而月份都从0开始。 格式化:格式化只对Date有用,Calendar则不行。 此外,它们也不是线程安全的;不能处理闰秒等。 总结:对日期和时间的操作一直是Java程序员最痛苦的地方之一

3.2. 新时间日期API

第三次引入的API是成功的,并且Java 8中引入的java.time API 已经纠正了 过去的缺陷,将来很长一段时间内它都会为我们服务。

Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。 新的 java.time 中包含了所有关于本地日期(LocalDate)、本地时间 (LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime) 和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 方法, 用于把 Date 转换成新的表示形式。这些新增的本地化时间日期 API 大大简 化了日期时间和本地化的管理。

3.2.1. LocalDate、LocalTime、LocalDateTime的使用

day21_java常用类(下)学习笔记 - 图1

  1. /*
  2. LocalDate、LocalTime、LocalDateTime 的使用
  3. 说明:
  4. 1.LocalDateTime相较于LocalDate、LocalTime,使用频率要高
  5. 2.类似于Calendar
  6. */
  7. @Test
  8. public void test1(){
  9. //now():获取当前的日期、时间、日期+时间
  10. LocalDate localDate = LocalDate.now();
  11. LocalTime localTime = LocalTime.now();
  12. LocalDateTime localDateTime = LocalDateTime.now();
  13. System.out.println(localDate);
  14. System.out.println(localTime);
  15. System.out.println(localDateTime);
  16. //of():设置指定的年、月、日、时、分、秒。没有偏移量
  17. LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23, 43);
  18. System.out.println(localDateTime1);
  19. //getXxx():获取相关的属性
  20. System.out.println(localDateTime.getDayOfMonth());
  21. System.out.println(localDateTime.getDayOfWeek());
  22. System.out.println(localDateTime.getMonth());
  23. System.out.println(localDateTime.getMonthValue());
  24. System.out.println(localDateTime.getMinute());
  25. //体现不可变性
  26. //withXxx():设置相关的属性
  27. LocalDate localDate1 = localDate.withDayOfMonth(22);
  28. System.out.println(localDate);
  29. System.out.println(localDate1);
  30. LocalDateTime localDateTime2 = localDateTime.withHour(4);
  31. System.out.println(localDateTime);
  32. System.out.println(localDateTime2);
  33. //不可变性
  34. LocalDateTime localDateTime3 = localDateTime.plusMonths(3);
  35. System.out.println(localDateTime);
  36. System.out.println(localDateTime3);
  37. LocalDateTime localDateTime4 = localDateTime.minusDays(6);
  38. System.out.println(localDateTime);
  39. System.out.println(localDateTime4);
  40. }

3.2.2. Instant类的使用

Instant:时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间 戳。

在处理时间和日期的时候,我们通常会想到年,月,日,时,分,秒。然而,这只是 时间的一个模型,是面向人类的。第二种通用模型是面向机器的,或者说是连续的。在此模型中,时间线中的一个点表示为一个很大的数,这有利于计算机 处理。在UNIX中,这个数从1970年开始,以秒为的单位;同样的,在Java中, 也是从1970年开始,但以毫秒为单位。

day21_java常用类(下)学习笔记 - 图2

  1. /*
  2. Instant的使用
  3. 类似于 java.util.Date类
  4. */
  5. @Test
  6. public void test2(){
  7. //now():获取本初子午线对应的标准时间
  8. Instant instant = Instant.now();
  9. System.out.println(instant);//2019-02-18T07:29:41.719Z
  10. //添加时间的偏移量
  11. OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
  12. System.out.println(offsetDateTime);//2019-02-18T15:32:50.611+08:00
  13. //toEpochMilli():获取自1970年1月1日0时0分0秒(UTC)开始的毫秒数 ---> Date类的getTime()
  14. long milli = instant.toEpochMilli();
  15. System.out.println(milli);
  16. //ofEpochMilli():通过给定的毫秒数,获取Instant实例 -->Date(long millis)
  17. Instant instant1 = Instant.ofEpochMilli(1550475314878L);
  18. System.out.println(instant1);
  19. }

3.2.3. java.time.format.DateTimeFormatter类的使用

DateTimeFormatter:格式化或解析日期、时间。类似于SimpleDateFormat

day21_java常用类(下)学习笔记 - 图3

方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME

方式二:本地化相关的格式。如:ofLocalizedDateTime()

方式三:自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)

  1. /*
  2. DateTimeFormatter:格式化或解析日期、时间
  3. 类似于SimpleDateFormat
  4. */
  5. @Test
  6. public void test3(){
  7. // 方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
  8. DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
  9. //格式化:日期-->字符串
  10. LocalDateTime localDateTime = LocalDateTime.now();
  11. String str1 = formatter.format(localDateTime);
  12. System.out.println(localDateTime);
  13. System.out.println(str1);//2019-02-18T15:42:18.797
  14. //解析:字符串 -->日期
  15. TemporalAccessor parse = formatter.parse("2019-02-18T15:42:18.797");
  16. System.out.println(parse);
  17. // 方式二:
  18. // 本地化相关的格式。如:ofLocalizedDateTime()
  19. // FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT :适用于LocalDateTime
  20. DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
  21. //格式化
  22. String str2 = formatter1.format(localDateTime);
  23. System.out.println(str2);//2019年2月18日 下午03时47分16秒
  24. // 本地化相关的格式。如:ofLocalizedDate()
  25. // FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT : 适用于LocalDate
  26. DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
  27. //格式化
  28. String str3 = formatter2.format(LocalDate.now());
  29. System.out.println(str3);//2019-2-18
  30. // 重点: 方式三:自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
  31. DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
  32. //格式化
  33. String str4 = formatter3.format(LocalDateTime.now());
  34. System.out.println(str4);//2019-02-18 03:52:09
  35. //解析
  36. TemporalAccessor accessor = formatter3.parse("2019-02-18 03:52:09");
  37. System.out.println(accessor);
  38. }

3.2.4. 其它API

ZoneId:该类中包含了所有的时区信息,一个时区的ID,如 Europe/Paris

ZonedDateTime:一个在ISO-8601日历系统时区的日期时间,如 2007-12- 03T10:15:30+01:00 Europe/Paris。

Clock:使用时区提供对当前即时、日期和时间的访问的时钟。

持续时间:Duration,用于计算两个“时间”间隔

日期间隔:Period,用于计算两个“日期”间隔

TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整 到“下一个工作日”等操作。

TemporalAdjusters : 该类通过静态方法 (firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用 TemporalAdjuster 的实现。

day21_java常用类(下)学习笔记 - 图4

4. Java比较器

java实现对象排序的方式有两种:

  • 自然排序:java.lang.Comparable
  • 定制排序:java.util.Comparator

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

4.1. 方式一:自然排序:java.lang.Comparable

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

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

  1. public class CompareTest {
  2. /*
  3. Comparable接口的使用举例: 自然排序
  4. 1.像String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式。
  5. 2.像String、包装类重写compareTo()方法以后,进行了从小到大的排列
  6. 3. 重写compareTo(obj)的规则:
  7. 如果当前对象this大于形参对象obj,则返回正整数,
  8. 如果当前对象this小于形参对象obj,则返回负整数,
  9. 如果当前对象this等于形参对象obj,则返回零。
  10. 4. 对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。
  11. 在compareTo(obj)方法中指明如何排序
  12. */
  13. @Test
  14. public void test1(){
  15. String[] arr = new String[]{"AA","CC","KK","MM","GG","JJ","DD"};
  16. //
  17. Arrays.sort(arr);
  18. System.out.println(Arrays.toString(arr));
  19. }
  20. @Test
  21. public void test2(){
  22. Goods[] arr = new Goods[5];
  23. arr[0] = new Goods("lenovoMouse",34);
  24. arr[1] = new Goods("dellMouse",43);
  25. arr[2] = new Goods("xiaomiMouse",12);
  26. arr[3] = new Goods("huaweiMouse",65);
  27. arr[4] = new Goods("microsoftMouse",43);
  28. Arrays.sort(arr);
  29. System.out.println(Arrays.toString(arr));
  30. }
  31. }
  1. package com.atguigu.java;
  2. /**
  3. * 商品类
  4. * @author shkstart
  5. * @create 2019 下午 4:52
  6. */
  7. public class Goods implements Comparable{
  8. private String name;
  9. private double price;
  10. public Goods() {
  11. }
  12. public Goods(String name, double price) {
  13. this.name = name;
  14. this.price = price;
  15. }
  16. public String getName() {
  17. return name;
  18. }
  19. public void setName(String name) {
  20. this.name = name;
  21. }
  22. public double getPrice() {
  23. return price;
  24. }
  25. public void setPrice(double price) {
  26. this.price = price;
  27. }
  28. @Override
  29. public String toString() {
  30. return "Goods{" +
  31. "name='" + name + '\'' +
  32. ", price=" + price +
  33. '}';
  34. }
  35. //指明商品比较大小的方式:按照价格从低到高排序,再按照产品名称从高到低排序
  36. @Override
  37. public int compareTo(Object o) {
  38. // System.out.println("**************");
  39. if(o instanceof Goods){
  40. Goods goods = (Goods)o;
  41. //方式一:
  42. if(this.price > goods.price){
  43. return 1;
  44. }else if(this.price < goods.price){
  45. return -1;
  46. }else{
  47. // return 0;
  48. return -this.name.compareTo(goods.name);
  49. }
  50. //方式二:
  51. // return Double.compare(this.price,goods.price);
  52. }
  53. // return 0;
  54. throw new RuntimeException("传入的数据类型不一致!");
  55. }
  56. }

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

背景:当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码, 或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那 么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排 序的比较。

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

  1. /*
  2. Comparator接口的使用:定制排序
  3. 1.背景:
  4. 当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,
  5. 或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,
  6. 那么可以考虑使用 Comparator 的对象来排序
  7. 2.重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
  8. 如果方法返回正整数,则表示o1大于o2;
  9. 如果返回0,表示相等;
  10. 返回负整数,表示o1小于o2。
  11. */
  12. @Test
  13. public void test3(){
  14. String[] arr = new String[]{"AA","CC","KK","MM","GG","JJ","DD"};
  15. Arrays.sort(arr,new Comparator(){
  16. //按照字符串从大到小的顺序排列
  17. @Override
  18. public int compare(Object o1, Object o2) {
  19. if(o1 instanceof String && o2 instanceof String){
  20. String s1 = (String) o1;
  21. String s2 = (String) o2;
  22. return -s1.compareTo(s2);
  23. }
  24. // return 0;
  25. throw new RuntimeException("输入的数据类型不一致");
  26. }
  27. });
  28. System.out.println(Arrays.toString(arr));
  29. }
  30. @Test
  31. public void test4(){
  32. Goods[] arr = new Goods[6];
  33. arr[0] = new Goods("lenovoMouse",34);
  34. arr[1] = new Goods("dellMouse",43);
  35. arr[2] = new Goods("xiaomiMouse",12);
  36. arr[3] = new Goods("huaweiMouse",65);
  37. arr[4] = new Goods("huaweiMouse",224);
  38. arr[5] = new Goods("microsoftMouse",43);
  39. Arrays.sort(arr, new Comparator() {
  40. //指明商品比较大小的方式:按照产品名称从低到高排序,再按照价格从高到低排序
  41. @Override
  42. public int compare(Object o1, Object o2) {
  43. if(o1 instanceof Goods && o2 instanceof Goods){
  44. Goods g1 = (Goods)o1;
  45. Goods g2 = (Goods)o2;
  46. if(g1.getName().equals(g2.getName())){
  47. return -Double.compare(g1.getPrice(),g2.getPrice());
  48. }else{
  49. return g1.getName().compareTo(g2.getName());
  50. }
  51. }
  52. throw new RuntimeException("输入的数据类型不一致");
  53. }
  54. });
  55. System.out.println(Arrays.toString(arr));
  56. }

4.4. Comparable接口与Comparator接口使用的对比

Comparable接口的方式一旦一定,保证Comparable接口实现类的对象在任何位置都可以比较大小。

Comparator接口属于临时性的比较。

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的属性对应的值。系统中常见 的属性名以及属性的作用如下表所示:
    day21_java常用类(下)学习笔记 - 图5

    1. @Test
    2. public void test1() {
    3. String javaVersion = System.getProperty("java.version");
    4. System.out.println("java的version:" + javaVersion);
    5. String javaHome = System.getProperty("java.home");
    6. System.out.println("java的home:" + javaHome);
    7. String osName = System.getProperty("os.name");
    8. System.out.println("os的name:" + osName);
    9. String osVersion = System.getProperty("os.version");
    10. System.out.println("os的version:" + osVersion);
    11. String userName = System.getProperty("user.name");
    12. System.out.println("user的name:" + userName);
    13. String userHome = System.getProperty("user.home");
    14. System.out.println("user的home:" + userHome);
    15. String userDir = System.getProperty("user.dir");
    16. System.out.println("user的dir:" + userDir);
    17. }

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) 角度—>弧度

7. BigInteger与BigDecimal

7.1. BigInteger类

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

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

  • 构造器
    BigInteger(String val):根据字符串构建BigInteger对象

  • 常用方法

7.2. BigDecimal类

背景:一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中, 要求数字精度比较高,故用到java.math.BigDecimal类。

BigDecimal类支持不可变的、任意精度的有符号十进制定点数。

  • 构造器

    • public BigDecimal(double val)
    • public BigDecimal(String val)
  • 常用方法

    • public BigDecimal add(BigDecimal augend)
    • public BigDecimal subtract(BigDecimal subtrahend)
    • public BigDecimal multiply(BigDecimal multiplicand)
    • public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
  1. @Test
  2. public void test2() {
  3. BigInteger bi = new BigInteger("1243324112234324324325235245346567657653");
  4. BigDecimal bd = new BigDecimal("12435.351");
  5. BigDecimal bd2 = new BigDecimal("11");
  6. System.out.println(bi);
  7. // System.out.println(bd.divide(bd2));//会报异常
  8. System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
  9. System.out.println(bd.divide(bd2, 25, BigDecimal.ROUND_HALF_UP));
  10. }