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.
String
String chaining can be time-consuming, especially with large data volumes, and simply unusable.It’s an experiment. You don’t usually do that!StringBuilder
,StringBuffer
Since 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 abcdef
Thanks to JVM compile-time optimization, the two strings are concatenated to create an object store.str_03 = str_01 + "def"
, instruction code:invokevirtual
This one is different. It involves concatenating two stringsStringBuilder
Object 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™ 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 array
1009
Jdk1.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.
- Say first
= =
Base types compare values and reference types compare addresses. In addition, equal compares hash values. - Two new objects must have different addresses, so false.
- Intern () pushes the value directly into the constant pool, so both objects do it
intern()
After the operation, the comparison is the value in the constant pool. 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 a
public final class StringBuilder extends AbstractStringBuilder
And the parent class ofStringBuffer
So let’s share this method. - This includes capacity detection, element copying, and recording
count
The 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).
- Starts in a lockless state when a thread enters
synchronized
Synchronous code block, will check whether the object header and stack frame has the current line ID number, if not, useCAS
Replacement. - Used when unlocking
CAS
å°†Displaced Mark Word
The 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. - 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 play
What 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 introduces
String, 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)