zoukankan      html  css  js  c++  java
  • JDK1.8源码——java.lang.String 类


    String 类也是java.lang 包下的一个类,算是日常编码中最常用的一个类了,那么本篇博客就来详细的介绍 String 类。

    1、String 类的定义

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {}

      和上一篇博客所讲的 Integer 类一样,这也是一个用 final 声明的常量类,不能被任何类所继承,而且一旦一个String对象被创建, 包含在这个对象中的字符序列是不可改变的, 包括该类后续的所有方法都是不能修改该对象的,直至该对象被销毁,这是我们需要特别注意的(该类的一些方法看似改变了字符串,其实内部都是创建一个新的字符串,下面讲解方法时会介绍)。接着实现了 Serializable接口,这是一个序列化标志接口,还实现了 Comparable 接口,用于比较两个字符串的大小(按顺序比较单个字符的ASCII码),后面会有具体方法实现;最后实现了 CharSequence 接口,表示是一个有序字符的集合,相应的方法后面也会介绍。

    2、字段属性

    /** 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;

      一个 String 字符串实际上是一个 char 数组。

    3、构造方法

      String 类的构造方法很多。可以通过初始化一个字符串,或者字符数组,或者字节数组等等来创建一个 String 对象。

      

    String str1 = "abc";//注意这种字面量声明的区别,文末会详细介绍
    String str2 = new String("abc");
    String str3 = new String(new char[]{'a','b','c'})

    4、equals(Object anObject) 方法

    instanceof 运算符 用于:判断 该运算符前面引用类型变量指向的对象是否是后面类,或者其子类、接口实现类创建的对象。如果是则返回true,否则返回false,
    
    其使用格式如下:     引用类型变量 instanceof (类、抽象类或接口)
     1 /**
     2      * Compares this string to the specified object.  The result is {@code
     3      * true} if and only if the argument is not {@code null} and is a {@code
     4      * String} object that represents the same sequence of characters as this
     5      * object.
     6      *
     7      * @param  anObject
     8      *         The object to compare this {@code String} against
     9      *
    10      * @return  {@code true} if the given object represents a {@code String}
    11      *          equivalent to this string, {@code false} otherwise
    12      *
    13      * @see  #compareTo(String)
    14      * @see  #equalsIgnoreCase(String)
    15      */
    16     public boolean equals(Object anObject) {
    17         if (this == anObject) {
    18             return true;
    19         }
    20         if (anObject instanceof String) {
    21             String anotherString = (String)anObject;
    22             int n = value.length;
    23             if (n == anotherString.value.length) {
    24                 char v1[] = value;
    25                 char v2[] = anotherString.value;
    26                 int i = 0;
    27                 //比较每一个字符的值
    28                 while (n-- != 0) {
    29                     if (v1[i] != v2[i])
    30                         return false;
    31                     i++;
    32                 }
    33                 return true;
    34             }
    35         }
    36         return false;
    37     }

    String 类重写了 equals 方法,比较的是组成字符串的每一个字符是否相同,如果都相同则返回true,否则返回false。

    5、hashCode() 方法

     1     /**
     2      * Compares this string to the specified object.  The result is {@code
     3      * true} if and only if the argument is not {@code null} and is a {@code
     4      * String} object that represents the same sequence of characters as this
     5      * object.
     6      *
     7      * @param  anObject
     8      *         The object to compare this {@code String} against
     9      *
    10      * @return  {@code true} if the given object represents a {@code String}
    11      *          equivalent to this string, {@code false} otherwise
    12      *
    13      * @see  #compareTo(String)
    14      * @see  #equalsIgnoreCase(String)
    15      */
    16     public boolean equals(Object anObject) {
    17         if (this == anObject) {
    18             return true;
    19         }
    20         if (anObject instanceof String) {
    21             String anotherString = (String)anObject;
    22             int n = value.length;
    23             if (n == anotherString.value.length) {
    24                 char v1[] = value;
    25                 char v2[] = anotherString.value;
    26                 int i = 0;
    27                 while (n-- != 0) {
    28                     if (v1[i] != v2[i])
    29                         return false;
    30                     i++;
    31                 }
    32                 return true;
    33             }
    34         }
    35         return false;
    36     }

     String 类的 hashCode 算法很简单,主要就是中间的 for 循环,计算公式如下:

    s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

      s 数组即源码中的 val 数组,也就是构成字符串的字符数组。这里有个数字 31 ,为什么选择31作为乘积因子,而且没有用一个常量来声明?主要原因有两个:

      ①、31是一个不大不小的质数,是作为 hashCode 乘子的优选质数之一。

      ②、31可以被 JVM 优化,31 * i = (i << 5) - i。因为移位运算比乘法运行更快更省性能。

    具体解释可以参考这篇文章https://www.cnblogs.com/nullllun/p/8350178.html

    6.split(String regex) 和 split(String regex, int limit) 方法

     split(String regex) 将该字符串拆分为给定正则表达式的匹配。split(String regex , int limit) 也是一样,不过对于 limit 的取值有三种情况:

      ①、limit > 0 ,则pattern(模式)应用n - 1 次

    1 String str = "a,b,c";
    2 String[] c1 = str.split(",", 2);
    3 System.out.println(c1.length);//2
    4 System.out.println(Arrays.toString(c1));//{"a","b,c"}

      ②、limit = 0 ,则pattern(模式)应用无限次并且省略末尾的空字串

    1 String str2 = "a,b,c,,";
    2 String[] c2 = str2.split(",", 0);
    3 System.out.println(c2.length);//3
    4 System.out.println(Arrays.toString(c2));//{"a","b","c"}

      ③、limit < 0 ,则pattern(模式)应用无限次

    1 String str2 = "a,b,c,,";
    2 String[] c2 = str2.split(",", -1);
    3 System.out.println(c2.length);//5
    4 System.out.println(Arrays.toString(c2));//{"a","b","c","",""}

      下面我们看看底层的源码实现。对于 split(String regex) 没什么好说的,内部调用  split(regex, 0) 方法:

    1  public String[] split(String regex) {
    2         return split(regex, 0);
    3  }

      重点看 split(String regex, int limit) 的方法实现:

     1 public String[] split(String regex, int limit) {
     2     /* 1、单个字符,且不是".$|()[{^?*+\"其中一个
     3      * 2、两个字符,第一个是"",第二个大小写字母或者数字
     4      */
     5     char ch = 0;
     6     if (((regex.value.length == 1 &&
     7          ".$|()[{^?*+\".indexOf(ch = regex.charAt(0)) == -1) ||
     8          (regex.length() == 2 &&
     9           regex.charAt(0) == '\' &&
    10           (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
    11           ((ch-'a')|('z'-ch)) < 0 &&
    12           ((ch-'A')|('Z'-ch)) < 0)) &&
    13         (ch < Character.MIN_HIGH_SURROGATE ||
    14          ch > Character.MAX_LOW_SURROGATE))
    15     {
    16         int off = 0;
    17         int next = 0;
    18         boolean limited = limit > 0;//大于0,limited==true,反之limited==false
    19         ArrayList<String> list = new ArrayList<>();
    20         while ((next = indexOf(ch, off)) != -1) {
    21             //当参数limit<=0 或者 集合list的长度小于 limit-1
    22             if (!limited || list.size() < limit - 1) {
    23                 list.add(substring(off, next));
    24                 off = next + 1;
    25             } else {//判断最后一个list.size() == limit - 1
    26                 list.add(substring(off, value.length));
    27                 off = value.length;
    28                 break;
    29             }
    30         }
    31         //如果没有一个能匹配的,返回一个新的字符串,内容和原来的一样
    32         if (off == 0)
    33             return new String[]{this};
    34 
    35         // 当 limit<=0 时,limited==false,或者集合的长度 小于 limit是,截取添加剩下的字符串
    36         if (!limited || list.size() < limit)
    37             list.add(substring(off, value.length));
    38 
    39         // 当 limit == 0 时,如果末尾添加的元素为空(长度为0),则集合长度不断减1,直到末尾不为空
    40         int resultSize = list.size();
    41         if (limit == 0) {
    42             while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
    43                 resultSize--;
    44             }
    45         }
    46         String[] result = new String[resultSize];
    47         return list.subList(0, resultSize).toArray(result);
    48     }
    49     return Pattern.compile(regex).split(this, limit);
    50 }
  • 相关阅读:
    nyoj 题目19 擅长排列的小明
    nyoj 题目20 吝啬的国度
    nyoj 题目17 单调递增最长子序列
    nyoj 题目14 会场安排问题
    nyoj 题目12 喷水装置(二)
    nyoj 题目7 街区最短路径问题
    nyoj 8 一种排序
    nyoj 题目6 喷水装置
    nyoj 题目5 Binary String Matching
    nyoj 1282 部分和问题
  • 原文地址:https://www.cnblogs.com/aaaazzzz/p/12822985.html
Copyright © 2011-2022 走看看