美文网首页
String你了解多少

String你了解多少

作者: 二旬一月 | 来源:发表于2020-05-30 17:06 被阅读0次

    常用方法
    这些用法应该烂熟于心

            String string = "Hello World!";
            String string2 = new String("abc");
    
            //1.获取字符串长度
            string.length();
            //2.截取一个字符
            string.charAt(0);
            //3.替代getChars()的一种方法是将字符存储在字节数组中,该方法即getBytes()
            byte[] bytes = string.getBytes();
            //4.转换成字符数组
            char[] chars = string.toCharArray();
            //5.判断字符串开始和结束
            boolean h = string.startsWith("H");
            boolean b = string.endsWith("World!");
            //6.indexOf() 查找字符或者子串第一次出现的地方。
            int e = string.indexOf('e');
            //7.lastIndexOf() 查找字符或者子串是后一次出现的地方
            int o = string.lastIndexOf('o');
            //8.截取字符串
            String substring = string.substring(1);//指定位置到结束
            String substring1 = string.substring(1, 3);//指定位置到指定位置,结果"el"
            //9.替换(这个替换是全部的)。
            String replace = string.replace('o', 'z');
            //10.连接两个字符串
            String concat = string.concat(string2);
            //11.去掉起始和结尾的空格
            String trim = string.trim();
            //12.将基础数据类型转换为字符串类型
            String s = String.valueOf(333);
            //13.大小写转换
            string.toLowerCase();
            string.toUpperCase();
    

    从源码去理解

    定义

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
              /** The value is used for character storage. */
              private final char value[];
              /** Cache the hash code for the string */
              private int hash; // Default to 0
              /** use serialVersionUID from JDK 1.0.2 for interoperability */
              private static final long serialVersionUID = -6849794470754667710L;
    

    从上面的定义我们可以看出

    • Final 标识不允许集成重载. jdk中还多重要类都是final 标识, 防止应用程序继承重载以影响jdk的安全
    • 继承Serializable 接口, 可以放心的序列化
    • Comparable 接口, 可以根据自然序排序.
    • CharSequence 字符串的重要接口
    • char数组 value . Final 修饰.
    • hash字段 int, 表示当前的hashCode值, 避免每次重复计算hash值

    字符串构造方法3+1

    • String string = "abcd";
    • public String()创建的是一个空字符
    • public String(char[])穿进去一个字符数组
    • public String(byte[])传递进去一个字节数组
      注意 直接使用双引号的形式,创建色字符串是保存在字符串常量池当中的
      new 关键字创建的方法,则是创建一条引用,然后指向了一个字符数组。
      空白构造方法其实是生成 "" 字符串传入其他字符串的构造方式其实只是把其他字符串的value 和hash 值的引用复制一份, 不用担心两个字符串的value和hash 互相干扰. 因为String类中没有修改这两个值的方法, 并且这两个值是private final修饰的, 已经无法修改了。
      空白构造方法中没有设置hash的值, 则使用 hash的默认值 // Default to 0

    hashCode方法

    public int hashCode() {
            int h = hash;
            if (h == 0 && value.length > 0) {
                char val[] = value;
    
                for (int i = 0; i < value.length; i++) {
                    h = 31 * h + val[i];
                }
                hash = h;
            }
            return h;
        }
    
    • 重写了hashcode 方法,可以看出hashcode 和每个字符都有关

    字符串的拼接concat方法和join静态方法

    • concat方法
    public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }
    

    直接在内存中复制一份新的数组, 在new 一个String对象. 线程安全. 性能较低.
    也可以直接是用 + 拼接.

    • join静态方法
      内部发现还是使用StringBuilder来实现, join 完全就是一个为了使用方便的一个工具方法。

    trim 方法

    从前后遍历空白字符, 判断空白字符是使用的 char <=' ' 来判断的, 后面在使用substring来截取非空白字符

    substring方法

    内部使用public String(char value[], int offset, int count) 构造方法来生成新的字符串, 在这个构造方法内部会有数组的赋值

    valueOf方法
    public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();
    }
    // 内部使用传入对象的自己的toString方法, 传入对象如果没有重载toString方法, 就使用默认的toString方法. 
    public static String valueOf(char data[]) {
        return new String(data);
    }
    // 根据传入的数组来选择合适的构造方法来生成String对象
    public static String valueOf(boolean b) {
        return b ? "true" : "false";
    }
    // 根据传入布尔值
    

    static copyValueOf方法

    public static String copyValueOf(char data[], int offset, int count) {
            return new String(data, offset, count);
        }
    // 静态工具方法, 默认使用合适构造方法来截取和生成新新的字符串
    

    了解了这些应该再去看看密切相关的两个东西StringBuffer、StringBuilder

    1. 如果要操作少量的数据用 String
    2. 单线程操作字符串缓冲区 下操作大量数据 StringBuilder
    3. 多线程操作字符串缓冲区 下操作大量数据 StringBuffer

    注意
    每次执行“+”操作时jvm都要new一个StringBuffer对象来处理字符串的连接,这在涉及很多的字符串连接操作时开销会很大。
    这一小节原文链接:https://blog.csdn.net/longfulong/article/details/78700239
    1.StringBuffer()的初始容量可以容纳16个字符,当该对象的实体存放的字符的长度大于16时,实体容量就自动增加。StringBuffer对象可以通过length()方法获取实体中存放的字符序列长度,通过capacity()方法来获取当前实体的实际容量。

    2.StringBuffer(int size)可以指定分配给该对象的实体的初始容量参数为参数size指定的字符个数。当该对象的实体存放的字符序列的长度大于size个字符时,实体的容量就自动的增加。以便存放所增加的字符。

    3.StringBuffer(String s)可以指定给对象的实体的初始容量为参数字符串s的长度额外再加16个字符。当该对象的实体存放的字符序列长度大于size个字符时,实体的容量自动的增加,以便存放所增加的字符。

    扩容算法:
    使用append()方法在字符串后面追加东西的时候,如果长度超过了该字符串存储空间大小了就需要进行扩容:构建新的存储空间更大的字符串,将久的复制过去;

    再进行字符串append添加的时候,会先计算添加后字符串大小,传入一个方法:ensureCapacityInternal 这个方法进行是否扩容的判断,需要扩容就调用expandCapacity方法进行扩容
    尝试将新容量扩为大小变成2倍+2 if 判断一下 容量如果不够,直接扩充到需要的容量大小。

    相关文章

      网友评论

          本文标题:String你了解多少

          本文链接:https://www.haomeiwen.com/subject/fxthzhtx.html