Blog: bugstack.cn

Precipitation, share, grow, let yourself and others can gain something! 😄

One, foreword

What we are talking about is the article of eight shares, and what we are doing is moving bricks!

I don’t even need it for my problem development. Why do you ask? This is probably what most programmers experience when looking for a job, and it’s even something they hate and fret about. Clearly give is screw money, clearly do is to write CRUD, clearly bear is a tool!

Clearly… There are many, but Mingming company will not hire 5 years of development and 3 years of experience, mingming company also prefers to add value of research and development. Some small companies are difficult to say, but in some large Internet factories, we hope to recruit people with training value, but also prefer to quickly beat strange upgrade, but also more willing to let such people assume greater responsibility.

But, you are sour! Others see source code you play games, others learn algorithms you brush some sound, others write blog you wave 98. So, if you don’t spend your time on personal growth, you’re constantly being milked.

2. Interview questions

Thank you, I always feel that I have a technical bottleneck and a blind spot, but I don’t know where it is. So make an appointment to chat with the interviewer, although you can’t face the past!

Interviewer: Plane, are you holding your big face again and coming to fuck me for nothing?

Thank plane: hey hey, I need knowledge, I thirst.

Interviewer: Ok, so today let’s talk about the most common type of String. How do you initialize a String?

String STR = “ABC “;

Interviewer: Anything else?

Thank plane: and? String STR = new String(” ABC “); 😄

Interviewer: Anything else?

Thank plane: ah! ? There are! I don’t know!

Interviewer: You don’t understand String. You haven’t read the source code. You could do that; new String(new char[]{‘c’, ‘d’}); Go home and learn more. Next time, buy me a Pepsi. I don’t drink coke.

Is StringBuilder faster than String?

1. StringBuilder is faster than String. Where’s the evidence?

I’ve been coding so fast, people are always saying that StringBuilder is so fast!

1.1 the String

long startTime = System.currentTimeMillis();
String str = "";
for (int i = 0; i < 1000000; i++) {
    str += i;
}
System.out.println("String time:" + (System.currentTimeMillis() - startTime) + "毫秒");
Copy the code

1.2 the StringBuilder

long startTime = System.currentTimeMillis();
StringBuilder str = new StringBuilder();
for (int i = 0; i < 1000000; i++) {
    str.append(i);
}
System.out.println("The StringBuilder time-consuming" + (System.currentTimeMillis() - startTime) + "毫秒");
Copy the code

1.3 StringBuffer

long startTime = System.currentTimeMillis();
StringBuffer str = new StringBuffer();
for (int i = 0; i < 1000000; i++) {
    str.append(i);
}
System.out.println("StringBuffer time-consuming" + (System.currentTimeMillis() - startTime) + "毫秒");
Copy the code

To sum up, String, StringBuilder, StringBuffer are used respectively, and String chaining operations (100, 1000, 10,000, 100,000, and 1,000,000) are recorded. The final summary chart is as follows;

The following conclusions can be drawn from the graph above.

  1. StringString chaining can be time-consuming, especially with large data volumes, and simply unusable.It’s an experiment. You don’t usually do that!
  2. StringBuilder,StringBufferSince there is no multi-threaded race and no 🔒 lock escalation, the time of the two classes is almost the same, which is of course recommended for single-threaded useStringBuilder 。

2. StringBuilder is faster than String.

String str = "";
for (int i = 0; i < 10000; i++) {
    str += i;
}
Copy the code

This code is the slowest of the three string concatenations. It’s a StringBuilder that’s going to be optimized for this plus plus notation.

It does get optimized by JVM compile-time, but to what extent, take a look at bytecode instructions; javap -c ApiTest.class

If_icmpgt = new StringBuilder (if_icmpgt); And if you look at it a little bit more closely, you can actually see, is this new inside a loop? Let’s write this code out and look at it;

String str = "";
for (int i = 0; i < 10000; i++) {
    str = new StringBuilder().append(str).append(i).toString();
}
Copy the code

Looking at the code now, it’s clear that all string linking operations need to be instantiated once to StringBuilder, so it’s time consuming. And you can verify that it takes the same amount of time to write code as a string link. So it’s faster to get StringBuilder out of the for loop one level up.

Four, String source code analysis

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; . }Copy the code

1. Initialization

String STR = “ABC “; String STR =” ABC “; The underlying data structure of a String is the array char value[], so it can be initialized in many ways.

String str_01 = "abc";
System.out.println("Default:" + str_01);

String str_02 = new String(new char[] {'a'.'b'.'c'});
System.out.println("Char mode:" + str_02);

String str_03 = new String(new int[] {0x61.0x62.0x63}, 0.3);
System.out.println("Int mode:" + str_03);

String str_04 = new String(new byte[] {0x61.0x62.0x63});
System.out.println("Byte mode:" + str_04);
Copy the code

All of these methods can be initialized, and the final result is the same, ABC. If it’s initialized in a way that doesn’t make you feel like it’s a data structure, str_01.charat (0); As long as you dig a little bit into the source code, you will find that it is O(1) time complexity to get elements from the array, so the efficiency is also very high, source code as follows;

public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}
Copy the code

2. Final

String creation is immutable, you see the + + sign connection operation, is to create a new object to store data in the past, through the source code can see;

As you can see from the source code, both the String class and the method used to store the String are final, that is, they are immutable once created.

For example

String str_01 = "abc";
String str_02 = "abc" + "def";
String str_03 = str_01 + "def";
Copy the code

Regardless of other cases, for program initialization. How many objects do these str_01, str_02, and str_03 initialize? In fact, the initialization of several objects from the side is to reflect whether the object is mutable.

Next we decompile the above code and create several objects through the instruction code.

Under the decompiled

  public void test_00(a);
    Code:
       0: ldc           #2                  // String abc
       2: astore_1
       3: ldc           #3                  // String abcdef
       5: astore_2
       6: new           #4                  // class java/lang/StringBuilder
       9: dup
      10: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
      13: aload_1
      14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;) Ljava/lang/StringBuilder;
      17: ldc           #7                  // String def
      19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;) Ljava/lang/StringBuilder;
      22: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      25: astore_3
      26: return
Copy the code
  • str_01 = "abc", instruction code:0: ldc, creates an object.
  • str_02 = "abc" + "def", instruction code:3: ldc // String abcdefThanks to JVM compile-time optimization, the two strings are concatenated to create an object store.
  • str_03 = str_01 + "def", instruction code:invokevirtualThis one is different. It involves concatenating two stringsStringBuilderObject until the endtoString:()Operation to create three objects.

So, as we can see, string creation cannot be modified, and concatenation creates new objects.

3. intern()

3.1 Classic Topics

String str_1 = new String("ab");
String str_2 = new String("ab");
String str_3 = "ab";

System.out.println(str_1 == str_2);
System.out.println(str_1 == str_2.intern());
System.out.println(str_1.intern() == str_2.intern());
System.out.println(str_1 == str_3);
System.out.println(str_1.intern() == str_3);
Copy the code

This is a classic String interview question, which may seem a bit confusing at first glance. The answers are as follows;

false
false
true
false
true
Copy the code

3.2 Source code Analysis

Intern () = intern() = intern()

/**
 * Returns a canonical representation for the string object.
 * <p>
 * A pool of strings, initially empty, is maintained privately by the
 * class {@code String}.
 * <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>
 * It follows that for any two strings {@code s} and {@code t},
 * {@code s.intern() == t.intern()} is {@code true}
 * if and only if {@code s.equals(t)} is {@codetrue}. * <p> * All literal strings and string-valued constant expressions are * interned. String literals are defined in Section 3.10.5 of the * <cite> the Java&trade; Language Specification</cite>. * *@return  a string that has the same contents as this string, but is
 *          guaranteed to be from a pool of unique strings.
 */
public native String intern(a);
Copy the code

What does this code and comment mean?

Intern () is a native method that calls functions written in C++ through JNI.

\openjdk8\jdk\src\share\native\java\lang\String.c

Java_java_lang_String_intern(JNIEnv *env, jobject this)  
{  
    return JVM_InternString(env, this);  
}  

oop result = StringTable::intern(string, CHECK_NULL);

oop StringTable::intern(Handle string_or_null, jchar* name,  
                        int len, TRAPS) {  
  unsigned int hashValue = java_lang_String::hash_string(name, len);  
  int index = the_table() - >hash_to_index(hashValue);  
  oop string = the_table() - >lookup(index, name, len, hashValue);  
  if(string ! =NULL) return string;   
  return the_table() - >basic_add(index, string_or_null, name, len,  
                                hashValue, CHECK_NULL);  
}  
Copy the code
  • Block of code a little longer here to capture only a part of the content, source code can learn open-source JDK code, connect: codeload.github.com/abhijangda/…
  • The C++ code is a bit like the HashMap hash bucket + list data structure, which is used to hold strings, so if the hashes clash too much, the list will be too long. This was covered in the hashMap tutorial, and you can go back to the hashMap source code
  • StringTable is a fixed-length array1009Jdk1.6 can not be adjusted, jdK1.7 can be set-XX:StringTableSize, adjust as needed.

3.3 Problem Diagram

Look at the picture and speak as follows.

  1. Say first= =Base types compare values and reference types compare addresses. In addition, equal compares hash values.
  2. Two new objects must have different addresses, so false.
  3. Intern () pushes the value directly into the constant pool, so both objects do itintern()After the operation, the comparison is the value in the constant pool.
  4. str_3 = "ab"The JVM compiler is optimized not to recreate the object, but to refer directly to the value in the constant pool. sostr_1.intern() == str_3, and the result is true.

Understanding this structure, there is no need to memorize interview, so that the understanding is really understand, the brain will follow pleasure.

5, StringBuilder source analysis

1. Initialization

new StringBuilder();
new StringBuilder(16);
new StringBuilder("abc");
Copy the code

Either of these methods can be initialized. You can pass an initial capacity or you can initialize a default string. Its source code is as follows;

public StringBuilder(a) {
    super(16);
}

AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}
Copy the code

This is initializing an array! That’s just like using an ArrayList.

2. Add elements

stringBuilder.append("a");
stringBuilder.append("b");
stringBuilder.append("c");
Copy the code

Adding an element is easy, just use Append. How does it fit into the array? Do I need to expand it?

2.1 Entry Method

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}
Copy the code
  • This is apublic final class StringBuilder extends AbstractStringBuilderAnd the parent class ofStringBufferSo let’s share this method.
  • This includes capacity detection, element copying, and recordingcountThe number.

2.2 Capacity Expansion

ensureCapacityInternal(count + len);

/** * This method has the same contract as ensureCapacity, but is * never synchronized. */
private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0)
        expandCapacity(minimumCapacity);
}

/** * This implements the expansion semantics of ensureCapacity with no * size check or synchronization. */
void expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
    if (newCapacity - minimumCapacity < 0)
        newCapacity = minimumCapacity;
    if (newCapacity < 0) {
        if (minimumCapacity < 0) // overflow
            throw new OutOfMemoryError();
        newCapacity = Integer.MAX_VALUE;
    }
    value = Arrays.copyOf(value, newCapacity);
}
Copy the code

StringBuilder, like arrays, detects capacity and expands as needed. I’m going to add n * 2 + 2, and I’m going to copy the old elements into the new array.

2.3 Filling Elements

str.getChars(0, len, value, count);

public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
    // ...
    System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
Copy the code

The method of adding elements is based on the System. Arraycopy copy operation, which is a local method.

2.4 the toString ()

Since stringBuilder is an array, how does it get converted to a string?

stringBuilder.toString();

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

In fact, when you use it as a String, you use the String constructor to pass in an array to convert it, which is what we did when we talked about strings.

StringBuffer source code analysis

StringBuffer is basically the same API as StringBuilder. The dimension difference is that StringBuffer is thread-safe because it has a synchronized 🔒 lock. The source code is as follows;

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

Isn’t synchronized a heavyweight lock, and how does the JVM optimize it?

In order to reduce the performance loss caused by lock acquisition and lock release, biased lock, lightweight lock and heavyweight lock are introduced for optimization. It carries out a lock upgrade, as shown in the following picture (this picture is taken from Internet users: Ji-ji-ji-chizi, very excellent picture).

  1. Starts in a lockless state when a thread enterssynchronizedSynchronous code block, will check whether the object header and stack frame has the current line ID number, if not, useCASReplacement.
  2. Used when unlockingCAS å°† Displaced Mark WordThe replacement goes back to the object header. If it succeeds, no contention occurred, and if it fails, the current lock has a contention and is upgraded to a heavyweight lock.
  3. In addition, in most cases the lock 🔒 is not contested and is basically held by a single thread. Therefore, in order to avoid the performance loss of acquiring and releasing locks, lock upgrades are introduced and cannot be degraded after upgrading.

7. Common APIS

The serial number methods describe
1 str.concat("cde") String concatenation, replace the + sign
2 str.length() To obtain the length of the
3 isEmpty() Sentenced to empty
4 str.charAt(0) Gets the element at the specified location
5 str.codePointAt(0) Gets the element at the specified position and returns the ASCII code value
6 str.getBytes() Get byte []
7 str.equals(“abc”) To compare
8 str.equalsIgnoreCase(“AbC”) Ignore case and compare
9 str.startsWith(“a”) Start position value judgment
10 str.endsWith(“c”) End position value judgment
11 str.indexOf(“b”) Determine the element position, the start position
12 str.lastIndexOf(“b”) Determine element position, end position
13 str.substring(0, 1) The interception
14 str.split(“,”) Split, can support re
15 STR. Replace (” a “, “d”), the replaceAll replace
16 str.toUpperCase() Turn the capital
17 str.toLowerCase() Turn to lowercase
18 str.toCharArray() Turn an array
19 String.format(str, “”) Format, % S, % C, % B, % D, % X, % O, % F, % A, % E, % G, % H, %%, %n, %tx
20 str.valueOf(“123”) Turn the string
21 trim() Format, start and end to space
22 str.hashCode() Get the hash value

Eight, summary

  • Practice makes perfect, shortage in playWhat you learn doesn’t have to be just to prepare you for an interview, but rather to expand your technical depth and breadth. The process can be painful, but there has to be some brain-burning process to make more knowledge easier to learn.
  • This article introducesString, StringBuilder, StringBuffer, the data structure and source code analysis, more thorough understanding, can also be more accurate use, will not be because do not understand and make mistakes.
  • Want to write good code, at least have the four content, including; Data structure, algorithm, source code, design pattern, these four aspects in addition to business experience and personal vision, can really write a requirement, a large project with good scalability and easy maintenance.

Nine, series recommendation

  • Hold the grass! You poisoned the code!
  • A code review, almost failed the trial period!
  • LinkedList inserts faster than ArrayList? Are you sure?
  • Relearning Java Design Patterns (22 Real Life Development Scenarios)
  • Interview manual (get the fastest car, get the most expensive offer)