第十一章、 Java常用类

第十一章、 Java常用类

11.1 包装类

11.1.1 包装类的分类

  1. 针对八种基本数据类型相应的引用类型-包装类
  2. 有了类的特点,就可以调用类中的方法。
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

11.1.2 包装类和基本数据的转换

  1. Jdk5前的手动装箱和拆箱方式,装箱:基本类型->包装类型(即把基本类型变成包装类型的过程称为装箱);拆箱反之。
  2. Jdk5以后(含jdk5)的自动装箱和拆箱方式
  3. 自动装箱底层调用的是valueOf方法,比如Integer.valueOf()
  4. 其他类型同理,面试题常考
package chapter11.wrapper;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class Integer01 {
    public static void main(String[] args) {
        //jdk5前是手动装箱和拆箱
        //手动装箱 int->Integer
        int n1=100;
        Integer integer=new Integer(n1);
        Integer integer1=Integer.valueOf(n1);
        //手动拆箱 Integer->int
        int n2=integer.intValue();

        //jdk5后,就可以自动装箱和拆箱
        int n3=100;
        //自动装箱
        Integer integer2=n3;//底层使用的是Integer.valueOf(n2)
        //自动拆箱
        int n4=integer2;//底层仍然使用的是 intValue()方法
    }
}

11.1.3 包装类练习

  1. 下面代码是否正确,为什么?
  2. 并判断两个输出语句输出是一样吗,如果不一样各是什么?为什么?
package chapter11.wrapper;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class WrapperType {
    public static void main(String[] args) {
        Double d=100d;//对,自动装箱,底层是Double.valueOf(100d);
        Float f=1.5f;//对,自动装箱,底层是Float.valueOf(1.5d);

        Object obj1=true?new Integer(1):new Double(2.0);
        System.out.println(obj1);//1.0,三元运算符是一个整体,会自动转型
        Object obj2;
        if(true){
            obj2=new Integer(1);
        }else{
            obj2=new Double(2.0);
        }
        System.out.println(obj2);//1
    }
}

11.1.4 包装类型和String类型的相互转换

  1. 通过代码来理解:包装类型和String类型之间的相互转换
package chapter11.wrapper;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class WrapperVSString {
    public static void main(String[] args) {
        //包装类型--->String类型
        Integer i=10;//自动装箱
        //方式1:
        String s1=i.toString();
        //方式2:
        String s2=String.valueOf(i);
        //方式3:这种方式不会改变i本身
        String s3=""+i;

        //String类型--->包装类类型
        String s="100";
        //方式1:
        Integer j1=new Integer(s1);//构造器
        //方式2:
        Integer j2=Integer.valueOf(s);
        //方式3:
        Integer j3=Integer.parseInt(s);//parseInt本身是返回int,但是这个可以进行自动装箱
    }
}

11.1.5 Integer类和Character类的常用方法

  1. Integer类和Character有些常用的方法(会常用方法即可。其他方法太多了,会查即可)。通过下面代码来理解。
package chapter11.wrapper;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class WrapperMethod {
    public static void main(String[] args) {
        System.out.println(Integer.MIN_VALUE);//通过访问属性,返回最小值
        System.out.println(Integer.MAX_VALUE);//返回最大值

        System.out.println(Character.isDigit('a'));//判断是否属于数字
        System.out.println(Character.isLetter('a'));//判断是否属于字母
        System.out.println(Character.isUpperCase('a'));//判断是否属于大写字母
        System.out.println(Character.isLowerCase('a'));//判断是否属于小写字母

        System.out.println(Character.isWhitespace('a'));//判断是否属于空格
        System.out.println(Character.toUpperCase('a'));//转成大写
        System.out.println(Character.toLowerCase('A'));//转成小写
    }
}
/*
-2147483648
2147483647
false
true
false
true
false
A
a
 */

11.1.6 Integer创建机制

  1. 查看下面代码,输出什么结果?为什么?
package chapter11.wrapper;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class WrapperExercise01 {
    public static void main(String[] args) {
        
    }
    public void method(){
        Integer i = new Integer(1);
        Integer j = new Integer(1);
        System.out.println(i==j);//false
        
        Integer m=1;
        Integer n=1;
        System.out.println(m==n);//true
        
        Integer x=128;
        Integer y=128;
        System.out.println(x==y);//false
    }
}

(1). 分析ij为什么是false,因为i和j分别是对象引用,对比的它的地址,所以是false。
(2). 分析m
n为什么是true,首先要知道底层代码是Integer.valueOf(1)。查看源码得知,当传入-128~127时,直接返回;否则就返回new Integer(x);
(3). 分析x
y为什么是false,由上面解释可得。

部分代码如下:(具体代码自行查看)
在这里插入图片描述
2. 查看下面代码,输出什么结果?为什么?

package chapter11.wrapper;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class WrapperExercise02 {
    public static void main(String[] args) {
        //1.
        Integer i1=new Integer(127);
        Integer j1=new Integer(127);
        System.out.println(i1==j1);//f

        //2.
        Integer i2=new Integer(128);
        Integer j2=new Integer(128);
        System.out.println(i2==j2);//f

        //3.
        Integer i3=127;
        Integer j3=127;
        System.out.println(i3==j3);//t

        //4.
        Integer i4=128;
        Integer j4=128;
        System.out.println(i4==j4);//f

        //5.
        Integer i5=127;
        Integer j5=new Integer(127);
        System.out.println(i5==j5);//f

        //6.如果存在基本数据类型,那么判断的是值是否相等
        Integer i6=127;
        int j6=127;
        System.out.println(i6==j6);//t

        //7.
        Integer i7=128;
        int j7=128;
        System.out.println(i7==j7);//t
    }
}

分析:如果存在基本数据类型,那么判断的是值是否相等

11.2 String

11.2.1 String类的理解和创建对象

  1. String对象用于保存字符串,也就是一组字符序列String 01.java
  2. 字符串常量对象是用双引号括起来的字符序列。例如:”你好”,”12.97”,”boy”等
  3. 字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
  4. String类较常用构造方法(其他看手册)
    (1). String s1=new String();
    (2). String s2=new String(String original);
    (3). String s3=new String(char[] a);
    (4). String s4=new String(char[] a,int startIndex,int count);
    (5). String 类实现了接口Serializable【String 可以串行化:可以在网络传输】、Comparable 【String 对象可以比较大小】
    (6). String 是final类,即不能被其他类继承
    (7). String有属性 private final byte[] value;用于存放字符串内容/,JDK8之前是char[]
    (8). 一定要注意:value 是一个final类型,不可以修改(重点):即内容可以修改,但是指向的地址不能修改(即value不能指向新地址)

在这里插入图片描述
在这里插入图片描述

package chapter11.string_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class String01 {
    public static void main(String[] args) {
        String name="jack";
        name="mark";
        //1.String 对象用于保存字符串,也就是一组字符序列
        //2."jack" 是字符串常量,双引号括起来的字符序列
        //3.字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
        //4.String类有很多构造器,构造器重载
        //        常用的有:
        //        (1). String s1=new String();
        //        (2). String s2=new String(String original);
        //        (3). String s3=new String(char[] a);
        //        (4). String s4=new String(char[] a,int startIndex,int count);
        //        (5). String s5=new String(byte[] b)
        //5.String 类实现了接口Serializable【String 可以串行化:可以在网络传输】
        //               接口Comparable 【String 对象可以比较大小】
        //6.String 是final类,即不能被其他类继承
        //7.String有属性 private final byte[] value;用于存放字符串内容/,JDK8之前是char[]
        //8.一定要注意:value 是一个final类型,不可以修改(重点):
        //  即内容可以修改,但是指向的地址不能修改(即value不能指向新地址)
        final byte[] value={1,2,3,4};
        value[0]=3;//可以修改内容
        byte[] v2={1,2,3,4};
//        value=v2;//报错,不可以修改value地址
    }

}

11.2.2 String结构剖析

  1. 创建String对象的两种方式
    (1). 方式一:直接赋值 String s=”hello”;
    (2). 方式二:调用构造器String s2=new String(“hello”);

  2. 两种创建String对象的区别
    (1). 方式一:先从常量池查看是否有”hello”的数据空间,如果有,直接指向;如果没有则重新创建,然后指向。s最终指向的是常量池的空间地址。
    (2). 方式二:先从堆中创建空间,里面维护了value属性,指向常量池的hello空间。如果常量池没有”hello”,重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。
    (3). 画出两种方式的内存分布图
    在这里插入图片描述

11.2.3 练习

  1. 思考下面代码输出什么?
package chapter11.string_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringExercise01 {
    public static void main(String[] args) {
        String a="hello";
        String b="hello";
        System.out.println(a.equals(b));//true,对比的是值
        System.out.println(a==b);//true,对比的是地址
    }
}
  1. 思考下面代码输出什么?
package chapter11.string_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringExercise02 {
    public static void main(String[] args) {
        String a=new String("hello");
        String b=new String("hello");
        System.out.println(a.equals(b));//true
        System.out.println(a==b);//false
    }
}
  1. 思考下面代码输出什么?
    知识点:
    当调用intern方法时,如果池中已经包含有一个等于这个String(用equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象的引用。
package chapter11.string_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringExercise03 {
    public static void main(String[] args) {
        String a="hello";   //指向 常量池中 hello的地址
        String b =new String("hello");  //指向的是堆中的对象,这个对象有个value指向常量池中 hello的地址
        String c = "hi";
        System.out.println(a.equals(b));// true
        System.out.println(a==b);//false
        System.out.println(a==b.intern());//true
        System.out.println(b==b.intern());//false
        System.out.println(c==b.intern());//false
        /*
        理解这个intern()的使用:
        由前面代码知道"hello",已经在常量池中存在了,那么执行b.intern(),
        如果常量池中存在和b对象的字符串一样的话,就将该返回池中的字符串,
        也就是b.intern指向的是常量池字符串"hello",否则,就将这个字符串"hello"
        添加到常量池中,返回这个b对象的引用,也就是b.intern指向的是堆中的对象
         */
    }
}
  1. 思考下面代码输出什么?
package chapter11.string_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringExercise04 {
    public static void main(String[] args) {
        String s1= "hello";
        String s2= "hi";
        String s3= "hi";
        String s4= new String("hi");
        System.out.println(s2==s3);//true
        System.out.println(s2==s4);//false
        System.out.println(s2.equals(s4));//true
        System.out.println(s1==s2);//false
    }
}
  1. 思考下面代码输出什么?
package chapter11.string_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringExercise05 {
    public static void main(String[] args) {
        Person p1=new Person();
        p1.name="hello";
        Person p2=new Person();
        p2.name="hello";

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

        String s1=new String("abc");
        String s2=new String("abc");
        System.out.println(s1==s2);//false
    }
}

class Person{
    public String name;
}

11.2.4 字符串的特性(面试题)

  1. 以下语句创建了几个对象?
String s1="hello";
s1="haha";
/*
2
理解:首先s1会去常量池寻找有没有hello这个字符串常量对象,如果没有就创建。
然后s1="haha",同理它会去常量池中寻找haha这个字符串常量对象,如果没有就创建。
并不会修改hello这个字符串常量对象
 */

总结:
(1). String是final类,代表不可变的字符序列
(2). 字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的。

  1. 以下语句创建了几个对象?
String a="hello"+"hi";
/*
创建了1个对象
 String a="hello"+"hi";底层优化等价于 String a="hellohi";
 */

总结:
(1). 编译器会做一个优化,判断创建的是不是属于字符串常量,如果是就做优化
(2). String a=“hello”+“hi”;==>底层优化等价于 String a=“hellohi”;

  1. 以下语句创建了几个对象?
package chapter11.string_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringExercise3 {
    public static void main(String[] args) {
        String a="hello";
        String b="hi";
        String c=a+b;
        /*
        创建了3个对象,但是对象引用不一样。a和b指向的常量池的字符串常量对象;而c指向的堆中对象的value。
        底层实现:
        1. 先创建一个StringBuilder sb=StringBuilder();
        2. 执行 sb.append("hello");
        3. sb.append("hi");
        4. String c=sb.toString();
        最后 c 指向堆中的对象(String) value[]-->池中"hellohi"
         */
        //证明c指向的不是池中的hellohi
        String s="hellohi";
        String s2="hello"+"hi";
        System.out.println(c==s);//false
        System.out.println(c==s2);//false
    }
}

总结:
(1). 底层是StringBuilder sb=StringBuilder(); sb.append(“hello”); sb.append(“hi”);
(2). String c=sb.toString(); sb在堆中,并且append是在原来字符串的基础上追加的。
(3). 重要规则:String c1=“ab”+“cd”;常量相加,看的是池。String c1=a+b; 变量相加,是在堆中。

  1. 判断下面代码输出什么?为什么?
package chapter11.string_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringExercise4 {
    public static void main(String[] args) {
        String s1="hello";//指向池中的"hello"
        String s2="hi";//指向池中的"hi"
        String s3="hellohi";//指向池中的"hellohi"
        String s4=(s1+s2).intern();//指向池中的"hellohi"
        System.out.println(s3==s4);//true
        System.out.println(s3.equals(s4));//true
    }
}
  1. 判断下面代码输出什么?为什么?(重点)
package chapter11.string_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class Test1 {
    public static void main(String[] args) {
        Test1 ex = new Test1();
        ex.change(ex.str,ex.ch);
        System.out.print(ex.str+ "   and  ");
        System.out.println(ex.ch);
        //输出:hello   and  wello
    }
    String str = new String("hello");
    final char[] ch ={'h','e','l','l','o'};
    public void change(String str ,char ch[]){
        str="hi";
        ch[0]='w';
    /*
    理解:首先在堆中创建了一个Test1对象指向main栈中的ex,在这个Test1对象中,有创建了一个str指向堆另一个String对象
    这个String对象有个属性value,value指向池中的"hello",ch就直接在静态区生成数组。
    然后ex引用变量调用方法change(),传入了str和ch.这时候在change栈中有一个str的变量指向了Test1对象的str
    而ch直接指向栈中静态区的数组。再然后执行str="hi",它是change栈中str的变量就去常量池中寻找或创建。
    也就是说这时候change栈的str指向的是池中的"hi"与Test1对象的str就没有关系了。
    而ch[0]='w'是栈中数组的引用传递,是可以直接在静态区的数组进行修改。所以最后输出:hello   and  wello
     */
    }
}

11.2.5 String类的常见方法

说明:
String类是保存字符串常量的。每次更新都需要重新开辟空间,效率较低,因此java设计者还提供了StringBuilder和StringBuffer来增强String的功能,并提高开发效率。

  1. String类的常见方法一览(不用背,用多就会啦)
    (1). equals //区分大小写,判断内容是否相等
    (2). equalsIgnoreCase //忽略大小写的判断内容是否相等
    (3). length //获取字符的个数,字符串长度
    (4). indexOf //获取字符或子串在字符串中第一次出现的索引,索引从0开始,如果找不到就返回-1
    (5). lastIndexOf //获取字符或子串在字符串中最后一次出现的索引,索引从0开始,如果找不到就返回-1
    (6). substring //截取指定范围的子串
    (7). trim //去前后空格
    (8). charAt //获取某索引处的字符,注意不能使用Str[index]这样的方式
    (9). toUpperCase //将小写字母转换成大写
    (10). toLowerCase //将大写字母转换成小写字母
    (11). concat //拼接字符串
    (12). replace //替换字符串中的字符,返回的是新的字符串,本身没有改变
    (13). split //分割字符串,对于某些分割字符,需要用到转义 .比如| \等
    (14). compareTo // 比较两个字符串的大小,如果前者大则返回正数;否则就返回负数;若相等则返回0
    (15). toCharArray //将字符串转换成字符数组
    (16). format //格式化字符串,占位符:%s字符串 %c字符 %d整型 %.2f浮点型(四舍五入)
package chapter11.string_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringMethod01 {
    public static void main(String[] args) {
        //(1). equals  //区分大小写,判断内容是否相等
        String s1="hello";
        String s2="Hello";
        System.out.println(s1.equals(s2));//false

        //(2). equalsIgnoreCase //忽略大小写的判断内容是否相等
        String a1="hi";
        String a2="HI";
        System.out.println(s1.equalsIgnoreCase(a2));//false

        //(3). length //获取字符的个数,字符串长度
        System.out.println("hello".length());//5

        //(4). indexOf //获取字符或子串在字符串中第一次出现的索引,索引从0开始,如果找不到就返回-1
        String b1="ehi@hi@3@";
        System.out.println(b1.indexOf('@'));//3
        System.out.println(b1.indexOf("hi"));//1
        System.out.println(b1.indexOf('c'));//-1

        //(5). lastIndexOf  //获取字符或子串在字符串中最后一次出现的索引,索引从0开始,如果找不到就返回-1
        String b2="ehi@hi@3@";
        System.out.println(b2.lastIndexOf('@'));//8
        System.out.println(b1.lastIndexOf("hi"));//4
        System.out.println(b2.lastIndexOf('c'));//-1

        //(6). substring //截取指定范围的子串
        String c="hello,java";
        System.out.println(c.substring(1));//从索引开始截取到最后面:ello.java
        System.out.println(c.substring(1,3));//截取索引1-2(遵循左闭右开):el

        //(7). trim  //去前后空格
        String d="   hello    ";
        System.out.println(d.trim());//hello

        //(8). charAt  //获取某索引处的字符,注意不能使用Str[index]这样的方式
        String e="hello";
        System.out.println(e.charAt(2));//l

        //(9). toUpperCase //将小写字母转换成大写
        String f="HEllo";
        System.out.println(f.toUpperCase());//HELLO

        //(10).    toLowerCase  //将大写字母转换成小写字母
        String g="heLLO";
        System.out.println(g.toLowerCase());//hello

        //(11).    concat  //拼接字符串
        String h1="你好";
        String h2=",mark";
        System.out.println(h1.concat(h2));//你好,mark

        //(12).    replace //替换字符串中的字符,返回的是新的字符串,本身没有改变
        String i="hello,jack";
        System.out.println(i.replace("jack","mark"));//将所有的jack替换为mark:hello,mark
        System.out.println(i);//hello,jack

        //(13).    split  //分割字符串,对于某些分割字符,需要用到转义 \.比如| \\等
        String j1="hi,mark";
        System.out.println(j1.split(",")[0]);//以,为标准进行分割,返回的是一个数组:hi
        String j2="E:\\cd\\ef";
        System.out.println(j2.split("\\\\")[0]);//E:

        //(14).    compareTo  //比较两个字符串的大小,如果前者大则返回正数;否则就返回负数;若相等则返回0
        // 比较规则:从str1和str2两个字符串的索引0开始按字符逐一比较,若第一个相同,则一直往下比较,
        // 直到str1和str2的某个位置的字符不相同,用str1的字符 - str2的字符(按Unicode码来)。
        //若 str1 和 str2 直到最后一个字符都相同,则比较长度,返回 str1.length() - str2.length()。
        String str1="abff";//a-97,b-98,c-99
        String str2="acd";
        String str3="acdef";
        System.out.println(str1.compareTo(str2));//-1
        System.out.println(str2.compareTo(str3));//-2


        //(15).    toCharArray  //将字符串转换成字符数组
        String l="hello";
        char[] ch=c.toCharArray();
        System.out.println(ch[0]);//h

        //(16).    format  //格式化字符串,占位符:%s字符串 %c字符  %d整型 %.2f浮点型(四舍五入)
        String n="我的名字是%s  年龄是%d  成绩是%.2f 性别是%c . 很高兴认识大家....";
        String info=String.format(n,"mark",22,87.758,'男');
        System.out.println(info);//我的名字是mark  年龄是22  成绩是87.76 性别是男 . 很高兴认识大家....
    }
}
  1. 输入商品名称和商品价格,要求打印效果示例,使用String.format的方法来实现:
    StringMethod02.java
    商品名 商品价格
    手机 123,456.79
    要求:使用千位分隔符。
package chapter11.string_;

import java.util.InputMismatchException;
import java.util.Scanner;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringMethod02 {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        System.out.print("请输入商品:");
        String goods=scanner.next();
        double price= 0;
        try {
            System.out.print("请输入手机价格:");
            price = scanner.nextDouble();
        } catch (InputMismatchException e) {
            System.out.println("你输入的价格不正确(默认0.00)");
        }

        String ans =String.format("商品名\t商品价格\n%s\t\t%,.2f",goods,price);
        System.out.print(ans);

    }
}
/*
请输入商品:菠萝手机
请输入手机价格:123
商品名	商品价格
菠萝手机		123.00
 */

11.3 StringBuffer

11.3.1 StringBuffer结构剖析

  1. 基本介绍
    (1). Java.lang.StringBuffer代表可变的字符序列,可以对字符串内容进行增删。
    (2). 很多方法和String相同,但StringBuffer是可变长度的。
    (3). StringBuffer是一个容器。

  2. 结构剖析
    (1). StringBuffer 的直接父类是AbstractStringBuilder
    (2). StringBuffer 实现了Serializable ,即StringBuffer的对象可以序列化(串行化)、比如保存文件、或网络传输。
    (3). 在父类中 AbstractStringBuilder 有属性 byte[ ] value,不是final,该value数组存放的是字符串内容,因此存放在堆中,而不是常量池中。
    (4). StringBuffer是一个fianl类,不能被继承
    (5). 因为StringBuffer 字符内容是在 byte[ ] value,所以在变化(增加/删除)不用每次都更换地址(即不是每次都创建对象),所以效率高于String。

  3. String VS StringBuffer
    String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低 //private final char value[ ];
    StringBuffer保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址(除了空间不够),效率较高 // char[ ] value //放在堆中

11.3.2 StringBuffer转换

  1. StringBuffer的构造器
构造方法描述
StringBuffer()构造一个其中不带字符的字符串缓冲区,其初始容量为16个字符。
StringBuffer(CharSequence seq)构造一个字符串缓冲区,它包含与指定的CharSequence相同的字符
StringBuffer(int capacity)构造一个不带字符,但具有指定初始容量的字符串缓冲区。即对byte[ ]大小进行指定
StringBuffer(String str)构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。
package chapter11.stringbuffer_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringBuffer01 {
    public static void main(String[] args) {
        //1.构造一个其中不带字符的字符串缓冲区,其初始容量为16个字符。
        StringBuffer stringBuffer = new StringBuffer();//16
        System.out.println(stringBuffer.capacity());

        //2.构造一个不带字符,但具有指定初始容量的字符串缓冲区。即对byte[ ]大小进行指定
        StringBuffer stringBuffer1 = new StringBuffer(4);//4
        System.out.println(stringBuffer1.capacity());

        //3.构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。char[ ]大小 str.length()+16
        StringBuffer hello = new StringBuffer("hello");//21
        System.out.println(hello.capacity());
    }
}
  1. String和StringBuffer相互转换
    在开发中,经常需要将String和StringBuffer进行转换,看看如何实现。
package chapter11.stringbuffer_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringBuffer02 {
    public static void main(String[] args) {
        //String-->StringBuffer
        String s = "hello";
        //方式一 使用构造器,对s本身没有任何影响
        StringBuffer b1=new StringBuffer(s);
        //方式二 使用append()方法
        StringBuffer b2=new StringBuffer();
        b2.append(s);

        //StringBuffer-->String
        //方式一 使用StringBuffer提供的toString()方法
        String s2=b1.toString();//b1 [StringBuffer]
        //方式二 使用构造器
        String s3=new String(b2);
    }
}

11.3.3 StringBuffer方法

  1. StringBuffer类常用方法
    StringBufferMethod.java
    (1). 增 append()
    (2). 删 delete(start,end)
    (3). 改replace(start,end,string) //将start—end间的内容替换掉,不含end
    (4). 查 indexOf() //查找子串在字符串第一次出现的索引,如果找不到返回-1
    (5). 插 insert()
    (6). 获取长度 length()
package chapter11.stringbuffer_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringBufferMethod {
    public static void main(String[] args) {
        StringBuffer strbu=new StringBuffer("hello");
        //1. 增
        strbu.append(',');
        strbu.append("李四");
        strbu.append("王五").append(100).append(true).append(19.19);
        System.out.println(strbu);//hello,李四王五100true19.19

        //2.删 (start,end)左闭右开
        strbu.delete(6,10);
        System.out.println(strbu);//hello,100true19.19

        //3.改(start,end,"")左闭右开
        strbu.replace(9,13,"false");
        System.out.println(strbu);//hello,100false19.19

        //4.查
        int ans =strbu.indexOf("1");
        System.out.println(ans);//6

        //5.插
        strbu.insert(6,"小青");//索引6插入,原来索引为6后移
        System.out.println(strbu);//hello,小青100false19.19

        //6.获取长度
        int len=strbu.length();
        System.out.println(len);//21
    }
}

11.3.4 StringBuffer练习

  1. 看看下面代码输出什么?为什么?(不要猜,要看看源码)
package chapter11.stringbuffer_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringBufferExercise01 {
    public static void main(String[] args) {
        String str =null;
        StringBuffer sb=new StringBuffer();
        sb.append(str);//查看源码知:如果str=null,就生成一个null的字符串
        System.out.println(sb.length());//4
        System.out.println(sb);//null

        // null.lenth()存在异常:NullPointerException
        StringBuffer sb1=new StringBuffer(str);//查看源码知:super(str.length() + 16);
        System.out.println(sb1);//
    }
}
  1. 输入商品名称和商品价格,要求打印效果示例,使用StringBuffer的insert的方法来实现:
    StringBufferExercise02.java
    商品名 商品价格
    手机 123,456.48
    要求:使用千位分隔符(不考虑进行四舍五入)。
package chapter11.stringbuffer_;

import java.util.Scanner;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringBufferExercise02 {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        System.out.print("请输入商品:");
        StringBuffer goods=new StringBuffer(scanner.next());
        System.out.print("请输入价格:");
        StringBuffer price=new StringBuffer(scanner.next());
        int i=price.indexOf(".");
        int len=price.length();
        if(i==-1){
            i=len;
        }
        while(i>3){
            i-=3;
            price.insert(i,",");
        }
        System.out.println(goods);
        System.out.println(price);
    }
}
/*
请输入商品:123
请输入价格:123456.34
123
123,456.34
 */

11.4 StringBuilder

11.4.1 StringBuilder结构剖析

  1. StringBuilder基本介绍
    (1). 一个可变的字符序列。此类提供一个与StringBuffer兼容的API,但不保证同步。该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可能,建议优先采用该类,因为在大多数实现中,它比线程使用的时候。如果可能,建议优先采用该类,因为在大多数实现中,它比StringBuffer要快。
    (2). 在StringBuilder上的主要操作是append和insert方法,可重载这些方法,以接收任意类型的数据。

  2. StringBuilder常用方法
    StringBuilder和StringBuffer均代表可变的字符序列,方法是一样的,所以使用和StringBuffer一样。

  3. StringBuilder结构剖析
    (1). StringBuilder 继承 AbstractStringBuilder类
    (2). 实现了Serializable,说明StringBuilder对象是可以串行化(网络传输、保存到文件)
    (3). StringBuilder 是final类,不能被继承
    (4). StringBuilder 对象字符序列仍然是存放在其父类AbstractStringBuilder 的byte[] value;因此,字符序列是在堆中的。
    (5). StringBuilder的方法,没有做互斥的处理,即没有synchronized关键字,因此在单线程的情况下优先使用StringBuilder。

11.4.2 StringBuilder应用

  1. String、StringBuffer和StringBuilder的比较(面试)
    (1). StringBuilder和StringBuffer非常类似,均代表可变的字符序列,而且方法也一样。
    (2). String:不可变字符序列,效率低,但是复用率高(即可以被多个变量指向)
    (3). StringBuffer:可变字符序列、效率较高(增删)、线程安全
    (4). StringBuilder:可变字符序列、效率最高、线程不安全
    (5). String使用注意事项:
String s="a";
s+="b";//实际上原来的"a"字符串对象因为没有对象引用指向,所以就丢弃了(被JVM销毁了),现在又生成了一个字符串s+="b"(也就是"ab")。
//如果多次执行这些改变串内容的操作,会导致大量副本字符串对象留在内存中,降低效率。如果这样的操作放到循环中,
// 会极大影响程序的性能==>结论:如果我们对String做大量修改,不要使用String
  1. 测试String、StringBuffer和StringBuilder执行效率
package chapter11.StringBulider_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class StringBuilder01 {
    public static void main(String[] args) {
        final int ITERATIONS = 1000000;

        // 测试 String
        long startTime = System.currentTimeMillis();
        String str = "";
        for (int i = 0; i < ITERATIONS; i++) {
            str += "a";
        }
        long endTime = System.currentTimeMillis();
        System.out.println("String 执行时间: " + (endTime - startTime) + " ms");

        // 测试 StringBuffer
        startTime = System.currentTimeMillis();
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < ITERATIONS; i++) {
            stringBuffer.append("a");
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuffer 执行时间: " + (endTime - startTime) + " ms");

        // 测试 StringBuilder
        startTime = System.currentTimeMillis();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < ITERATIONS; i++) {
            stringBuilder.append("a");
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuilder 执行时间: " + (endTime - startTime) + " ms");
    }
}
/*
String 执行时间: 72706 ms
StringBuffer 执行时间: 12 ms
StringBuilder 执行时间: 9 ms
 */
  1. String、StringBuffer和StringBuilder的选择(使用的原则)
    (1). 如果字符串存在大量的修改操作,一般使用StringBuffer或StringBuilder
    (2). 如果字符串存在大量的修改操作,存在单线程的情况,使用StringBuilder
    (3). 如果字符串存在大量的修改操作,存在多线程的情况,一般使用StringBuffer
    (4). 如果字符串很少修改,被多个对象引用,使用String,比如配置信息等

11.5 Math

  1. 基本介绍
    Math类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
  2. 方法一览(均为静态方法)只例举了部分(具体查看API)

在这里插入图片描述
4. Math类常见方法应用案例MathMethod.java
(1). abs绝对值
(2). pow 求幂
(3). ceil 向上取整
(4). floor 向下取整
(5). round 四舍五入
(6). sqrt 求开方
(7). random 求随机函数
(8). max 求两个数的最大值
(9). min 求两个数的最小值

package chapter11.math_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class MathMethod {
    public static void main(String[] args) {
        //(1). abs绝对值
        System.out.println(Math.abs(-99));//99
        //(2). pow 求幂,返回double
        System.out.println(Math.pow(2,3));//8.0,2的3次方
        //(3). ceil  向上取整,返回double
        System.out.println(Math.ceil(-2.000001));//-2.0
        //(4). floor  向下取整,返回double
        System.out.println(Math.floor(-1.0000001));//-2.0
        //(5). round 四舍五入,返回long
        System.out.println(Math.round(4.56768));//5
        //(6). sqrt  求开方,返回double
        System.out.println(Math.sqrt(4));//2.0
        //(7). random 求随机函数,一个伪随机 double大于或等于 0.0并小于 1.0,返回double
        System.out.println(Math.random());
        //(8). max 求两个数的最大值
        System.out.println(Math.max(10,9));//10
        //(9). min 求两个数的最小值
        System.out.println(Math.min(10,9));//9
    }
}
  1. 练习
    (1). 请使用Math.random获取a-b之间的一个随机整数,a和b均为整数,比如:a=2,b=7
package chapter11.math_;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class MathExercise {
    public static void main(String[] args) {
        int a=2;
        int b=7;
        for (int i = 0; i < 15; i++) {
            int ans=(int) (a+Math.random()*(b-a+1));
            System.out.println(ans);
        }
    }
}
//输出随机的2至7

11.6 Date、Calendar、LocalDate…

日期类分为了三代。【知道怎么查,怎么用即可,不用每个方法都背】

11.6.1 第一代日期类

  1. 日期和时间模式
    在这里插入图片描述
  2. Date:精确到毫秒,代表特定的时间
  3. SimpleDateFormat:格式和解析日期的具体类。它允许进行格式化(日期->文本)、解析(文本->日期)和规范化
package chapter11.date_;

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

/**
 * @aim java基础学习
 * @note java笔记
 */
public class Date01 {
    public static void main(String[] args) {
        // 1.获取当前系统时间
        // 2.这里的Date类是在java.util中的,而不是在java.sql中
        // 3.默认输出的日期格式是外国的方式,通常需要进行格式化处理
        Date d1 = new Date();
        System.out.println(d1);//Sun Aug 11 23:21:36 CST 2024
        //获取某个时间对应的毫秒数
        System.out.println(d1.getTime());//1723389696776

        //通过指定毫秒数得到时间
        Date d2 = new Date(9234567);
        System.out.println(d2);//Thu Jan 01 10:33:54 CST 1970


        //这里的字母是规定好的,不可以乱写
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");
        //将日期转换成指定格式的字符串
        String format =sdf.format(d1);
        System.out.println(format);//2024年08月11日 11:32:16 周日

        //1.将文本转换成日期格式
        //2.把Date输出时,仍然还是外国的方式,如需指定格式还是要转换
        //3.在把String-->Date  , 使用的sdf格式需要和String的格式一样,否则就会抛出ParseException异常
        String s="1996年02月23日 10:20:30 星期一";
        try {
            Date parse=sdf.parse(s);
            System.out.println(parse);//Fri Feb 23 10:20:30 CST 1996
        } catch (ParseException e) {
            System.out.println("日期格式不对");
        }

    }
}

11.6.2 第二代日期类

  1. 第二代日期类,主要就是Calendar类(日历)
public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar>
  1. Calendar类是一个抽象类,它为特定瞬间与一组诸如YEAR、MONTH、DAY_OF_MONTH、HUOR等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法
package chapter11.date_;

import java.util.Calendar;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class Calendar01 {
    public static void main(String[] args) {
        //1.Calendar是一个抽象类,并且构造器是protected
        //2.可以通过getInstance() 来获取实例
        //3.提供大量的方法和字段提供给程序员
        //4.Calendar没有专门的格式化方法,所以需要程序员自己来组合显示
        //5.如果需要按照 24小时进制来获取时间,Calendar.HOUR 改为 Calendar.HOUR_OF_DAY
        Calendar c = Calendar.getInstance();//创建日历类对象
        //获取日历对象的某个日历字段
        System.out.println("年:" + c.get(Calendar.YEAR));
        //这里为什么要+1,因为Calendar返回月的时候,是按照0开始编号的
        System.out.println("月:" + (c.get(Calendar.MONTH) + 1));
        System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
        System.out.println("小时:" + c.get(Calendar.HOUR));
        System.out.println("小时:" + c.get(Calendar.HOUR_OF_DAY));
        System.out.println("分钟:" + c.get(Calendar.MINUTE));
        System.out.println("秒:" + c.get(Calendar.SECOND));
        //Calendar没有专门的格式化方法,所以需要程序员自己来组合显示
        System.out.println(c.get(Calendar.YEAR) + "年" + (c.get(Calendar.MONTH) + 1) + "月"
                + c.get(Calendar.DAY_OF_MONTH) + "日");
    }
}
/*
年:2024
月:8
日:12
小时:3
小时:15
分钟:48
秒:5
2024年8月12日
 */

11.6.3 第三代日期类

  1. 前面两代日期类的不足分析(具体使用请查看API文档)
    (1). JDK1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK1.1引入了Calendar类之后被弃用了。
    (2). 而Calendar也存在问题是:
    ① 可变性:像日期和时间这样的类应该是不可变的。
    ② 偏移性:Date中的年份是从1900开始的,而月份都从0开始
    ③ 格式化:格式化只对Date有用,Calendar则不行
    ④ 此外,它们也不是线程安全的;不能处理闰秒等(每隔两天,多出1s)

  2. 第三代日期类常见方法JDK8加入
    LocalDate(日期/年月日)、LocalTime(时间/时分秒)、LocalDateTime(日期时间/年月日时分秒)
    (1). LocalDate只包含日期,可以获取日期字段
    (2). LocalTime只包含时间,可以获取时间字段
    (3). LocalDateTime包含日期+时间,可以获取日期和时间字段

package chapter11.date_;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class LocalDate_ {
    public static void main(String[] args) {
        //第三代日期
        LocalDateTime ldt =LocalDateTime.now();//返回当前日期时间(年月日时分秒)的对象
        System.out.println(ldt);//2024-08-12T16:09:01.867845500
        System.out.println(ldt.getYear());//2024
        System.out.println(ldt.getMonth());//AUGUST
        System.out.println(ldt.getMonthValue());//8
        System.out.println(ldt.getDayOfMonth());//12
        System.out.println(ldt.getHour());//16
        System.out.println(ldt.getMinute());//9
        System.out.println(ldt.getSecond());//1
        
        LocalDate.now();//返回当前年月日
        LocalTime.now();//返回当前时分秒
    }
}

(4). DateTimeFormatter格式日期类。类似于:SimpleDateFormat

DateTimeFormat dtf=DatetimeFormatter.ofPattern(格式);
String str=dtf.format(日期格式);

在这里插入图片描述

package chapter11.date_;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class LocalDateFormat_ {
    public static void main(String[] args) {
        //创建当前日期时间(年月日时分秒)的对象
        LocalDateTime ldt = LocalDateTime.now();

        //创建DateTimeFormatter对象
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年mm月dd日 HH时mm分ss秒");
        String format = dtf.format(ldt);
        System.out.println(format);//2024年10月12日 19时10分53秒
    }
}

(5). Instant时间戳
类似于Date
提供了一系列和Date类转换的方式如下代码:

package chapter11.date_;

import java.time.Instant;
import java.util.Date;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class Instant_ {
    public static void main(String[] args) {
        //1.通过 静态方法 now() 获取表示当前时间戳的对象
        Instant now=Instant.now();
        System.out.println(now);//2024-08-12T11:16:18.989720Z
        
        //2.将Instant----> Date:通过from
        Date date=Date.from(now);
        System.out.println(date);//Mon Aug 12 19:16:36 CST 2024
        
        //将Date---->Instant:通过Date的toInstant()
        Instant instant=date.toInstant();
        System.out.println(instant);//2024-08-12T11:16:52.273Z
    }
}

(6). 第三代日期类更多方法

  • LocalDateTime类
  • MonthDay类:检查重复事件
  • 是否是闰年
  • 增加日期的某个部分
  • 使用plus方法测试增加时间的某个部分
  • 使用minus方法测试查看一年前和一年后的日期
package chapter11.date_;

import java.time.LocalDateTime;
import java.time.MonthDay;
import java.time.Year;
import java.time.temporal.ChronoUnit;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class DateTimeMethod_ {
    public static void main(String[] args) {
        // 当前日期和时间
        LocalDateTime now = LocalDateTime.now();
        System.out.println("当前日期和时间: " + now);

        // MonthDay类检查重复事件
        MonthDay event = MonthDay.now();
        System.out.println("今天的日期(月-日格式): " + event);

        // 是否是闰年
        int currentYear = now.getYear();
        boolean isLeapYear = Year.isLeap(currentYear);
        System.out.println(currentYear + " 是闰年吗? " + isLeapYear);

        // 增加日期的某个部分
        LocalDateTime futureDate = now.plusDays(10).plusMonths(1);
        System.out.println("增加10天和1个月后的日期: " + futureDate);

        // 使用plus方法测试增加时间的某个部分
        LocalDateTime dateInTwoWeeks = now.plusWeeks(2);
        System.out.println("从现在起2周后的日期: " + dateInTwoWeeks);

        // 使用minus方法测试查看一年前和一年后的日期
        LocalDateTime dateOneYearAgo = now.minusYears(1);
        LocalDateTime dateOneYearLater = now.plusYears(1);
        System.out.println("一年前的日期: " + dateOneYearAgo);
        System.out.println("一年后的日期: " + dateOneYearLater);

        // 使用ChronoUnit测试时间差
        long daysBetween = ChronoUnit.DAYS.between(now, dateOneYearLater);
        System.out.println("从现在到一年后共有 " + daysBetween + " 天");
    }
}
/*
当前日期和时间: 2024-08-12T19:32:29.285117800
今天的日期(月-日格式): --08-12
2024 是闰年吗? true
增加10天和1个月后的日期: 2024-09-22T19:32:29.285117800
从现在起2周后的日期: 2024-08-26T19:32:29.285117800
一年前的日期: 2023-08-12T19:32:29.285117800
一年后的日期: 2025-08-12T19:32:29.285117800
从现在到一年后共有 365 天
 */

11.7 System

11.7.1 System类常用的方法和案例

  1. exit退出当前程序
  2. arraycopy:复制数组元素,比较适合底层调用,一般使用Arrays.copyOf完成复制数组
  3. currentTimeMillens:返回当前时间距离1970-1-1的毫秒数
  4. gc:运行垃圾回收机制System.gc();
package chapter11.system_;

import java.util.Arrays;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class System01 {
    public static void main(String[] args) {
        //1.   exit退出当前程序
        System.out.println("hello");
//        System.exit(0);//0表示一个状态,正常的状态。
        System.out.println("hello");

        //2.   arraycopy:复制数组元素,比较适合底层调用,一般使用Arrays.copyOf完成复制数组
        /*
        形参分析:
        src - 源数组。
        srcPos - 源数组中的起始位置。
        dest - 目标数组。
        destPos - 目标数据的起始位置。
        length - 要复制的数组元素个数。
         */
        int[] src={1,2,3};
        int[] dest= new int[3];//当前数组dest={0,0,0}
        System.arraycopy(src,1,dest,1,2);
        System.out.println(Arrays.toString(dest));//[0, 2, 3]

        //3.   currentTimeMillens:返回当前时间距离1970-1-1的毫秒数
        long start=System.currentTimeMillis();
        System.out.println(start);//1723378894796

        //4.   gc:运行垃圾回收机制System.gc();
        System.gc();
    }
}

11.8 Arrays

11.8.1 Arrays类常见方法应用案例

  1. Arrays里面包含了一系列静态方法,用于管理或操作数据(比如排序和搜索)
    (1). toString返回数组的字符串形式
    (2). sort排序(自然排序和定制排序)。
    (3). binarySearch 通过二分查找法进行查找,要求必须排好序。若无则return -(low + 1).
    (4). copyOf数组元素的复制
    (5). fill 数组元素的填充
    (6). equals比较两个数组元素内容是否完全一致。
    (7). asList 将一组值,转换成List集合
package chapter11.arrays_;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class ArraysMethod {
    public static void main(String[] args) {
        //1.toString返回数组的字符串形式
        Integer arr1[] = {1, 2, 3, 4, 5, 6};
        System.out.println(Arrays.toString(arr1));//[1, 2, 3, 4, 5, 6]

        //2.sort排序(自然排序和定制排序)。
        Integer arr2[] = {1, -1, 7, 0, 89};
        //(1).默认排序,从小到大
        Arrays.sort(arr2);
        System.out.println(Arrays.toString(arr2));//[-1, 0, 1, 7, 89]
        //(2).定制排序,从大到小,传入两个参数,第一个是arr数组,第二个是实现了Comparator的匿名内部类,实现了compare方法。
        /*
        ①.体现的是接口编程的方式,源码分析:
        ②.Arrays.sort(arr3, new Comparator(),先进入Arrays的sort中
        最终到TimSort类的private static <T> void binarySort(T[] a, int lo, int hi, int start,
                                       Comparator<? super T> c)
         ③.执行到binarySort方法的代码,会根据动态绑定机制c.compare()执行传入的匿名内部类的方法compare()
          while (left < right) {
                int mid = (left + right) >>> 1;
                if (c.compare(pivot, a[mid]) < 0)
                    right = mid;
                else
                    left = mid + 1;
            }
        ④.public int compare(Object o1, Object o2) 返回的是>0,还是<0;会影响整个排序结果
        这就充分体现了 接口编程+动态绑定+匿名内部类的综合使用;将来的底层框架和源码使用方式,会非常常见。
         */
        Integer arr3[] = {1, -1, 7, 0, 89};
        Arrays.sort(arr3, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                Integer i1=(Integer) o1;
                Integer i2=(Integer) o2;
                return i2-i1;
            }
        });
        System.out.println(Arrays.toString(arr3));//[89, 7, 1, 0, -1]

        //(3). binarySearch 通过二分查找法进行查找,要求必须排好序。
        Integer[] arr4={1,4,5,9,12,34,45};
        int index=Arrays.binarySearch(arr4,5);
        System.out.println(index);//2
        int notindex=Arrays.binarySearch(arr4,35); // return -(low + 1);  // key not found.
        System.out.println(notindex);//-7,按道理35应该在34后面,即35的索引应该是6,即low=6

        //(4). copyOf数组元素的复制
        //拷贝的长度要>0,否则就会抛出异常NegativeArraySizeException,
        // 若大于拷贝数组arr的长度,就在新数组后面添加 null,若长度在0<=arr<arr.length(),则复制部分元素
        //该方法的底层使用的是  System.arraycopy()
        Integer[] arr5={1,2,3,4};
        Integer[] newArr = Arrays.copyOf(arr5,arr5.length+2);
        System.out.println(Arrays.toString(newArr));//[1, 2, 3, 4, null, null]

        //(5). fill 数组元素的填充
        Integer[] num = new Integer[]{9, 4, 3};
        Arrays.fill(num, 99);
        System.out.println(Arrays.toString(num));//[99, 99, 99]

        //(6). equals比较两个数组元素内容是否完全一致。
        Integer[] a1={1,2,3,4};
        Integer[] a2={1,2,3,4};
        boolean equals =Arrays.equals(a1,a2);
        System.out.println(equals);//true

        //(7). asList 将一组值,转换成list集合
        // 编译类型是List(接口)
        // 运行类型是java.util.Arrays$ArrayList,ArrayList是内部类
        // 静态内部类  private static class ArrayList<E> extends AbstractList<E>
        //        implements RandomAccess, java.io.Serializable
        List asList = Arrays.asList(1, 2, 3, 4, 5, 6);
        System.out.println("asList=" + asList);//asList=[1, 2, 3, 4, 5, 6]
        System.out.println(asList.getClass());//class java.util.Arrays$ArrayList

    }
}

11.8.2 Arrays类练习

  1. 实现冒泡排序
    (1). 编写一个方法 Bubble 对整数数组进行冒泡排序,默认从小到大排序。
    (2). 编写一个重载的方法 Bubble,接受一个 Comparator 对象,按照自定义的排序规则对整数数组进行冒泡排序。
    要求:
    (1). Bubble(Integer[] arr): 对给定的整数数组进行排序,按照从小到大的顺序。
    (2). Bubble(Integer[] arr, Comparator c): 对给定的整数数组进行排序,按照 Comparator 提供的排序规则(可以是从大到小或其他自定义顺序)。
package chapter11.arrays_;

import java.util.Arrays;
import java.util.Comparator;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class ArraysBubble {
    public static void main(String[] args) {
        Integer arr[] = {3, -2, 12, 0, 4, 90};
        // 使用默认的冒泡排序(从小到大)
        Bubble(arr);
        System.out.println(Arrays.toString(arr)); // 输出: [-2, 0, 3, 4, 12, 90]

        Integer arr1[] = {3, -2, 12, 0, 4, 90};
        // 使用带有Comparator的冒泡排序(从大到小)
        Bubble(arr1, new Comparator<Integer>() {
            @Override
            public int compare(Integer i1, Integer i2) {
                // 比较两个整数,返回负数表示 i1 应该排在 i2 前面
                return i2 - i1;
            }
        });
        System.out.println(Arrays.toString(arr1)); // 输出: [90, 12, 4, 3, 0, -2]
    }

    /**
     * 冒泡排序算法,默认从小到大排序
     * @param arr 需要排序的整数数组
     */
    public static void Bubble(Integer[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - i - 1; j++) {
                // 如果当前元素大于下一个元素,则交换它们
                if (arr[j] > arr[j + 1]) {
                    // 交换 arr[j] 和 arr[j + 1]
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

    /**
     * 带 Comparator 的冒泡排序算法,可以实现自定义排序规则
     * @param arr 需要排序的整数数组
     * @param c 自定义的 Comparator,用于决定排序规则
     */
    public static void Bubble(Integer[] arr, Comparator<Integer> c) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - i - 1; j++) {
                // 使用 Comparator 比较当前元素和下一个元素
                if (c.compare(arr[j], arr[j + 1]) > 0) {
                    // 交换 arr[j] 和 arr[j + 1]
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}
  1. 案例:自定义Book类,里面包含name和price。有一个Book[] books= 5本书对象。使用Arrays.sort()方法 实现Comparator接口匿名内部类,也称为定制排序()。要求使用可以按照name长度排序、按照price排序(均可从大到小或从小到大)。
package chapter11.arrays_;

import java.util.Arrays;
import java.util.Comparator;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class Book {
    private String name;
    private double price;

    public Book(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public double getPrice() {
        return price;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "name='" + name + '\t' + ", price=" + price;
    }
}
class Test{
    public static void main(String[] args) {
        Book[] books=new Book[4];
        books[0]=new Book("西游记",200);
        books[1]=new Book("红楼梦",400);
        books[2]=new Book("水浒传",150);
        books[3]=new Book("三国演义",300);
        //这里没学过泛型就把<Book>去了。
        Arrays.sort(books, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                Book book1=(Book) o1;
                Book book2=(Book) o2;
                double price=book1.getPrice()-book2.getPrice();
                if(price>0){
                    return -1;
                }else if(price<0){
                    return 1;
                }else {
                    return 0;
                }
            }
        });
        for(Book book:books){
            System.out.println(book.toString());
        }
        //其他方式同理,这里就不写了,提示如果是书名,就length即可
    }
}
/*
name='红楼梦	, price=400.0
name='三国演义	, price=300.0
name='西游记	, price=200.0
name='水浒传	, price=150.0
*/

11.9 BigInteger、BigDecimal

11.9.1 BigInteger和BigDecimal介绍

  1. 应用场景:
    (1). BigInteger适合保存比较大的整型
    (2). BigDecimal适合保存精度更高的浮点型(小数)

  2. BigInteger和BigDecimal常见的方法
    (1). add 加
    (2). subtract
    (3). multiple
    (4). divide

package chapter11.biginteger_;

import java.math.BigInteger;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class BigInteger_ {
    public static void main(String[] args) {
        BigInteger b1=new BigInteger("91234560000");
        BigInteger b2=new BigInteger("20000");
//        System.out.println(b1+b2);//错误,不允许使用+
        System.out.println(b1.add(b2));
        System.out.println(b1.subtract(b2));
        System.out.println(b1.multiply(b2));
        System.out.println(b1.divide(b2));
    }
}
/*
91234580000
91234540000
1824691200000000
4561728
 */
package chapter11.bigdecimal;

import java.math.BigDecimal;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class BigDecimal_ {
    public static void main(String[] args) {
        BigDecimal b1=new BigDecimal("1234567890.123");
        BigDecimal b2=new BigDecimal("10.123");
//        System.out.println(b1+b2);错误,不允许使用+
        System.out.println(b1.add(b2));
        System.out.println(b1.subtract(b2));
        System.out.println(b1.multiply(b2));
//        System.out.println(b1.divide(b2));//存在异常ArithmeticException,原因:就是除不进,无限小数。
        // 解决方法如下:保存的是分子的精度
        System.out.println(b1.divide(b2,BigDecimal.ROUND_CEILING));
    }
}
/*
1234567900.246
1234567880.000
12497530751.715129
121956721.340
 */

11.10 本章作业

  1. 编程题 Task01.java
    (1). 将字符串中指定部分进行反转。比如将 “abcedf” “aedcbf”
    (2). 编写方法public static String reverse(String str,int start,int end) 搞定
package chapter11.task;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class Task01 {
    public static void main(String[] args) {
        String str = "abcdef";
        String reverse_str = null;
        try {
            reverse_str = reverse(str, 1, 4);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        System.out.println(reverse_str);//aedcbf
    }

    public static String reverse(String str, int start, int end) {
        //对传入的参数做一个验证,一般:写出正确的情况,然后取反即可
        if (str == null || start < 0 || end >= str.length() || start > end) {
            throw new IllegalArgumentException("传入参数不正确");
        }
        char[] chars=str.toCharArray();
        for (int i=start,j=end; i < j; i++,j--) {
            char temp=chars[i];
            chars[i]=chars[j];
            chars[j]=temp;
        }
        return new String(chars);
    }
}
  1. 编程题 Task02.java
    输入用户名、密码、邮箱,如果信息录入正确,则提示注册成功,否则生成异常对象,要求:
    (1). 用户名长度为2-4
    (2). 密码的长度为6,要求全是数字 isDigital
    (3). 邮箱中包含@和.并且@在.的前面
package chapter11.task;

import java.util.Scanner;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class Task02 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入用户名(2-4个字符):");
        String username = scanner.next();
        System.out.print("请输入密码(6位数字):");
        String password = scanner.next();
        System.out.print("请输入邮箱:");
        String mailbox = scanner.next();
        try {
            // 调用userRegister方法进行用户注册验证
            userRegister(username, password, mailbox);
            System.out.println("恭喜你注册成功~");
        } catch (Exception e) {
            // 捕获并打印注册失败的异常信息
            System.out.println("注册失败:" + e.getMessage());
        } finally {
            // 关闭Scanner对象以释放资源
            scanner.close();
        }
    }

    /**
     * 验证用户输入的用户名、密码和邮箱是否符合要求
     *
     * @param username 用户名
     * @param password 密码
     * @param mailbox  邮箱
     * @throws IllegalArgumentException 如果输入的参数不合法,则抛出该异常
     */
    public static void userRegister(String username, String password, String mailbox) {
        // 检查输入参数是否为null
        if (username == null || password == null || mailbox == null) {
            throw new IllegalArgumentException("输入的参数不能为空");
        }

        // 验证用户名长度是否在2到4个字符之间
        int userLength = username.length();
        if (!(userLength >= 2 && userLength <= 4)) {
            throw new RuntimeException("用户名长度为2-4");
        }

        // 验证密码长度是否为6且全为数字
        if (!(password.length() == 6 && isDigital(password))) {
            throw new RuntimeException("密码长度为6,且全是数字");
        }

        // 验证邮箱中@和.的位置关系
        int front = mailbox.indexOf("@");
        int rear = mailbox.indexOf(".");
        if (!(front > 0 && rear > front)) {
            throw new RuntimeException("邮箱中包含@和.并且@在.的前面");
        }
    }

    /**
     * 判断密码是否全由数字组成
     *
     * @param password 密码
     * @return 如果密码全是数字,则返回true;否则返回false
     */
    public static boolean isDigital(String password) {
        char[] chars = password.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            // 检查每个字符是否在'0'到'9'范围内
            if (chars[i] < '0' || chars[i] > '9') {
                return false;
            }
        }
        return true;
    }
}
  1. 编程题
    (1). 编写java程序,输入形式为:Han Shun Ping的人名,以Ping,Han .S的形式打印出来。其中.S是中间单词的首字母。
    (2). 例如输入:Willian Jefferson Clinton,输出形式为:Clinton,Willian .J
package chapter11.task;

import java.net.SocketTimeoutException;
import java.util.Scanner;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class Task03 {
    public static void main(String[] args) {
        String n1 = "Han Shun Ping";
        String n2 = "Willian Jefferson Clinton";
        printName(n1);// Han,Ping .S

    }

    public static void printName(String str) {
        if (str == null) {
            System.out.println("不能为空");
            return;
        }
        String[] strings = str.split(" ");
        if (strings.length != 3) {
            System.out.println("字符格式不对");
            return;
        }
        String name = "%s,%s .%c";
        String info = String.format(name, strings[0], strings[2], strings[1].toUpperCase().charAt(0));
        System.out.println(info);
    }
}
  1. 编程题
    输入字符串,判断里面有多少个大写字母,多少个小写字母,多少个数字
package chapter11.task;

import java.util.Scanner;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class Task04 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.next();
        count(str);
    }

    public static void count(String str) {
        if (str == null) {
            System.out.println("字符串不能为空");
            return;
        }
        int upperCount = 0;
        int lowerCount = 0;
        int numberCount = 0;
        int otherCount = 0;
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(i) >= 'A' && str.charAt(i) <= 'Z') {
                upperCount++;
            } else if (str.charAt(i) >= 'a' && str.charAt(i) <= 'z') {
                lowerCount++;
            } else if (str.charAt(i) >= '0' && str.charAt(i) <= '9') {
                numberCount++;
            } else {
                otherCount++;
            }
        }
        System.out.println("大写字母=" + upperCount + "小写字母=" + lowerCount + "数字=" + numberCount + "其他=" + otherCount);
    }
}
/*
输入:123你好helloHI
大写字母=2小写字母=5数字=3其他=2
 */
  1. 试写出以下代码的运行结果
    已知Animal类有属性name,可以通过有参构造为属性赋值。
package chapter11.task;

/**
 * @aim java基础学习
 * @note java笔记
 */
public class Task05 {
    public static void main(String[] args) {
        String s1 = "hello";
        Animal a = new Animal(s1);
        Animal b = new Animal(s1);
        System.out.println(a == b);//false,对比的是不是同一对象
        System.out.println(a.equals(b));//false,对比的是不是同一对象
        System.out.println(a.name == b.name);//true,对比的是地址

        String s2 = new String("hello");
        String s3 = "hello";
        System.out.println(s1 == s2);//false
        System.out.println(s2 == s3);//false

        String t1 = "hello" + s1;//实际是一个String对象在堆中
        String t2 = "hellohello";
        System.out.println(t1.intern() == t2);//true
    }
}

class Animal {
    String name;

    public Animal(String name) {
        this.name = name;
    }
}
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值