zoukankan      html  css  js  c++  java
  • Java substring实现原理

    substring实现原理


    String是Java中一个比较基础的类,每一个开发人员都会经常接触到。而且,String也是面试中经常会考的知识点。String有很多方法,有些方法比较常用,有些方法不太常用。今天要介绍的subString就是一个比较常用的方法,而且围绕subString也有很多面试题。

    substring(int beginIndex, int endIndex)方法在不同版本的JDK中的实现是不同的。了解他们的区别可以帮助你更好的使用他。为简单起见,后文中用substring()代表substring(int beginIndex, int endIndex)方法。

    substring()的作用

    substring(int beginIndex, int endIndex)方法截取字符串并返回其[beginIndex,endIndex-1]范围内的内容。s

    String x = "abcdef";
    x = x.substring(1,3);
    System.out.println(x);
    

    输出内容:

    bc
    

    调用substring时发生了什么?

    你可能知道,因为x是不可变的,当使用x.substring(1,3)对x赋值的时候,它会指向一个全新的字符串:

    然而,这个图不是完全正确的表示堆中发生的事情。因为在jdk6 和 jdk7中调用substring时发生的事情并不一样。

    JDK 6中的subString

    tring是通过字符数组实现的。在jdk 6 中,String类包含三个成员变量:char value[]int offsetint count,他们分别用来:存储真正的字符数组、存储数组的第一个位置索引、存储字符串中包含的字符个数。

    当调用substring方法的时候,会创建一个新的string对象,但是这个string的值仍然指向堆中的同一个字符数组。这两个对象中只有count和offset 的值是不同的

    源码

    //JDK 6
    String(int offset, int count, char value[]) {
        this.value = value;
        this.offset = offset;
        this.count = count;
    }
    
    public String substring(int beginIndex, int endIndex) {
        //check boundary
        return  new String(offset + beginIndex, endIndex - beginIndex, value);
    }
    
    

    存在的问题

    如果有一个很长的字符串,但是你只需要使用很短的一段,于是你使用substring进行切割,但是由于你实际上引用了整个字符串,这个很长的字符串无法被回收。往小了说,造成了存储空间的浪费,往大了说,可能造成内存泄漏。这个问题已经被官方记录在Java Bug Database里面了:

    相应的解决办法:

    s1 = s1.substring(x,y) + "";
    

    JDK 7 中的substring

    上述问题在JDK 7中得到了解决。JDK 7中,substring方法会在堆中创建一个新的数组。

    源码

        //JDK 7
    
        /**
         * Allocates a new {@code String} that contains characters from a subarray
         * of the character array argument. The {@code offset} argument is the
         * index of the first character of the subarray and the {@code count}
         * argument specifies the length of the subarray. The contents of the
         * subarray are copied; subsequent modification of the character array does
         * not affect the newly created string.
         *
         * @param value  Array that is the source of characters
         * @param offset The initial offset
         * @param count  The length
         * @throws IndexOutOfBoundsException If the {@code offset} and {@code count} arguments index
         *                                   characters outside the bounds of the {@code value} array
         */
        public String(char value[], int offset, int count) {
            //check boundary
            this.value = Arrays.copyOfRange(value, offset, offset + count);
        }
    
        /**
         * Returns a string that is a substring of this string. The
         * substring begins at the specified {@code beginIndex} and
         * extends to the character at index {@code endIndex - 1}.
         * Thus the length of the substring is {@code endIndex-beginIndex}.
         * <p>
         * Examples:
         * <blockquote><pre>
         * "hamburger".substring(4, 8) returns "urge"
         * "smiles".substring(1, 5) returns "mile"
         * </pre></blockquote>
         *
         * @param beginIndex the beginning index, inclusive.
         * @param endIndex   the ending index, exclusive.
         * @return the specified substring.
         * @throws IndexOutOfBoundsException if the
         *                                   {@code beginIndex} is negative, or
         *                                   {@code endIndex} is larger than the length of
         *                                   this {@code String} object, or
         *                                   {@code beginIndex} is larger than
         *                                   {@code endIndex}.
         */
        public String substring(int beginIndex, int endIndex) {
            //check boundary
            int subLen = endIndex - beginIndex;
            return ((beginIndex == 0) && (endIndex == value.length)) ?
                    this :
                    new String(value, beginIndex, subLen);
        }
    

    参考文献地址:https://hollischuang.github.io/toBeTopJavaer/#/basics/java-basic/substrin

  • 相关阅读:
    18文件权限管理
    17用户身份管理
    16Shell脚本—计划任务服务程序
    15Shell脚本—流程控制
    14Shell脚本—判断语句
    13Shell脚本—编写简单脚本
    12Vim在系统配置中的应用示例
    11Vim文本编辑器
    10重要的环境变量
    09命令行通配符和转义字符
  • 原文地址:https://www.cnblogs.com/XiaoZhengYu/p/12789835.html
Copyright © 2011-2022 走看看