--------------------------------------------------------------------------------------------莫听穿林打叶声,一蓑烟雨任平生--------------------------------------------------------------------------------------------

Java笔记day19

一、String Buffer类概述及其构造方法
1、StringBuffer概述
    1)、如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象
        既耗时,又浪费空间,而String Buffer就可以解决这个问题
    2)、简单记忆:String Buffer是线程安全的可变字符序列
2、线程安全的
    不安全,就是存在同步操作同一数据的行为,效率高
    安全的时候,没有同步操作,效率不高

    在开发中,效率和安全一直都是很难平衡的事情。
    生活中有哪些线程安全的例子:
        线程安全的例子: 银行的一些业务,医院取号,电影院售票
        线程不安全的例子:视频会员,博客评论
3、字符串缓冲区就像一个String ,但可以修改
4、在任何时间点,它包含一些特定的字符序列,但可以通过某些方法调用来更改序列的长度和内容。
5、StringBuffer与String的区别:
    1)、StringBuffer的长度和内容都是可以发生改变的,String不可变
    2)、String每创建一个新的字符串都会开辟一个新的内存空间
        StringBuffer可以提前给出一个容量,可以进行字符串的拼接,而不会重新开辟

二、StringBuffer的构造方法:
    StringBuffer()
            构造一个没有字符的字符串缓冲区,初始容量为16个字符。
    StringBuffer(int capacity)
            构造一个没有字符的字符串缓冲区和指定的初始容量。
    StringBuffer(String str)
        构造一个初始化为指定字符串内容的字符串缓冲区。
    举例
    //public int capacity() 返回当前容量

查看代码
    public class StringBufferDemo1 {
    public static void main(String[] args) {
        //StringBuffer() 构造一个没有字符的字符串缓冲区,初始容量为16个字符。
        StringBuffer sb1 = new StringBuffer();
        System.out.println("sb1:" + sb1);       //StringBuffer重写的toString()方法
        int capacity = sb1.capacity();          //查看StringBuffer的容量
        System.out.println("StringBuffer的容量: " + capacity);
        int length = sb1.length();
        System.out.println("StringBuffer中字符串的长度: " + length);

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

        //StringBuffer(int capacity) 构造一个没有字符的字符串缓冲区和指定的初始容量。
        StringBuffer sb2 = new StringBuffer(50);
        System.out.println("sb2:" + sb2);       //StringBuffer重写的toString()方法
        int capacity2 = sb2.capacity();         //查看StringBuffer的容量
        System.out.println("StringBuffer2的容量: " + capacity2);
        int length2 = sb2.length();
        System.out.println("StringBuffer2中字符串的长度: " + length2);

        System.out.println("**************************************************");
        //StringBuffer(String str) 构造一个初始化为指定字符串内容的字符串缓冲区。
        StringBuffer sb3 = new StringBuffer("hello");
        System.out.println("sb3:" + sb3);
        int capacity3 = sb3.capacity();
        System.out.println("StringBuffer3的容量: " + capacity3); // 16+5=21
        int length3 = sb3.length(); 
        System.out.println("StringBuffer3中字符串的长度: " + length3);
    }
}


    注:在初始化String Buffer之后,容量是固定的,就算后面追加字符串或者进行其他操作
        改变的都是长度,而不是容量

三、StringBuffer中的方法:
1、添加功能
    public StringBuffer append(String str)
        观察API发现,不光可以追加字符串类型,可以将任意数据类型添加到
        字符串缓冲区中,返回的是什么呢?返回的是字符串缓冲区本身
        插入超过容量会自动扩容
    public StringBuffer insert(int offset,String str)
        将字符串插入到此字符序列中。返回的是字符串缓冲区本身
        String参数的String按顺序插入到指定偏移量的该序列中,
        向上移动原始位于该位置的任何字符,并将该序列的长度增加到参数的长
        如果str是null ,则四个字符"null"被插入到该序列中。

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

        //public StringBuffer append(String str)
        StringBuffer stringBuffer = sb.append("hello");
        System.out.println(stringBuffer);
        System.out.println(sb);
        System.out.println(stringBuffer==sb);       //true,stringBuffer和sb指向同一处常量池

        //sb.append(10);
        //sb.append('a');
        //sb.append(true);
        //sb.append(12.34);
        //System.out.println(sb);
        //System.out.println(stringBuffer);         //hello10atrue12.34

        //链式编程
        sb.append(10).append('a').append(true).append(12.34);
        System.out.println(sb);                     //hello10atrue12.34

        
        sb.insert(5,"hadoop");              //此处是在o和1之间插入一个hadoop
        System.out.println(sb);

        Object s = null;
        sb.insert(5,s);                     //此处不能写成sb.insert(5,null);会报错
        System.out.println(sb);
    }
}

2、删除功能
    删除:remove,move,delete,drop,truncate
    public StringBuffer deleteCharAt(int index)
        删除char在这个序列中的指定位置,该序列缩短了一个char 
    public StringBuffer delete(int start,int end)
        [start,end)
        删除此序列的子字符串中的字符
        子串开始于指定start并延伸到字符索引end - 1 ,
        或如果没有这样的字符存在的序列的结束。
        如果start等于end ,则不作任何更改。

查看代码
public class StringBufferDemo3 {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("bigdata");
        System.out.println("未删除字符之前:"+sb);
        sb.deleteCharAt(3);             //bigata
        System.out.println("删除字符之后:"+sb);
        //如果 index为负数或大于或等于 length() ,报错
        //sb.deleteCharAt(15);

        //public StringBuffer delete(int start,int end)
        //bigata
        //sb.delete(2,5);
        //sb.delete(2,6);
        //System.out.println(sb);

        //使用目前所学的技术删除所有的字符
        sb.delete(0,sb.length());
        System.out.println("删除所有的字符sb: "+sb);
    }
}


3、替换功能
    public StringBuffer replace(int start,int end,String str)
        用指定的String中的字符替换此序列的子字符串中的String
        子串开始于指定start并延伸到字符索引end - 1 ,
        或如果没有这样的字符存在的序列的结束
        第一子串中的字符被去除,然后指定String被插入在start

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

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

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

        //helloworldmysqlhadoophive
        //含头不含尾
        sb.replace(5,10,"数加学院真好");        //替换时,新的字符串不管多长都可以替换,会自动扩容
        System.out.println(sb);             
    }
}


4、反转功能
    public StringBuffer reverse()
        导致该字符序列被序列的相反代替
        如果序列中包含任何替代对,则将它们视为单个字符进行反向操作

查看代码
public class StringBufferDemo5 {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer();
        sb.append("我爱舒凡马");
        System.out.println("反转前:");
        System.out.println(sb);

        System.out.println("反转后:");
        StringBuffer reverse = sb.reverse();
        System.out.println(sb);
        System.out.println(reverse);        //sb和reverse的值是一样的
    }
}


5、截取功能
    String substring(int start)
        返回一个新的 String ,其中包含此字符序列中当前包含的字符的子序列。
    String substring(int start, int end)
        返回一个新的 String ,其中包含此序列中当前包含的字符的子序列。

查看代码
public class StringBufferDemo6 {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer();
        sb.append("java")
                .append("hadoop")
                .append("hive")
                .append("ETL")
                .append("spark")
                .append("flink");

        System.out.println(sb);

        //String substring(int start)
        String s1 = sb.substring(4);
        System.out.println("截取出来的字符串是:" + s1);        //hadoophiveETLsparkflink,从索引为4的地方开始截取
        System.out.println("StringBuffer的内容为:" + sb);      //不变,另外s1是string类型,sb是string buffer类型

        //String substring(int start, int end)  含头不含尾的 [start,end)
        //javahadoophiveETLsparkflink
        String s2 = sb.substring(10, 17);       //hiveETL
        System.out.println("截取出来的字符串是:" + s2);
        System.out.println("StringBuffer的内容为:" + sb);


    }
}

四、String Buffer练习
1、String和StringBuffer的相互转换
    A--B,将A转换成B,是为了使用B中特有功能
    B--A,再将B转换成A,可能是引用最终的结果需要A类型,所以还得转换回来
 

查看代码
public class StringBufferDemo7 {
    public static void main(String[] args) {
        //String ---> StringBuffer

        String s = "hello";
        //不兼容的类型: java.lang.String无法转换为java.lang.StringBuffer
        //StringBuffer sb1 = s;
        //StringBuffer sb1 = "hello";这两种方法都是错误的

        //方式1:通过构造方法转换
        StringBuffer sb1 = new StringBuffer(s);
        System.out.println(s);
        System.out.println(sb1);

        //方式2:通过append方法
        StringBuffer sb2 = new StringBuffer();
        sb2.append(s);
        System.out.println(s);
        System.out.println(sb2);

        //StringBuffer ---> String
        StringBuffer sb3 = new StringBuffer("bigdata");

        //方式1:使用StringBuffer中的toString()方法
        //public String toString()
        String s1 = sb3.toString();
        System.out.println(s1);
        System.out.println(sb3);
        
        //方式2:substring()
        String s2 = sb3.substring(0);
        System.out.println(s2);
        System.out.println(sb3);

        //方式3:String的构造方法,
        //String(StringBuffer buffer)
        //分配一个新的字符串,其中包含当前包含在字符串缓冲区参数中的字符序列。
        String s3 = new String(sb3);
        System.out.println(s3);
        System.out.println(sb3);
    }
}


2、把数组拼接成一个字符串(用StringBuffer实现)
 

查看代码
public class StringBufferDemo8 {
    public static void main(String[] args) {
        char[] chars = {'a','b','c','d'};
        //创建一个空的StringBuffer对象
        StringBuffer sb = new StringBuffer();

        //遍历数组获取到每一个字符
        for(int i=0;i<chars.length;i++){
            sb.append(chars[i]);
        }

        //将StringBuffer转换成字符串
        String s = sb.toString();
        System.out.println(s);
    }
}


3、把字符串反转,键盘录入字符串

查看代码
import java.util.Scanner;
public class StringBufferDemo9 {
    public static void main(String[] args) {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入字符串:");
        String stringLine = sc.next();

        //方式1:使用String的方式
        String s = "";
        //将输入的字符串转成字符数组
        char[] chars = stringLine.toCharArray();
        //倒着遍历字符数组
        for (int i = chars.length - 1; i >= 0; i--) {
            s += chars[i];
        }
        System.out.println(stringLine + "反转之后的字符串为:" + s);

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

        //方式2:利用StringBuffer中的reverse()方法实现反转
        //将输入的字符串转换成StringBuffer类型
        StringBuffer sb = new StringBuffer(stringLine);
        //调用StringBuffer中的reverse()方法
        sb.reverse();
        String s2 = sb.toString();
        System.out.println(stringLine + "反转之后的字符串为:" + s2);
        System.out.println("链式编程:");
        System.out.println(stringLine + "反转之后的字符串为:" + new StringBuffer(stringLine).reverse().toString());
    }
}


4、判断一个键盘录入的字符串是否是对称字符串
    例如"abc"不是对称字符串,"aba"、"abba"、"aaa"、"mnanm"是对称字符串
    分析:
        1、第1个字符与最后一个字符进行比较
        2、第2个字符与倒数第2个字符进行比较
        3、...

        比较的次数:字符串的长度(length())/2

查看代码
import java.util.Scanner;
public class StringBufferDemo10 {
    public static void main(String[] args) {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入您想要判断的字符串:");
        String stringLine = sc.next();

        //方式1:一个一个的去比较
        //将字符串转换成字符数组
        char[] chars = stringLine.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("该字符串是对称字符串!");
        }

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

        //方式2:利用StringBuffer中reverse()方法,将反转后与反转前进行比较
        //将输入的字符串转换成StringBuffer类型
        StringBuffer sb = new StringBuffer(stringLine);
        StringBuffer reverse = sb.reverse();
        //再将反转后的StringBuffer类型转换回String类型
        String s = reverse.toString();
        if(s.equals(stringLine)){                           //用等于号也是可以的,因为如果是对称字符,Strig Buffer转为
            System.out.println("该字符串是对称字符串!");     //String之后会指向常量池中的同一个位置,即地址值相同
        }else {
            System.out.println("该字符串不是对称字符串!");
        }
    }
}

五、注意事项
1、String,StringBuffer,StringBuilder之间的区别
    1)、StringBuffer是线程同步安全的,数据安全,效率低
        StringBuilder不是线程同步安全的,数据不安全,效率高
    2)、String的内容是不可变的,StringBuffer和StringBuilder是可变的
    3)、StringBuffer中的方法是由synchronized关键字修饰的。
2、StringBuffer和数组的区别?
    它们都可以被看作是一个容器,装一些数据。
    但是呢,StringBuffer里面的数据都是一个一个的字符
    数组可以存放不同数据类型的数据,但是同一个数组只能存放同一种数据类型的数据
3、探究String与StringBuffer分别作为方法的参数传递的区别

查看代码
public class StringBufferDemo11 {
    public static void main(String[] args) {
        //StringBuffer sb = new StringBuffer();
        //sb.append("hello");
        //System.out.println(sb);

        //StringBuilder sb2 = new StringBuilder();
        //sb2.append("world");
        //System.out.println(sb2);

        String s1 = "hello";
        String s2 = "world";
        System.out.println("s1: " + s1+" ,s2:" + s2); //s1:hello ,s2:world
        change(s1,s2);
        System.out.println("s1: " + s1+" ,s2:" + s2); //s1:hello ,s2:world
        //此处传入的只是容量池中的地址值,而他们本身并没有改变

        System.out.println("*******************************************");
        StringBuffer sb1 = new StringBuffer("hello");
        StringBuffer sb2 = new StringBuffer("world");
        System.out.println("sb1: " + sb1+" ,sb2:" + sb2);
        change(sb1,sb2);
        System.out.println("sb1: " + sb1+" ,sb2:" + sb2);       //sb1: hello ,sb2:worldworld            
    }

    private static void change(StringBuffer sb1,StringBuffer sb2){
        sb1 = sb2;
        sb2.append(sb1);
        System.out.println("sb1: " + sb1+" ,sb2:" + sb2);
        //sb1: worldworld ,sb2:worldworld
    }

    private static void change(String s1, String s2) {
        s1 = s2;                                              //s1:"world"
        s2 = s1 + s2;                                        //s2:"worldworld"
        System.out.println("s1: " + s1+" ,s2:" + s2);         //s1:world ,s2:worldworld
    }
}

画图解释String和String Buffer传参过程

String过程

String Buffer过程

六、array的相关操作
1、例题
    把字符串中的字符进行排序。
            举例:"dacgebf"
            结果:"abcdefg"
    符合常识字典字母顺序,在java中又称之为自然排序
    分析:
        1)、将被排序的字符串转成字符数组
        2)、将字符数组进行排序
        3)、将数组转成字符串
        4)、输出
 

查看代码
public class StringBufferDemo12 {
    public static void main(String[] args) {
        //定义一个字符串
        String s = "dacgebf";
        System.out.println("排序之前的字符串为:" + s);

        //将被排序的字符串转成字符数组
        char[] chars = s.toCharArray();

        //将字符数组进行排序
        //举例冒泡排序
        bubblingSort(chars);

        //将数组转换从字符串
        String s1 = String.valueOf(chars);
        System.out.println("排序后的字符串为:" + s1);
    }

    private static void bubblingSort(char[] chars) {
        for (int x = 0; x < chars.length - 1; x++) {
            for (int y = 0; y < chars.length - 1 - x; y++) {
                if (chars[y] > chars[y + 1]) {
                    char temp = chars[y];
                    chars[y] = chars[y + 1];
                    chars[y + 1] = temp;
                }
            }
        }

    }
}


2、Arrays类概述及其常用方法
    该类包含用于操作数组的各种方法(如排序和搜索)
    public static String toString(int[] a)
        转为字符串
    public static void sort(int[] a)
        排序
    public static int binarySearch(int[] a,int key)
        二分查找
        当查找的数不在数组中时,输出的是-(arrays.lenght)

查看代码
public class ArraysDemo1 {
    public static void main(String[] args) {
        //定义一个数组
        int[] arr = {21, 32, 41, 431, 2, 41, 15};

        //public static String toString(int[] a)
        //System.out.println(arr);
        String s = Arrays.toString(arr);
        System.out.println("数组:" + s);

        System.out.println("*****************************");
        //public static void sort(int[] a)
        Arrays.sort(arr);
        System.out.println("排序后的数组为:" + Arrays.toString(arr));

        System.out.println("******************************");
        //public static int binarySearch(int[] a,int key)二分查找
        //[2, 15, 21, 32, 41, 41, 431]
        //二分查找的前提:序列是有序的
        int i = Arrays.binarySearch(arr, 32);
        System.out.println("二分查找32:" + i);
        System.out.println("二分查找100:"+Arrays.binarySearch(arr,100));//-7
    }
}

 

posted @ 2021-12-16 22:04  等你回眸一笑  阅读(37)  评论(0)    收藏  举报