Day15 Java StringBuffer类、基本类型包装类

30 篇文章 0 订阅

StringBuffer类

概述:线程安全的可变字符序列

线程安全与不安全:

不安全就是指存在同步操作同一数据的行为,效率高

实际开发过程中,效率和安全问题很难平衡

StringBuffer的特点:

1、线程安全,没有同步操作,效率低

2、StringBuffer是一个可变序列

3、StringBuffer又称之为字符串缓冲区,把它当作一个字符串去操作,只不过它与String相比是可以修改内容的

4、在任何时间点,它包含着一些特定的字符序列,但是可以通过某些方法修改这些字符序列的长度和内容

StringBffer与String的区别:

1、StringBuffer的长度和内容都可以发生改变,String不可以

2、String每创建一个新的字符串都会开辟一个新的常量池区域;StringBuffer会提前给出容量,可以进行字符串的拼接,而不会重新开辟空间。

StringBuffer的构造方法:

public StingBuffer():构造一个没有字符的字符串缓冲区,初始容量为16个字符

public StringBuffer(int capacity):构造一个没有字符的字符串缓冲区和指定的初始容量

public StringBuffer(String str):构造一个初始化内容为指定字符串内容的字符串缓冲区

这里引出:

public int capacity():返回当前容量。

public int length():返回长度(字符数)。

 代码举例:

public class Test1 {
    public static void main(String[] args) {
        StringBuffer sb1=new StringBuffer();
        System.out.println("sb1:"+sb1);
        System.out.println("字符串sb1的容量为"+sb1.capacity());
        System.out.println("字符串sb2的长度为:"+sb1.length());
   
        StringBuffer sb2=new StringBuffer(40);
        System.out.println("sb2:"+sb2);
        System.out.println("字符串sb2的容量为:"+sb2.capacity());
        System.out.println("字符串sb2的长度为:"+sb2.length());
        
        StringBuffer sb3=new StringBuffer("hello");
        System.out.println("sb3:"+sb3);
        System.out.println("字符串sb3的容量为:"+sb3.capacity());
        System.out.println("字符串sb3的长度为:"+sb3.length());
    }
}

输出结果:

根据输出结果来看:

由于sb1,sb2以及sb3输出的都不是地址值,因此说明StringBuffer类中重写了toString方法

另外对于sb3的容量的解释:为初始化容量(16)+字符串内容容量(5)

StringBuffer中的各种功能:

StringBuffer的添加功能:

public StringBuffer append(String str):

通过观察API发现:不光可以追加字符串,还可以是任意数据类型的追加到StringBuffer中

返回的StringBuffer是字符串缓冲区本身

无论什么类型,追加到StringBuffer中全部变成了字符串

public StringBuffer insert(int index,String str):

将字符串str插入到此字符序列中,返回字符串缓冲区本身,按顺序插入到指定index的该序列中,向上移动原来位于该位置的任何字符,并将该序列的长度加到参数的长度。

代码举例:

public class Test2 {
    public static void main(String[] args) {
        StringBuffer s1=new StringBuffer();
        StringBuffer s2 = s1.append("hello");
        System.out.println(s1);//hello
        System.out.println(s2);//hello
        System.out.println(s1==s2);//true
//       s1与s2比较结果为true进一步说明返回的是StringBuffer本身
        s2.append(10);
        s2.append('a');
        s2.append(true);
        s2.append(13.24);
        System.out.println(s2);
//      无论什么类型都变成了字符串
//        这里结果为:hello10atrue13.24
//        链式编程追加
        s2.append(10).append('a').append(true).append(13.24);
        System.out.println(s2);
//        结果:hello10atrue13.2410atrue13.24
        System.out.println("================================");
//        插入操作:
        s2.insert(5,"HADOOP");
        System.out.println(s2);
//    结果:helloHADOOP10atrue13.2410atrue13.24
//        如果插入的是null,四个字符'null'也会被插入到该序列中,但是不可以直接插入:
//        s2.insert(5,null);
        Object o=null;
        s2.insert(5,o);
        System.out.println(s2);
//      结果:hellonullHADOOP10atrue13.2410atrue13.24
    }
}

StringBuffer的删除功能:

public StringBuffer deleteCharAt(int index):

删除指定索引处的字符,该序列缩短了一个char

注意:如果index为负数或者大于等于length(),运行时会报错。

index的值最大可以取到实际存储字符串的长度-1。

public StringBuffer delete(int start,int end):

删除此序列的子字符串中的字符,子字符串开始于指定start索引处并延伸到字符索引end-1,或者没有这样的子字符串序列存在,则结束。

注意:如果start等于end,则不做任何修改,且删除位置索引为:start<=index<end,索引end处的字符不会被删除,但是start处的字符会被删除。故start索引位置一定要是已经存在的索引,否则会报错。

代码举例:

public class Test3 {
    public static void main(String[] args) {
        StringBuffer sc1=new StringBuffer("bigdata");
        System.out.println("删除前的字符串为:"+sc1);//bigdata
        StringBuffer sc2 = sc1.deleteCharAt(2);
        System.out.println("删除后的字符串为:"+sc2);//bidata
        System.out.println(sc1==sc2);
//        true说明删除操作的是同一个StringBuffer对象
//      删除指定子字符串
        sc2.delete(1,4);
        System.out.println("删除指定子字符串后为:"+sc2);
//        删除全部字符串
        sc2.delete(0, sc1.length());
        System.out.println("删除全部字符串后为:"+sc2);
//        也可以写成:
//        sc2.delete(0,4)/sc2.delete(0,6)等
    }
}

输出结果:

StringBuffer中的替换功能:

public StringBuffer replace(int start,int end,String str):

用指定Str中的字符替换此序列的子字符串中的String,子字符串开始于指定索引start处并延伸到字符索引end-1处,或者没有这样的子字符串的存在,则结束

第一子字符串的字符被删除,然后指定str被插入在start位置

代码举例:

public class StringBufferDemo4 {
    public static void main(String[] args) {
        //创建一个StringBuffer对象
        StringBuffer sb = new StringBuffer();

        //往StringBuffer中添加一些内容
        sb.append("java").append("mysql").append("hadoop").append("hive");
        System.out.println(sb);

        //public StringBuffer replace(int start,int end,String str)
        sb.replace(5,10,"你真好");
        System.out.println(sb);
    }
}

输出结果:

StringBuffer的反转功能:

public StringBuffer reverse():

导致该字符序列被序列的相反代替,如果序列中包含任何替代对,则将它们视为单个字符进行反向操作

代码举例:

public class StringBufferDemo5 {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer();
        sb.append("我爱恩知李");
        System.out.println("反转之前:" + sb);

        System.out.println("反转之后:");
        StringBuffer sb2 = sb.reverse();
        System.out.println("sb:"+sb);
        System.out.println("sb2:"+sb2);
        // 操作的是同一个StringBuffer对象
    }
}

输出结果:

StringBuffer的截取功能:

public String substring(int start):

返回一个新的String,其中包含此字符序列当前包含的字符的子序列。

public String substring(int start,int end):

 返回一个新的String,其中包含此序列中当前包含的字符的子序列。子字符串开始于指定的start索引,并扩展到索引end-1处。

两种截取不会影响原来的StringBuffer的数据,且返回值为String类型

 代码举例:

public class StringBufferDemo6 {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer();
        sb.append("java").append("mysql").append("hive").append("ETL").append("spark");
        System.out.println(sb);

        String s1 = sb.substring(4);
        System.out.println("截取的内容是:"+s1);
        System.out.println("StringBuffer的内容为:"+sb);

        String s2 = sb.substring(9, 13);
        System.out.println("截取的内容是:"+s2);
        System.out.println("StringBuffer的内容为:"+sb);
    }
}

输出结果:

String与StringBuffer之间的转换

为什么要进行转换?

A转换成B,是为了使用B中的特有功能

B再转换成A,可能是引用最终的结果需要的是A类型的数据,所以还得转换回来

将String转换成StringBuffer:

1、通过StringBuffer的构造方法

2、通过StringBuffer的append方法将String类型数据追加到StringBuffer中。

将StringBuffer转换成String:

1、通过toString方法转换

2、通过截取功能substring方法,substring方法的返回值刚好是String类型

3、通过String的构造方法

代码举例:

/*
        String与StringBuffer之间的转换
 */
public class Test4 {
    public static void main(String[] args) {
        String s = "hello";
//        StringBuffer s1 = s;
//        这里不可直接使用StringBuffer接收String类型数据,会报错:
//        java: 不兼容的类型: java.lang.String无法转换为java.lang.StringBuffer
        System.out.println(s);
        System.out.println("String转换为StringBuffer:");
//        1、通过StringBuffer的构造方法
        StringBuffer s1 = new StringBuffer(s);
        System.out.println("通过StringBuffer的构造方法转换:" + s1);
//        2、通过append方法:
        StringBuffer s2 = new StringBuffer();
        s2.append(s);
        System.out.println("通过append方法转换:" + s2);
        System.out.println("StringBuffer转换为String:");
        StringBuffer sb = new StringBuffer("bigdata");
//        1、通过tostring方法
        System.out.println(sb);
        String sb1 = sb.toString();
        System.out.println("通过tostring方法转换:"+sb1);
//        2、通过subString方法
        String sb2=sb.substring(0);
        System.out.println("通过subString方法转换:"+sb2);
//        3、通过String的构造方法
//        String sb3 = new String();
        String sb3 = new String(sb);
        System.out.println("通过String的构造方法转换:"+sb3);
    }
}

输出结果:

 代码实现:

 在API中有一个与StringBuffer几乎相同的类:StringBuilder,包括其中的构造方法与成员方法基本完全一样。

StringBuffer、StringBuilder、String之间的区别:

1、StringBuffer是线程同步安全的,数据安全,效率低;StringBuilder不是线程安全的,数据不安全,效率高。

2、String的内容不可以改变,StringBuffer与StringBuilder是可变序列。

3、StringBuffer方法上有synchronized关键字

StringBuffer与数组的区别:

他们都可以看成一个容器,存放一些数据。但是StringBuffer中的数据都是一个一个字符。

数组可以存放不同类型的数据,但是同一个数组中只能存放同一种数据类型的数据

探究String作为参数传递和StringBuffer作为参数传递的区别:

代码:

public class Test5 {
    public static void main(String[] args) {
//        String作为参数传递时:
        String s1="hello";
        String s2="world";
        System.out.println("s1:"+s1+"\ts2:"+s2);
        change(s1,s2);
        System.out.println("s1:"+s1+"\ts2:"+s2);
        System.out.println("============================");
//        StringBuffer作为参数传递时;
        StringBuffer sb1 = new StringBuffer("hello");
        StringBuffer sb2 = new StringBuffer("world");
        System.out.println("sb1:"+sb1+"\tsb2:"+sb2);
        change(sb1,sb2);
        System.out.println("sb1:"+sb1+"\tsb2:"+sb2);
    }
    public static void change(String s1,String s2){
        s1=s2;
        s2=s1+s2;
        System.out.println("s1;"+s1+"\ts2:"+s2);
    }
    public static void change(StringBuffer sb1,StringBuffer sb2){
        sb1=sb2;
        sb2=sb1.append(sb2);
        System.out.println("sb1:"+sb1+"\tsb2:"+sb2);
    }
}

输出结果:

代码解读:

String中的初始化使变量s1与s2直接指向常量池的地址值访问常量

s1=s2:s2指向常量池的地址值赋给了s1,此时s1:world,s2:world

s2=s1+s2:将s1与s2做字符串拼接后在常量池中寻找是否有worldworld,没有开辟新空间存放worldworld。

方法调用完毕,从栈内存中消失,此时s1返回到指向hello,s2返回指向world。


StringBuffer使用构造方法初始化,在堆内存中开辟空间存放对象,使栈中的sb1指向堆中的地址0x01,堆中的地址0x01指向常量池中地址值为0x001的hello,sb2同理指向堆中的0x02,0x02指向地址值为0x002的world。

sb1=sb2:将堆中sb2的指向赋给sb1,

此时sb1----堆中0x02----常量池0x002"world",sb2----堆中0x02----常量池0x002"world"

sb2=sb1.append(sb2):sb1追加sb2赋值给sb2,同样在常量池中寻找,没有则开辟空间0x003,由于sb2指向的是堆中的地址,所以赋值操作更改了堆中的地址0x02为0x03,使其指向常量池中的0x003。

此时sb1----堆中0x03----常量池0x003"worldworld",sb2----堆中0x03----常量池0x003"worldworld"

方法调用结束,从栈中消失,sb1返回到指向0x01,sb2返回到指向0x02,此时堆中的0x02已经被更改为0x03所以sb2指向0x03

故最后一行输出为:sb1:hello,sb2:worldworld

 StringBuffer作为参数传递图解:

 总结:当多个StringBuffer作为参数进行传递时,谁发生了操作,谁就会受到影响。

例题:

使用StringBuffer实现把数组拼接成一个字符串

代码实现:

public class Test6 {
    public static void main(String[] args) {
        char[] chars={'h','e','l','l','o'};
//        创建一个空的StringBuffer对象
        StringBuffer s = new StringBuffer();
//        使用for循环遍历数组每个字符利用append将其追加到s中
        for(int i=0;i<chars.length;i++){
            s.append(chars[i]);
        }
//      将字符串缓冲区转换成字符串
        String s2 = s.toString();
        System.out.println(s2);
    }
}

 反转字符串:输入一个字符串,输出其反转字符串

代码实现:

import java.util.Scanner;

public class Test7 {
    public static void main(String[] args) {
        Scanner sc =new Scanner(System.in);
        System.out.println("请输入要反转的字符串:");
        String s = sc.next();
//        方式1:使用字符串拼接
        String s1="";
//        将字符串转换成字符数组
        char[] chars = s.toCharArray();
//        遍历数组反向获取字符
        for(int i=chars.length-1;i>=0;i--){
            s1+=chars[i];
        }
        System.out.println("反转后的字符串为:"+s1);
        System.out.println("=============================");
//      使用StringBuffer的反转功能
        StringBuffer s2 = new StringBuffer(s);
        s2.reverse();
//        将StringBuffer类型转换回String类型
        String s3 = s2.toString();
        System.out.println("反转后的字符串为"+s3);
        System.out.println("=========使用链式编程=============");
        System.out.println(new StringBuffer(s).reverse().toString());

    }
}

判断一个字符串是否为对称字符串:例:abc不是对称字符串,mnanm是对称字符串

代码实现:

import java.util.Scanner;

public class Test8 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String s = sc.next();
//        方式1:一个一个去比较:
        char[] chars = s.toCharArray();
        boolean flag = true;
        for (int start = 0, end = chars.length - 1; start <= end; start++, end--) {
            if (chars[start] != chars[end]) {
                System.out.println("该字符串不是对称字符串");
                flag=false;
                break;
            }
        }
        if(flag){
            System.out.println("该字符串是对称字符串");
        }
//        方式2:使用字符串反转比较:
        StringBuffer s2 = new StringBuffer(s);
        s2.reverse();
        String s3 = s2.toString();
        if(s3!=null){
            if(s3.equals(s)){
                System.out.println("该字符串是对称字符串");
            }             
        }
    }
}

Arrays类 

概述:Arrays类是针对于数组做操作的类,该类包含用于操作数组的各种方法(如排序和搜索)

Arrays类中的常用成员方法:

public static String toString(int[] a):将数组转换成一个字符串

public static void sort(int[] a):对数组进行排序操作

public static int binarySearch(int[] a,int key):对数组进行二分查找操作

 代码举例:

import java.util.Arrays;

public class Test9 {
    public static void main(String[] args) {
        int[] arr={12,43,32,76,342,76,3,2,1};
        String s = Arrays.toString(arr);
        System.out.println(s);
        System.out.println("---------------------------------------------------");
        Arrays.sort(arr);
        System.out.println("排序后的数组为:"+Arrays.toString(arr));
        System.out.println("---------------------------------------------------");
        int index = Arrays.binarySearch(arr, 43);
        int index2 = Arrays.binarySearch(arr, 100);
        System.out.println("进行二分查找43的结果:"+index);
        System.out.println("进行二分查找100的结果:"+index2);
    }
}

输出结果:

 由于进行二分查找的前提是有序,所以在进行binarySearch()方法前必须要先排序。

对于二分查找的结果需要观察binarySearch()方法的源码:

binarySearch()的源码:

private static int binarySearch0(int[] a, int fromIndex, int toIndex,
                                     int key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            int midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

观察源码,大致同二分查找相同,但若没有要寻找的字符,返回值是- (low + 1)。

日期类Date

顾名思义,该类是针对日期及时间进行操作的类

日期类的构造方法:

Date(): 分配一个 Date对象,并初始化它,以便它代表它被分配的时间,测量到最近的毫秒。

但是日期类输出的时间不是常见形式的时间,是系统时间的顺序:周 月 日 时 分 秒 上下午 年

想要让它的输出结果是我们平时所见到的顺序,需要另外一个类:

SimpleDateFormat(String pattern):

日期格式化,使用给定模式 SimpleDateFormat并使用默认的 FORMAT语言环境的默认日期格式符号。

API中的常用格式:

代码举例:

public class DateDemo {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);
//        使用SimpleDateFormet进行日期格式化
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd EEE a hh:mm:ss ");
        String s = simpleDateFormat.format(date);
        System.out.println(s);

    }
}

输出结果:

 结果中第一行为系统时间,第二行为格式化后的时间

常见格式化格式:

yyyy:年;  MM:月  ;  dd:日 ;  HH:24小时制度;   hh:12小时制度  ; mm:表示分钟 ;    ss:表示秒;

Math类:

概述:Math类包含执行基本数字运算的方法,如基本指数,对数,平方根和三角函数。

Math类中的成员方法:

public static int abs(int a):绝对值

public static double ceil(double a):向上取整

public static double floor(double a):向下取整

public static int max(int a,int b):取两个int类型的值中的最大值

public static int min(int a,int b):取两个int类型的值中的最小值

public static double pow(double a,double b):幂运算,a的b次幂

public static double random():获取一个随机数生成器

public static int round(float a):四舍五入

public static double sqrt(double a):正平方根运算

代码举例:

public class MathDemo {
    public static void main(String[] args) {
        // 绝对值
        int num1 = Math.abs(-10);
        System.out.println("绝对值:"+num1);
        //public static double ceil(double a)
        double num2 = Math.ceil(12.04);
        System.out.println("向上取整:"+num2);
        //floor
        double num3 = Math.floor(12.84);
        System.out.println("向下取整:"+num3);
//        max:取最大值
        int num4=Math.max(4,8);
        System.out.println("最大值:"+num4);
//        min:取最小值
        int num5=Math.min(4,8);
        System.out.println("最小值:"+num5);
//        pow:幂运算
        double num6=Math.pow(2,3);
        System.out.println("幂运算:"+num6);
//        四舍五入
        int num7= (int) Math.round(12.56);
        System.out.println("四舍五入:"+num7);
        //正平方根
        double num9 = Math.sqrt(3);
        System.out.println("平方根:"+num4);
    }
}

 输出结果:

 对于random方法:引入RanDom类

RanDom类:

对于生成的随机数进行输出,使用random.nextInt()方法:返回下一个随机数,int类型

代码举例:
 

public class RandomDemo {
    public static void main(String[] args) {
        //public Random()
        Random random = new Random();
//        int i = random.nextInt();
//        System.out.println(i);

        int i = random.nextInt(10)+1; // 0-9
        System.out.println(i);

        //public Random(long seed)
        Random random1 = new Random(10000000000L);
        int j=random1.nextInt();
        System.out.println(j);
    }
}

输出结果:在1到10的范围内和在一百亿的范围内分别生成一个随机数,不包括一百亿。

包装类:

需求1:有100这个数据,计算出它的二进制,八进制,十六进制

需求2:如何使用代码求出int类型数据范围

通过观察需求后发现,我们得出原本的基本数据类型无法调用任何方法和属性

为了对基本数据类型进行更多的操作,更方便的操作,Java就针对每一个基本数据类型都提供了一个对应的类类型。 我们称之为为包装类类型

包装类类型:byte----Byte;short----Short;int----Integer;long----Long;float----Float;double----Double;char----Character;boolean----Boolean

Integer类中有:

public static String toBinaryString(int i):

在基数2中返回整数参数的字符串表示形式为无符号整数,即求2进制数

public static String toHaxString(int i):

返回整数参数的字符串表示形式,作为16位中的无符号整数,即求16进制数

public static Sring toOctalString(int i):

在基数8中返回整数参数的字符串表示形式为无符号整数,即求8进制数

static int MAX_VALUE:持有最大值一个 int可以有2^31 -1。

static int MIN_VALUE:持有最小值一个 int可以有-2^31 -1

代码举例:

public class Test10 {
    public static void main(String[] args) {
        String s=Integer.toBinaryString(101);
        System.out.println("101的二进制数:"+s);
        String s2=Integer.toHexString(101);
        System.out.println("101的十六进制数:"+s2);
        String s3=Integer.toOctalString(101);
        System.out.println("101的八进制数:"+s3);
        int maxvalue=Integer.MAX_VALUE;
        int minvalue=Integer.MIN_VALUE;
        System.out.println("int类型的最大值为:"+maxvalue);
        System.out.println("int类型的最小值为:"+minvalue);
    }
}

输出结果:

 包装类一般是用于基本数据类型与字符串之间做转换

int类型的数据与String类型做互相转换

int -- String

static String valueOf(int i) :返回 int参数的字符串 int形式。

String -- Integer -- int

public static int parseInt(String s):将字符串参数解析为带符号的十进制整数。

代码举例:

public class PackageClassDemo2 {
    public static void main(String[] args) {
        //int -- String
        int num = 100;
        //方式1:static String valueOf(int i) 返回 int参数的字符串 int形式。
        String s = String.valueOf(num);  // 100 -->"100"
        System.out.println(s);
        System.out.println("==================================");
        //方式2:int -- Integer -- String
//        String string = new String(num);
        //Integer(int value) 构造一个新分配的 Integer对象,该对象表示指定的 int值。
        Integer integer = new Integer(num);
        System.out.println(integer); // Integer重写了toString方法
        String s1 = integer.toString();
        System.out.println(s1);
        //方式3:字符串拼接
        String s2 = ""+num;
        System.out.println(s2);
        //方式4:public static String toString(int i)
        String s3 = Integer.toString(100);
        System.out.println(s3);
        System.out.println("==========================");
        //String-->int
        String s4 = "200";
//        String s4 = "你好";
        //方式1:String--Integer--int
        //Integer(String s)
        //构造一个新分配 Integer对象,表示 int由指示值 String参数。
        Integer integer1 = new Integer(s4);
        System.out.println(integer1);
        //public int intValue()将 Integer的值作为 int 。
        int number = integer1.intValue();
        System.out.println(number);

        int i = integer1; //在包装类中称之为自动拆箱
        Integer i2 = 300; //在包装类中称之为自动装箱
    }
}

该输出结果相同,但是区别在于数据类型不同

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值