常用类

常用类

  1. 字符串相关的类
    • String类及常用方法
    • StringBuffer
    • StringBuilder
  2. JDK8之前的日期时间API
    • System静态方法---------->currentTimeMillis()
    • Date类
    • Calendar类
    • SimpleDateFormat类
  3. JDK8中新日期时间API
    • LocalDate
    • LocalTime
    • LocalDateTime
    • Instant
    • DateTimeFormatter
  4. Java比较器
    • Compara接口
    • Comparator接口
  5. System类
  6. Math类
  7. BigInteger与BigDecimal

String

  • String类:代表字符串

  • String实现了Serializable接口:表示字符串是支持序列化的。
    实现了Comparable接口:表示String可以比较大小

  • String内部定义了final char[] value用于存储字符串数据。

  • String:代表不可变的字符序列。简称:不可变性。

    • 体现:

      1. 当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
      2. 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value赋值。
      3. 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值。
    • @Test
      public void test1(){
          String s1="abc";//字面量
          String s2="abc";
          s1="hello";
      
          System.out.println(s1);//hello
          System.out.println(s2);//abc
      
  • 字符串是常量,它们的值在创建之后不能更改。

  • String对象的字符内容是存储在一个字符数组value[]中的。

  • 通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。

  • 字符串常量池中是不会存储相同内容的字符串。

String对象的创建

String的实例化方式:

  • 通过字面量定义的方式

  • 通过new + 构造器的方式

String str = "hello";

//本质上this.value = new char[0];
String s1 = new String();

//this.value = original.value;
String s2 = new String(String original);

//this.value = Arrays.copyOf(value,value.length);
String s3 = new String(char[] a);

String s4 = new String(char[] a,int startIndex,int count);
@Test
    public void test2(){
        //通过字面量定义的方法:此时的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(s2==s3);//false
        System.out.println(s3==s4);//false
        System.out.println(s4==s1);//false

        System.out.println("=================");

        Person p1 = new Person("Tom",12);
        Person p2 = new Person("Tom",12);

        System.out.println(p1.name.equals(p2.name));//true
        System.out.println(p1.name==p2.name);//true

        p1.name = "Jerry";
        System.out.println(p2.name);//Tom

    }

图解:image-20201201232418035

面试题:

  • String s = new String("abc");方式创建对象,在内存中创建了几个对象?
    • 两个:一个是在堆空间中new结构,另一个是char[]对应的常量池中的数据:"abc"。
@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 = s5.intern();//返回值得到的s8使用的常量值中已经存在的“javaEEhadoop”


    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(s3==s8);//true

}

结论:

  • 常量与常量的拼接结果在常量池,且常量池中不会存在相同内容的常量
  • 只要其中有一个变量,结果就在堆中
  • 如果拼接的结果调用intern()方法返回值就在常量池中

面试题:

public class StringTest {

   String str = new String("good");
   char[] ch ={'t','e','s','t'};

   public void change(String str,char ch[]){
       str = "test ok";
       ch[0] = 'b';
   }

    public static void main(String[] args) {
        StringTest ex = new StringTest();
        ex.change(ex.str, ex.ch);
        System.out.println(ex.str);//good
        System.out.println(ex.ch);//best
    }
}

String类常用方法

image-20201123172624397

image-20201123172658300

image-20201123172732411

package stringtest;

import org.junit.jupiter.api.Test;

public class StringMethodTest {

    @Test
    public void test(){
        String s1 = "Hello World";
        String s2 = new String("   boom shit  ");
        String s3 = "Hello World";
        String s4 = new String("Hello World");
        String s5 = new String("Hello Worlda");
        String s6 = "d";

        System.out.println(s1.length());//11
        System.out.println(s1.charAt(8));//r
        System.out.println(s1.isEmpty());//false

        System.out.println(s1.toLowerCase());//hello world
        System.out.println(s1.toUpperCase());//HELLO WORLD

        System.out.println(s2.trim());//boom shit

        System.out.println(s1.equals(s3));//true
        System.out.println(s1.equals(s4));//true
        System.out.println(s1.equalsIgnoreCase(s3.toUpperCase()));//true

        System.out.println(s1.concat(s3));//Hello WorldHello World

        System.out.println(s1.compareTo(s5));//-1

        System.out.println(s1.substring(3));//lo World
        System.out.println(s1.substring(3,7));//lo W

        System.out.println(s1.endsWith(s6));//true
        System.out.println(s1.endsWith(s3));//true

        System.out.println(s1.startsWith(s3));//true
        System.out.println(s1.startsWith("he",0));//false

        String s7 = "hello world";
        String s8 = new String("hello");

        System.out.println(s7.contains(s8));//true
        System.out.println(s7.indexOf("lo"));//3
        System.out.println(s7.indexOf("l",3));//3
        System.out.println(s7.indexOf("es"));//-1

        String s9 = new String("abbccddccbba");
        //索引从左边开始计数,而不是按搜索顺序计数
        System.out.println(s9.lastIndexOf("bb"));//9
        System.out.println(s9.lastIndexOf("bb",6));//1
        System.out.println(s9.lastIndexOf("ee"));//-1

        String t1 = "Hello World";
        String t2 = new String("boom shit");
        String t4 = "ff";

        String t3 = t1.replace("Hello", t2);
        String t5 = t1.replace(t1, t4);

        System.out.println(t3);//boom shit World
        System.out.println(t5);//ff

        String t6 = "大大得到的道德";
        String t7 = t6.replace('大', '小');
        String t8 = t6.replace("道德", "答复");
        System.out.println(t7);//小小得到的道德
        System.out.println(t8);//大大得到的答复

        String str1 = "12hello23world13java2322mysql2323";
        String str2 = str1.replaceAll("\\d+", ",");
        System.out.println(str2);//,hello,world,java,mysql,
        String str3 = str2.replaceAll("^,|,$", "");
        System.out.println(str3);//hello,world,java,mysql\

        String str5 = new String("12345");
        boolean matches = str5.matches("\\d+");
        System.out.println(matches);//true
    }
}

String与基本数据类型、包装类之间的转换

  • String-->基本数据类型、包装类:

  • 调用包装类的静态方法:parseXxx(str)

  • 基本数据类型、包装类-->String:

    • 调用String重载的valueOf(xxx)
@Test
    public void test1(){
        String str1 = "123";
//        int num = (int)str1;//错误
        int i = Integer.parseInt(str1);
        System.out.println(i);
        i++;

        String str2 = String.valueOf(i);
        String str3 = i +"";
        System.out.println(str1==str3);//false
    }

String与char[]之间的转换

  • String-->char[]:

    • 调用String的tocharArray();
  • char[] -->String :

    • 调用String的构造器
@Test
public void test2(){
    String str1 = "abc123";
    char[] charArray = str1.toCharArray();
    for (char i :charArray) {
        System.out.println(i);
    }

    char[] arr =new char[]{'h', 'e', 'l', 'l', 'o'};
    String str2 = new String(arr);
    System.out.println(str2);//hello

}

String与byte[]之间的转换

编码:String-->byte[]:调用String的getBytes()

解码:byte[]-->String:调用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字符集进行编码
//        for (byte i:gbks) {
//            System.out.print(i+" ");
//        }
        System.out.println(Arrays.toString(gbks));
        System.out.println();
        String str2 = new String(bytes);//使用默认字符集进行解码
        System.out.println(str2);//abc123中国

        String str3 = new String(gbks);
        System.out.println(str3);//出现乱码。原因;编码集和解码集不一致

        String gbk = new String(gbks, "gbk");
        System.out.println(gbk);//abc123中国


    }

String、StringBuffer和StringBuilder三者的异同

String不可变的字符序列:底层用final char[]存储

StringBuffer:可变的字符序列,线程安全的,效率低底层用char[]存储

StringBuilder可变的字符序列,线程不安全的效率高底层用char[]存储

String、StringBuffer和StringBuilder三者相互转换

调用转换类的构造器就行

源码分析:

@Test
    public void test1(){
        StringBuffer sb1 = new StringBuffer("abc");
        sb1.setCharAt(1,'k');
        System.out.println(sb1);//akc

        String str = new String();//final char[] value = new char[0];
        String str1 = new String("abc");//final char[] value = new char[]{'a','b','c'};

        StringBuffer sb2 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度为16的数组
        System.out.println(sb2.length());//0
        sb2.append('a');//value[0] = 'a';
        sb2.append('b');//value[1] = 'b';
        sb2.append('c');//value[2] = 'c';
        System.out.println(sb2);//abc
        System.out.println(sb2.length());//3

        StringBuffer sb3 = new StringBuffer("abcd");//char[] value = new char["abc".length()+16];
        /**
         * 扩容问题:
         * 默认情况下,扩容为原来容量的2倍+2,同时将原来数组中的元素复制到新的数组中去
         * 指导意义:建议使用:StringBuffer(int capacity)或StringBuilder(int capacity)
         */

StringBuffer类常用方法

image-20201203193155400

以上方法支持方法链原理,原理如下

@Override
public StringBuilder append(String str) {
    super.append(str);
    return this;
}

image-20201203193217567

遍历需要for循环

for (int i = 0;i<stringbuffer.length();i++) {
            System.out.println(stringbuffer.charAt(i));
        }
@Test
    public void test1(){
        StringBuffer sb1 = new StringBuffer("abc");
        char[] ch = {'a','c'};
        sb1.append(1).append(ch);
        System.out.println(sb1);//abc1ac
        sb1.delete(1,4);
        System.out.println(sb1);//aac
        String str1 = new String("lll");
        sb1.replace(1,2,str1);
        System.out.println(sb1);//alllc
        sb1.insert(0,123);
        System.out.println(sb1);//123alllc
        sb1.reverse();
        System.out.println(sb1);//cllla321
        sb1.setCharAt(3,'A');
        System.out.println(sb1);//cllAa321
        System.out.println(sb1.substring(1,3));//ll
    }

JDK8之前的日期时间API

java.lang.System类

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

@Test
public void test1(){

    System.out.println(currentTimeMillis());
}

可用于订单编号

java.util.Date类

Date类的两个构造器的使用:

  • Date():创建一个对应当前时间的Date对象
  • Date(long)创建指定毫秒数的Date对象

java.util.Date类常用方法

image-20201205014252063

@Test
    public void test1(){
        Date date1 = new Date();
        System.out.println(date1.toString());//Sat Dec 05 00:43:41 CST 2020
        System.out.println(date1.getTime());//1607100221127

        Date date2 = new Date(1606997024829L);
        System.out.println(date2.toString());//Thu Dec 03 20:03:44 CST 2020
        
    }

创建java.sql.Date对象

	java.sql.Date date3 = new java.sql.Date(1607100221127L);
    System.out.println(date3);//2020-12-05

如何将java.util.Date对象转换为java.sql.Date对象

//方法一:
        Date date4 = new java.sql.Date(1607100422833L);
        java.sql.Date date5 = (java.sql.Date) date4;
        System.out.println(date5);//2020-12-05    
//方法二:
    	Date date6 = new Date();
    	java.sql.Date date7 = new java.sql.Date(date6.getTime());
    	System.out.println(date7);//2020-12-05

SimpleDateFormat类

该类是一个不与语言环境有关的方式来格式化和解析日期的具体类

它允许进行格式化:日期-->文本

​ 解析:文本-->日期

image-20201205014748702

@Test
    public void test1() throws ParseException {
        //实例化SimpleDateFormat:使用默认的构造器
        SimpleDateFormat sdf = new SimpleDateFormat();


        Date date = new Date();
        System.out.println(date);//Sat Dec 05 01:52:35 CST 2020

        //格式化:日期-->字符串
        String format = sdf.format(date);
        System.out.println(format);//20-12-5 上午1:52

        //解析:字符串-->日期
        String str = "20-12-34 下午3:32";
        Date date1 = sdf.parse(str);
        System.out.println(date1);//Sun Jan 03 15:32:00 CST 2021

        //调用有参构造器
//        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//按照指定方式解析
        //格式化
        String format1 = sdf2.format(date);
        System.out.println(format1);//2020-12-05 02:06:37
        //解析    要求解析的字符串必须符合SimpleDateFormat格式(通过SimpleDateFormat构造器有参参数体现)
        Date date2 = sdf2.parse("2020-12-05 02:06:37");
        System.out.println(date2);//Sat Dec 05 02:06:37 CST 2020
    }

练习一:字符串"2020-09-08"转换为java.sql.Date

@Test
public void test1() throws ParseException {
    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
    Date date1 = sdf1.parse("2020-09-08");
    System.out.println(date1);

    java.sql.Date date2 = new java.sql.Date(date1.getTime());
    System.out.println(date2);
}

练习二:从1990-01-01开始“三天打渔两天晒网“,2020-09-08是打渔还是晒网?

@Test
public void test2() throws ParseException {
    //1990-01-01     2020-09-08
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
    Date date1 = simpleDateFormat.parse("1990-01-01");
    long time1 = date1.getTime();
    SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
    Date date2 = simpleDateFormat1.parse("2020-09-08");
    long time2 = date2.getTime();
    long timeSub = time2 - time1;
    
    long i = 86_400_000L;//一天的毫秒数
    long day = timeSub / i ;
    int j = (int)day%5;
    switch (j){
        case 0:
            System.out.println("晒网");
            break;
        case 1:
            System.out.println("打渔");
            break;
        case 2:
            System.out.println("打渔");
            break;
        case 3:
            System.out.println("打渔");
            break;
        case 4:
            System.out.println("晒网");
            break;

    }
}

Calendar类(抽象类)

实例化方法:

  • 创建其子类GregorianCalendar的对象
  • 调用其静态方法getInstance()
@Test
public void test1(){
    Calendar calendar = Calendar.getInstance();
    //get()
    int days = calendar.get(Calendar.DAY_OF_MONTH);
    System.out.println(days);
    System.out.println(calendar.get(Calendar.DAY_OF_YEAR));

    //set()
    calendar.set(Calendar.DAY_OF_YEAR,13);
    System.out.println(calendar.get(Calendar.DAY_OF_YEAR));

    //add()
    calendar.add(Calendar.DAY_OF_YEAR,33);
    System.out.println(calendar.get(Calendar.DAY_OF_YEAR));

    //getTime()  日历类-->Date
    Date date = calendar.getTime();
    System.out.println(date);

    //setTime()  Date-->日历类
    Date date1 = new Date();
    calendar.setTime(date1);
    System.out.println(calendar.get(Calendar.DAY_OF_YEAR));

}

Calendar的常用方法:

image-20201205131045560

LocalDate、LocalTime、LocalDateTime

常用方法:

image-20201205151856941

@Test
public void test(){
    //实例化方式:now(),of()
    //now()
    LocalDate localDate = LocalDate.now();
    LocalTime localTime = LocalTime.now();
    LocalDateTime localDateTime = LocalDateTime.now();
    /*
    2020-12-05

    14:53:33.926
    2020-12-05T14:53:33.926
     */
    System.out.println(localDate);
    System.out.println(localTime);
    System.out.println(localDateTime);

    //of()  设置指定的年,月,日,时,分,秒,没有偏移量
    LocalDateTime localDateTime1 = LocalDateTime.of(2020, 12, 22, 15, 22,33);
    System.out.println(localDateTime1);//2020-12-22T15:22:33
    System.out.println("==================================");
    //getXxx()
    System.out.println(localDateTime1.getDayOfMonth());//22
    System.out.println(localDateTime1.getDayOfYear());//357
    System.out.println(localDateTime1.getDayOfWeek());//TUESDAY
    System.out.println(localDateTime1.getMonth());//DECEMBER
    System.out.println(localDateTime1.getMonthValue());//12
    System.out.println(localDateTime1.getMinute());//22
    System.out.println(localDateTime1.getSecond());//33


    //体现不可变性
    //withXxx():设置相关属性
    LocalDateTime localDateTime2 = localDateTime1.withDayOfMonth(22);
    System.out.println(localDateTime1);//2020-12-30T15:22:33
    System.out.println(localDateTime2);//2020-12-22T15:22:33

    LocalDateTime time3 = localDateTime1.plusDays(2);
    System.out.println(time3);//2020-12-24T15:22:33

    LocalDateTime time4 = localDateTime1.minusHours(3);
    System.out.println(time4);//2020-12-22T12:22:33


}

Instant类

常用方法

image-20201205152111629

@Test
public void test1(){
    Instant now = Instant.now();
    System.out.println(now);//返回的时间时本初子母线的时间
    
}

DateTimeFormatter类

格式化或解析日期、时间

@Test
public void test3(){
    DateTimeFormatter time3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");

    //格式化
    String s = time3.format(LocalDateTime.now());
    System.out.println(s);//2020-12-05 03:36:08

    //解析
    TemporalAccessor accessor = time3.parse("2020-12-30 05:22:33");
    System.out.println(accessor);//{NanoOfSecond=0, SecondOfMinute=33, MicroOfSecond=0, MilliOfSecond=0, MinuteOfHour=22, HourOfAmPm=5},ISO resolved to 2020-12-30

}

Java比较器

使用Comparable接口和Comparator,对对象进行排序.

Comparable接口的使用举例:自然排序

  1. String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式。
  2. String、包装类重写compareTo()方法以后,进行了大小排列。
  3. 重写compareTo(obj)的规则:
    • 如果当前对象this大于形参对象obj,则返回正整数,
    • 如果当前对象this小于形参对象obj,则返回负整数,
    • 如果当前对象this等于于形参对象obj,则返回0。
  4. 对于自定义类来说,如果需要排序,我们可以让自定义类来实现Comparable接口,重写compareTo(obj)方法.
package compareTest;

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;
            if (this.price > goods.price){
                return 1;
            }else if(this.price<goods.price){
                return -1;
            }else
                return 0;
        }
        throw new RuntimeException("数据有问题");
    }
}
package compareTest;

import org.junit.jupiter.api.Test;

import java.util.Arrays;

public class CompareTest {
    @Test
    public void test(){
        Goods[] arr = new Goods[4];
        arr[0] = new Goods("lenovn",5);
        arr[1] = new Goods("dell",6);
        arr[2] = new Goods("xiaomi",3);
        arr[3] = new Goods("huawei",9);

        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));//[Goods{name='xiaomi', price=3.0}, Goods{name='lenovn', price=5.0}, Goods{name='dell', price=6.0}, Goods{name='huawei', price=9.0}]

    }
}

Comparator接口的使用:定制排序

  1. 背景:

    • 当元素的类型没有实现Comparable接口而又不方便修改代码,或者实现了Comparable接口但排序规则不适合当前的操作。
  2. 重写comparator(object o1,object o2)方法,比较o1和o2的大小:

    返回正整数,o1>o2

    返回负整数,o1<o2

    返回0,o1=o2

@Test
public void test1(){
    String[] arr = new String[]{"AA","CC","FF","EE","DD","GG","HH"};
    Arrays.sort(arr,new Comparator(){
        @Override
        public int compare(Object o1, Object o2) {
            if (o1 instanceof String && o2 instanceof String){
                String s1 = (String) o1;
                String s2 = (String) o2;
                return s1.compareTo(s2);

            }
            throw new RuntimeException("输入的数据类型不一致");
        }
    });
    System.out.println(Arrays.toString(arr));
}

二者对比

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

System类

image-20201205171352540

image-20201205171438673

Math类

image-20201205171506541

BigInteger

image-20201205171612006

image-20201205171634423

BigDecimal

image-20201205171703411

posted on 2020-12-05 20:01  kikikikikiku  阅读(79)  评论(0编辑  收藏  举报