JAVA中StringBuilder 和 StringBuffer 使用

764 阅读2分钟

这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战

文章目录

简介

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

StringBuilder

在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。StringBuffer 的说明如下:

1、可改变的字符序列
2、封装char[]数组
3、常用来代替字符串,做高效率字符串链接运算

举例1:大量字符串拼接

在程序开发过程中,我们常常碰到字符串连接的情况,方便和直接的方式是通过+符号来实现,但是这种方式达到目的的效率比较低,且每执行一次都会创建一个 String 对象,即耗时,又浪费空间。使用 StringBuilder 类就可以避免这种问题的发生

String s0 = "abcdefghigklmnopqrstuvwxyz";
StringBuilder sb = new StringBuilder();
long t = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
	sb.append(s0);
}
System.out.println(System.currentTimeMillis() - t);

运行结果:
可以看到对字母 a-z 拼接了 100000 次 ,只用了 22 毫秒
在这里插入图片描述
创建对象

StringBuilder sb = new StringBuilder();
或者
StringBuilder sb = new StringBuilder("abc");

常用方法

append()
作用:在字符序列末尾,追加字符,高效的字符串连接

delete(int start,int end)
作用:删除字符串中 start 开始到 end 结束的字符,即 [start,end) 左闭右开

deleteCharAt(int index)
作用:删除单个字符

insert(int index,子串)
作用:在index位置,插入一个子串

replace(int start,int end,String str)
作用:将 [start,end) 替换为指定字符串str

reverse()
作用:翻转

setCharAt(int index,char ch)
作用:将 index 位置替换为字符 ch

toString()
作用:转为String类型

举例2:StringBuilder 方法练习

		StringBuilder sb = new StringBuilder("abc");
        sb.append("def")//abcdef
                .append("ghi")//abcdefghi
                .insert(2, "jkl")//abjklcdefghi
                .replace(4, 6, "mnop")//abjkmnopdefghi
                .reverse()//ihgfedponmkjba
                .delete(2, 5)//ihdponmkjba
                .deleteCharAt(0)//hdponmkjba
                .setCharAt(2, '*');//hd*onmkjba
        System.out.println(sb);

运行输出结果:

hd*onmkjba

举例3:勾选兴趣爱好

需要实现以下效果:
在这里插入图片描述

xml

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stretchColumns="0,1,2">

    <TableRow>

        <CheckBox
            android:onClick="doClick"
            android:text="足球" />

        <CheckBox
            android:onClick="doClick"
            android:text="篮球" />

        <CheckBox
            android:onClick="doClick"
            android:text="气球" />
    </TableRow>

    <TableRow>

        <CheckBox
            android:onClick="doClick"
            android:text="流行乐" />

        <CheckBox
            android:onClick="doClick"
            android:text="古典乐" />

        <CheckBox
            android:onClick="doClick"
            android:text="小月月" />
    </TableRow>

    <TableRow>

        <CheckBox
            android:onClick="doClick"
            android:text="京剧" />

        <CheckBox
            android:onClick="doClick"
            android:text="戏剧" />

        <CheckBox
            android:onClick="doClick"
            android:text="杯具" />
    </TableRow>

    <TableRow>

        <CheckBox
            android:onClick="doClick"
            android:text="抽烟" />

        <CheckBox
            android:onClick="doClick"
            android:text="喝酒" />

        <CheckBox
            android:onClick="doClick"
            android:text="烫头" />
    </TableRow>

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="#222"
        android:textSize="18sp"
        android:gravity="center"
        android:layout_marginTop="20dp"/>
</TableLayout>

Activity 中

public class MainActivity extends AppCompatActivity {
    private TextView textView;
    private StringBuilder sb = new StringBuilder();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView);
    }

    /*
     * View 所有界面控件的父类型
     *   |-EditText
     *   |-TextView
     *   |-......
     * */
    public void doClick(View view) {
        CheckBox checkBox = (CheckBox) view;
        String s = checkBox.getText().toString();
        if (checkBox.isChecked()) {//勾选
            if (sb.length() != 0) {
                //已有内容先连接一个,
                sb.append(",");
            }
            sb.append(s);
        } else {//取消
            //中间的情况:ccc
            //aaa,bbb,ccc,ddd,eee
            //start:8   end:12

            //末尾的情况:ccc
            //aaa,bbb,ccc
            //start:8   end:12
            //end > 11

            //开头的情况:ccc
            //ccc,aaa,bbb
            //start:0   end:4

            //唯一:ccc
            //ccc
            //start:0   end:4
            int start = sb.indexOf(s);//8
            int end = start + s.length() + 1;//(需要删除逗号,因为删除是左闭右开的范围,所以还要加1)
            //end > sb.length 的情况是处于末尾的情况
            //所以只需要删除最后的ccc即可,它后边没有逗号,所以 end--
            //除了删除ccc还要删除前边的逗号,所以 start--
            //
            if (end > sb.length()) {
                if (start != 0) {
                    start--;
                }
                end--;
            }
            sb.delete(start, end);
        }
        textView.setText(sb);
    }
}

StringBuffer

StringBuffer 和 StringBuilder 非常相似,只是有以下区别:

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。

总结如下:
StringBuilder 线程不安全(效率高)
StringBuffer 线程安全(牺牲程序性能)