Java String object, you really understand it?

Achieve String object

StringObject is one of the most frequently used objects in Java, so Java companies are constantly on the Stringrealization of the object optimized to enhance Stringperformance object, look at the picture below, look along Stringthe optimization process of the object.

1. Java6 and earlier versions

StringThe object is a char array of objects that encapsulate implementation, there are four member variables: char array, offset, offset, character number count, the hash value of the hash.

StringThe object is to locate the char [] array by offset and count two attributes, get the string. Doing so efficiently and quickly share an array of objects, while saving memory space, but this approach is likely to cause a memory leak.

2. From the beginning to the Java8 version version Java7

Java7 version from the beginning, Java for Stringclass made some changes. StringClass is no longer offset and count two variables. The advantage is that Stringthe object occupies a little less of memory, while String.substring method is no longer shared char [], so as to solve the memory leak problem that may result from the use of this method.

3. Starting Java9 version

The char [] array instead of byte [] array, why you need to do it? We know that char is two bytes, if used to store a bit of a waste-byte character, in order to save space, Java company into a byte to store a byte string. In such a memory byte character is to avoid waste.

In Java9 maintains a new attribute Coder, which is encoded format identification, calculation of the length of the string or calls the indexOf () function, the required length of the string in accordance with how the field determination calculations. Default attributes coder has two values 0 and 1, 0 for Latin-1 (single-byte encoding), UTF-16 code represents. If the Stringdetermination string contains only Latin-1, the coder value of zero, otherwise it is one.

Way to create String objects

1, by way of string constants

String str= "pingtouge"Form, create a string when using this form, JVM will check whether the object exists in the string constant pool, if present, returns a reference to the address of the object, if does not exist, create it in a string constant pool string object and returns a reference. The benefits created using this approach are: to avoid the repetition of the same value string to create, save memory

2, String () function constructed

String str = new String("pingtouge")Form, the process of creating a string object using this method is more complicated, two stages, first at compile time, the string pingtougewill be added to the structure constant, when the class loader creates the string in constant pool. Then it is when you call new (), JVM will call Stringthe constructor, as well as references to the constant pool pingtougestring,
create a heap memory in Stringthe object and returns a reference to the address of the heap.

Understanding of the Stringobjects created in two ways, we have to analyze the code below, to deepen our understanding of these two methods, the following code sheet, stris equal to str1it?

  String str = "pingtouge";
  String str1 = new String("pingtouge");
  system.out.println(str==str1)

We analyze one by one these few lines of code, first of all from String str = "pingtouge"the beginning, where the use of string constants way to create a string object is created pingtougewhen a string object, JVM constant pool will go to look for the existence of the string, the answer here is affirmative it is not, so the JVM will be created in the constant pool of the string object and returns the address of an object references, so strpoints to a pingtougestring object reference in the address of the constant pool.

Then String str1 = new String("pingtouge")this line of code, used here is the way to create a string object constructor, on the face of our way to create understanding constructor string object, str1the resulting heap should be pingtougereferenced address of the string. Because strpoints to pingtougea string object reference in the address of the constant pool while str1pointing to a heap pingtougequoted address of the string, it stris certainly not equal str1.

Immutability of String objects

We know from the Stringstarting object that moment, I think we all know the Stringobjects are immutable. That it is immutable how to do it? JavaWhat are the benefits of doing so can bring? We work together to explore simple, take a look at Stringthe object section of source code:

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;
    }

As can be seen from this source, the Stringclass with the final qualifier, we know that when a class is final modification, it indicates that this class can not be inherited, so the Stringclass can not be inherited. This is Stringnot the first change point

Then look down, used to store the string char value[]array is privateand finalmodified, for we know is a finalbasic data type of a variable, its value can not be changed once after initialization. This is the Stringsecond point immutable.

Why Java company you want to Stringset immutable, mainly from the following three considerations:

  • 1, to ensure the safety of String objects. Assume String object is variable, then the String object can be maliciously modified.
  • 2, to ensure hash property values ​​do not change frequently, to ensure the uniqueness that is similar to HashMap container in order to achieve the appropriate key-value cache function.
  • 3, may be achieved string constant pool

Optimization of the String object

We used the string is Javaone of the types, so the operation of the string is unavoidable in the course of a string operation, if used improperly, the performance will be bad days to do. So during the operation of the string, there are areas we need to pay attention to it?

Elegant string concatenation

String concatenation string manipulation is one of the most frequently used operations, because we know that Stringimmutable objects, so when we do spliced using as little +string stitching or subconsciously believe that you can not use +string splicing, that the use of +string splicing generates many useless objects. The fact is it really? We do an experiment. We used +to splice the following piece of string.

String str8 = "ping" +"tou"+"ge";

Together to analyze how many objects This code will produce? If you analyze the case in accordance with our understanding of the meaning, first creates pingthe object, and then create pingtouan object, and finally will create pingtougean object, creating a total of three objects. Is it really? In fact not the case, Java programmers companies were afraid of us wrong hands, so the compiler optimized, above this string concatenation is optimized our compiler, optimized to a String str8 = "pingtouge";target. In addition to the constant string other than the splice optimized, for use +number string concatenation dynamic compiler also made the corresponding optimized to improve Stringthe performance of, for example, the following code:

String str = "pingtouge";

for(int i=0; i<1000; i++) {
      str = str + i;
}

The compiler will help us to optimize this


String str = "pingtouge";

for(int i=0; i<1000; i++) {
              str = (new StringBuilder(String.valueOf(str))).append(i).toString();
}

Java can be seen that this company had a lot of optimization, to prevent the programmer inadvertently lead to Stringperformance rapid decline, although the company in Java compiler to do this one corresponding optimization, but we still can see Java optimization company deficiencies, during dynamic string concatenation, and although StringBuilder for string concatenation, but each cycle will generate a new StringBuilder instance, will also degrade system performance.

So when we do the string concatenation, we need to optimize the code level, using StringBuilder in the dynamic string concatenation, if the case does not involve thread-safe, we show splicing, improve system performance, if it involves the thread-safe, we use StringBuffer to string concatenation

Clever use intern () method

     * <p>
     * When the intern method is invoked, if the pool already contains a
     * string equal to this {@code String} object as determined by
     * the {@link #equals(Object)} method, then the string from the pool is
     * returned. Otherwise, this {@code String} object is added to the
     * pool and a reference to this {@code String} object is returned.
     * <p>
     public native String intern();

This is the intern () function of the official explanatory notes, probably means intern function that returns a string constant pool, if the string constant pool already exists, it is returned directly to the object of constant pool references. Otherwise, the object is added to the constant pool, and then returns a reference.

One Twitterengineers QConshared their a global Software Development Conference on the Stringsubject optimized case, they use String.intern()methods will require 20G of memory storage optimization ago to require only a few megabytes of memory. This is enough to reflect String.intern()the power of us look at an example, simply look at String.intern()usage.

    public static void main(String[] args) {
        String str = new String("pingtouge");
        String str1 = new String("pingtouge");
        System.out.println("未使用intern()方法:"+(str==str1));
        System.out.println("未使用intern()方法,str:"+str);
        System.out.println("未使用intern()方法,str1:"+str1);

        String str2= new String("pingtouge").intern();
        String str3 = new String("pingtouge").intern();
        System.out.println("使用intern()方法:"+(str2==str3));
        System.out.println("使用intern()方法,str2:"+str2);
        System.out.println("使用intern()方法,str3:"+str3);

    }


As can be seen from the results, is not used String.intern()when the method, the same value is configured to return different string object object reference address, using String.intern()the method, the same value when the configuration string object, returns an object reference the same address. This can help us save a lot of space

String.intern()方法虽然好,但是我们要结合场景使用,不能乱用,因为常量池的实现是类似于一个HashTable的实现方式,HashTable 存储的数据越大,遍历的时间复杂度就会增加。如果数据过大,会增加整个字符串常量池的负担。

灵活的字符串的分割

字符串的分割是字符串操作的常用操作之一,对于字符串的分割,大部分人使用的都是 Split() 方法,Split() 方法大多数情况下使用的是正则表达式,这种分割方式本身没有什么问题,但是由于正则表达式的性能是非常不稳定的,使用不恰当会引起回溯问题,很可能导致 CPU 居高不下。在以下两种情况下 Split() 方法不会使用正则表达式:

  • 传入的参数长度为1,且不包含“.$|()[{^?*+\”regex元字符的情况下,不会使用正则表达式
  • 传入的参数长度为2,第一个字符是反斜杠,并且第二个字符不是ASCII数字或ASCII字母的情况下,不会使用正则表达式

所以我们在字符串分割时,应该慎重使用 Split() 方法,首先考虑使用 String.indexOf() 方法进行字符串分割,如果 String.indexOf() 无法满足分割要求,再使用 Split() 方法,使用 Split() 方法分割字符串时,需要注意回溯问题。

文章不足之处,望大家多多指点,共同学习,共同进步

参考资料

  • Java性能调优实战 刘超

最后

打个小广告,欢迎扫码关注微信公众号:「平头哥的技术博文」,一起进步吧。
平头哥的技术博文

Guess you like

Origin www.cnblogs.com/jamaler/p/11576754.html