String类

String

String常用方法

package stringTest;

import java.util.Arrays;

public class StringTest {
    public static void main(String[] args) {

        String str = "abcabcabc";
        //返回指定索引处字符
        char ch = str.charAt(0);//abcabcabc -----> a

        //从字符串中截取一部分子字符串,含头不含尾
        String str_sub = str.substring(2,5);//abcabcabc -----> cab

        //以指定的规则将此字符串分割成数组
        String[] str_array1 = str.split("a");//abcabcabc -----> [, bc, bc, bc]
        String[] str_array2 = str.split("c");//abcabcabc -----> [ab, ab, ab]

        //去除字符串前后空格
        String str1 = " abcabcabc    ";
        String str_trim = str1.trim();//" abcabcabc    "----->abcabcabc

        //返回字串在此字符首次出现的位置
        int index = str.indexOf("b");//abcabcabc -----> 1

        //返回字串在此字符最后出现的位置
        int index_last = str.lastIndexOf("b");//abcabcabc -----> 7

        //将字符串所有字符大写
        String str_up = str.toUpperCase();//abcabcabc -----> ABCABCABC

        //将字符串所有字符小写
        String str2 = "abcAbcABC";
        String str_low = str2.toLowerCase();//"abcAbcABC" ------> abcabcabc

        //返回字符串长度
        int length = str.length();//abcabcabc -----> 9

        //是否为空字符串
        Boolean bool1 = str.isEmpty();//abcabcabc -----> false

        String str3 = "     ";
        Boolean bool2 = str3.isEmpty();//"     " -----> false

        String str4 = "";
        Boolean bool3 = str4.isEmpty();//"" -----> true

        //将指定字符串替换所有匹配子串
        String str5 = str.replaceAll("abc","ccc");//abcabcabc -----> ccccccccc

    }

}

基本数据类型和包装类与String的相互转换

包装类--->String        String.valueOf(xxx);

String--->基本数据类型/包装类型        包装类的静态方法:parseXxx(str);

String--->char[]        str.tocharArray();

char[]--->String        String的构造方法:new String(char[]);

String--->byte[]        str.getbyte();

byte[]--->String        String的构造方法:new String(byte[]);

String的不可变性

String被final修饰,不可以被继承,代表不可变字符序列;String对象字符内容存储在底层一个字符数组final value[]中;实现了Serializable接口-->支持序列化;实现了Comparable(内部比较器)--->可以比较大小。

String字符串存储特性:

 创建字符串用new和不用的区别

String为什么要设置为不可变类

出于安全和性能考虑。

  1. 在多线程中,只有不变的对象和值是线程安全的,可以在多个线程中共享数据。
  2. 字符串不变时,常量池才有意义,可以节约更多堆内存空间。String作为我们最常用的引用数据类型,设为不可变,为其在方法区中开辟一块常量池,避免重复的创建String对象,可以缓解堆内存空间的压力,内存溢出常常就是因为堆内存空间溢出造成的。
  3. 在散列集合中,根据hashCode确定元素位置。String的不可变性,避免了重复计算hashCode,只需使用缓存的hashCode即可,可以提高在散列集合中使用String的性能。

String、StringBuffer、StringBuildedr

String:不可变字符序列;底层使用char[]存储。

StringBuffer:可变字符序列;线程安全(里面方法都用synchornized修饰),效率低,底层使用char[]存储,初始容量可以容纳16个字符。当字符容纳不下时,创建一个容量(扩容)为原来的2倍+2的字符数组,并将原数组中字符都复制过来。

   /**
     * Constructs a string buffer with no characters in it and an
     * initial capacity of 16 characters.
     */
    public StringBuffer() {
        super(16);
    }

StingBuffer中toStringCache变量:当bf对象第一次调用toString对象时,会将bf对象cope到toStringCache中(这个copy是从下标0到有效字符的下标的copy,不会造成空间浪费)。

    @Override
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }

然后返回一个String对象,在创建这个String对象时,是直接将toStringCache这个字符数组传给String,此过程不用再进行数组的复制。源码如下(这就是这个缓存的作用,当值没变需要转换为String时,不用去重复的进行数组的复制,这一点与StingBuffer不同)。

    String(char[] value, boolean share) {
        // assert share : "unshared not supported";
        this.value = value;
    }

当bf对象发生改变时会将toStringCache这个缓存置为null。下次toString()时确保toStringCache中的缓存都是最新值。

    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

PS:如果你用IDEA想DEBUGE这个过程,千万要把下面标红的地方关掉。不然你会发现toStringCache根本不会置为null)

StringBuildedr :可变字符序列;JDK1.5新增,线程不安全,底层使用char[]存储,初始容量可以容纳16个字符。当字符容纳不下时,创建一个容量(扩容)为原来的2倍+2的字符数组,并将原数组中字符都复制过来。

StringBulider中的toString():如下,由于StringBuilder的字符数组存储的字符并不一定能将这个数组存满。所以调用的String构造方法与StringBuffer(toStringCache已提前处理好)不一样,需要传入字符数组,下标0,有效字符下标count这三个参数。

    @Override
    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

这个构造方法每次都会进行数组的copy,根据传入的三个参数进行copy。即使StringBulider对象的值从头到尾都没变过,只要调用一次toString(),就会进行一次copy。(StringBuffer只会进行一次)

效率:StringBulider>StringBuffer>String。

字符串的拼接

  1.  +号拼接:
    • 拼接的字符串中有变量(new出来的String对象)时:底层使用StringBuilder.append,然后调用StringBuilder的toString()返回字符串。
    • 拼接的字符串中无变量时:即拼接的都是字符串常量,在编译时,编译器会直接将其优化为一个完整的字符串,和直接写一个完整字符串是一样的,此时效率很高。
  2. concat拼接:底层先创建一个字符数组,将两个字符串的值复制到字符数组中,然后使用这个字符数组创建一个新的String对象返回。
  3. StringUtils.join拼接:底层使用StringBuffe.append,然后调用StringBuffer的toString()返回字符串。
  4. StringBuffer
  5. StringBuilder

使用选择:

  1. 循环中进行拼接
    1. 要线程安全直接选用StringBuffer。
    2. 不要求线程安全直接使用StringBuilder。
    3. 千万不要用+,当拼接的对象都是字符常量时,会一直创建char[]对象。
  2. 非循环中进行拼接:如果是两个字符串拼接用concate;字符串和List<String>里的元素进行拼接用StringUtils.join;其余情况就用 + ,简单方便。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值