In JAVA programs, most of the performance problems are not caused by the JAVA language, but by the program itself. Developing good coding habits is important and can significantly improve application performance.

Use singletons when appropriate

Using singletons can reduce the load burden, shorten the load time, and improve the load efficiency. However, it is not applicable to all places. Simply speaking, singletons are mainly applicable to the following three aspects:

  • Control the use of resources, through thread synchronization to control the concurrent access of resources;

  • Control the generation of instances to achieve the purpose of saving resources;

  • Control data sharing to allow multiple unrelated processes or threads to communicate without establishing a direct correlation. Compiled a Java interview treasure book complete PDF

Avoid arbitrary use of static variables

When an object is defined as a static variable, the GC usually does not reclaim the memory occupied by the object, such as

public class A {
    private static B b = new B();
}
Copy the code

At this point, the lifetime of the static variable B is synchronized with that of class A. If class A is not unloaded, the b object is resident in memory until the program terminates.

Avoid creating Java objects too often

Try to avoid in the method called often, cycle of the new object, because the system not only takes time to create the object, but also to spend time to garbage collection and processing of these objects, in we can control the range, maximum reuse objects, best can use object or array to replace basic data type.

Use the final modifier

Classes with the final modifier are not derivable. There are many examples of final applications in the JAVA core API, such as JAVA, Lang, and String. Specifying final for the String class prevents the consumer from overwriting the Length () method. In addition, if a class is final, all the methods of that class are final. The Java compiler looks for opportunities to inline all final methods (depending on the specific compiler implementation), which can improve performance by an average of 50%.

For example, change getters/setters that access variables in an instance to “final:”

Simple getter/setter methods should be made final. This tells the compiler that the method is not loaded so it can be changed to “inlined”. Example:

class MAF {
    public void setSize (int size) {
        _size = size;
    }
    private int _size;
}
Copy the code

correct

class DAF_fixed {
    final public void setSize (int size) {
        _size = size;
    }
    private int _size;
}
Copy the code

Using local variables

Parameters passed when calling a method and temporary variables created during the call are stored in the Stack, which is faster. Other variables, such as static variables, instance variables, etc., are created in the Heap and are slower.

Handle where both the package type and the base type are used

Although wrapper types and primitive types are interchangeable in use, the memory areas they generate are completely different. Primitive types are generated and processed in the stack, while wrapper types are objects and instances are generated in the heap. In the case of collection-class objects, processing that has object aspects needs applies to wrapper types, while other processing advocates primitive types.

Use synchronized sparingly, minimizing the use of synchronize

It is well known that synchronization is expensive and can even cause deadlocks, so try to avoid unnecessary synchronization control. When the synchronize method is called, it locks the current object so that no other thread can call any other methods on the current object until the method completes execution. Therefore, the synchronize method is kept to a minimum and method synchronization should be used instead of code block synchronization whenever possible.

Do not use finalize methods

As a matter of fact, it is not a good choice to finalize the resource cleaning in Finalize method. Because of the heavy workload of GC, especially when the Young generation memory is recycled, the application program will be paused. Therefore, to finalize the resource cleaning in Finalize method will lead to a heavier burden of GC and a worse running efficiency of the program.

Use primitive data types instead of objects

String str = "hello";
Copy the code

This creates a “hello” string, which is cached by the JVM’s character cache pool;

String str = new String("hello");
Copy the code

In addition to creating a String, the String referenced by STR also contains an array of char[], which holds h, E, L, L,o

Multithreading should use HashMap and ArrayList as far as possible without thread safety

HashTable, Vector, and so on use synchronization, which degrades performance.

Create a HashMap properly

Make full use of this constructor when creating a large hashMap

public HashMap(int initialCapacity, float loadFactor);
Copy the code

By default, initialCapacity is only 16, and loadFactor is 0.75. You’d better be able to accurately estimate the optimal size you need. Vectors do the same thing.

Reduce double counting of variables

Such as:

for(int i=0; i<list.size(); i++)Copy the code

Should read:

for(int i=0,len=list.size(); i<len; i++)Copy the code

And avoid using complex expressions in loops, where loop conditions are evaluated repeatedly. If you leave the loop condition values unchanged without using complex expressions, the program will run faster.

Avoid unnecessary creation

Such as:

A a = new A();
  if(i==1){
    list.add(a);
}
Copy the code

Should read:

if(i==1){
    A a = new A();
    list.add(a);
}
Copy the code

Release resources ina finally block

Resources used ina program should be released to avoid resource leaks, preferably ina finally block. Regardless of the result of program execution, the finally block is always executed to ensure that the resource is closed properly.

Use a shift instead of the ‘a/b’ operation

“/” is an expensive operation, and using a shift operation would be faster and more efficient

Such as:

int num = a / 4;
int num = a / 8;
Copy the code

Should read:

int num = a >> 2;
int num = a >> 3;
Copy the code

Note, however, that the use of shifts should be annotated, because the shift operation is not intuitive and difficult to understand.

Replace the ‘a*b’ operation with a shift

Similarly, for the ‘*’ operation, the shift operation will be faster and more efficient

Such as:

int num = a * 4;
int num = a * 8;
Copy the code

Should read:

int num = a << 2;
int num = a << 3;
Copy the code

Determine the size of the StringBuffer

The constructor of a StringBuffer creates an array of characters of a default size (usually 16). In use, if this size is exceeded, memory is reallocated, a larger array is created, the original array is copied over, and the old array is discarded. In most cases, you can specify the size when creating a StringBuffer so that it doesn’t automatically grow when capacity is low, which improves performance.

Such as:

StringBuffer buffer = new StringBuffer(1000);
Copy the code

Avoid using two-dimensional arrays

Two-dimensional data takes up much more memory than a one-dimensional array, perhaps 10 times more.

Avoid using split

Avoid using split unless it is absolutely necessary. Because split supports regular expressions, it is relatively inefficient. If it is frequently called tens of millions of times, it will consume a lot of resources. Consider using Apache’s stringutils.split (string,char). Frequent splits can cache results.

ArrayList & LinkedList

One is a linear list, one is a LinkedList, in short, random queries use ArrayList as much as possible, ArrayList is better than LinkedList, LinkedList also moves Pointers, add and delete operations LinkedList is better than ArrayList, ArrayList also moves data, However, this is a theoretical analysis, the fact is not necessarily so, the important thing is to understand the data structure of the two, appropriate medicine.

Use system.arrayCopy () instead of looping over arrays

System.arraycopy() is much faster than copying an array through a loop.

Cache frequently used objects

Frequently used objects can be cached as much as possible. Arrays or containers of HashMap can be used for caching, but this method may lead to excessive cache occupation and performance deterioration. It is recommended to use some third-party open source tools such as EhCache and Oscache for caching. They basically implement FIFO/FLU and other caching algorithms.

Avoid very large memory allocations

Sometimes problems are not caused by the state of the heap at the time, but by allocation failures. The allocated blocks must all be contiguous, and as the heap gets fuller, it becomes more difficult to find large contiguous blocks.

26. Use exceptions with caution

When an exception is created, a stack track is collected that describes where the exception was created. Building these stack traces requires taking a snapshot of the runtime stack, which is very expensive. When an Exception needs to be created, the JVM has to say: Hold still, I want to save a snapshot of you as you are now, so stop pushing and pushing for a while. The stack trace contains not just one or two elements in the runtime stack, but every element in that stack.

If you create an Exception, you pay a price, but catching exceptions is inexpensive, so you can wrap the core with a try-catch. Technically, you can even throw exceptions at will without spending a lot of money. It is not the throw operation that incurs the performance penalty — although it is somewhat unusual to throw an exception without having previously created it. The real cost is to create exceptions, and fortunately, good programming habits have taught us that we shouldn’t throw exceptions out of the window. Exceptions are designed for exceptional situations and should be used with this principle in mind.

Reuse objects

In the case of strings in particular, use StringBuffer instead of String concatenation because not only will the system spend time generating objects, it may also spend time garbage collecting and processing them later. Therefore, generating too many objects will have a significant impact on the performance of the program.

Do not initialize variables repeatedly

By default, when class constructors are called, Java initializes variables to certain values. All objects are set to null, integer variables to 0, float and double to 0.0, and logical values to false. This is especially important when a class is derived from another class, because all constructors in the constructor chain are automatically called when an object is created with the new keyword.

One note here is that it is best to place an initial value on a member variable in one method when you need to call another method. For example, in initXXX(), calling a method directly to assign may throw a null pointer exception because the class has not been initialized, such as: public int state = this.getState().

Shut down IO in time

In the Java programming process, database connection, I/O flow operation, after the use, timely closure to release resources. Because operating on these large objects can cause a lot of overhead.

Do not use a Try/Catch statement in a loop. Place the Try/Catch statement in the outermost part of the loop

Error is the class that gets system errors, or virtual machine errors. Not all exceptions can be obtained. If the VM reports an Exception, the Exception cannot be obtained.

The StringBuffer’s constructor sets its initialization capacity

Can significantly improve performance

The default size of a StringBuffer is 16, and when the StringBuffer reaches its maximum size, it increases itself to twice its current size +2, that is, 2*n+2. Whenever a StringBuffer reaches its maximum capacity, it has to create a new array of objects and then copy the old array of objects, which can waste a lot of time. So it’s important to set the StringBuffer to a reasonable initialization capacity.

HaspMap traversal:

Map<String, String[]> paraMap = new HashMap<String, String[]>();
for( Entry<String, String[]> entry : paraMap.entrySet() ) {
    String appFieldDefId = entry.getKey();
    String[] values = entry.getValue();
}
Copy the code

The hash value is used to extract the corresponding Entry for comparison and obtain the result. After obtaining the Entry value, the key and value are directly obtained.

Use of array and ArrayList

Array is the most efficient array, but its capacity is fixed and cannot be changed dynamically. ArrayList can grow dynamically, but at the expense of efficiency.

Single thread using HashMap, ArrayList,

The use of HashTable and Vector is not recommended unless necessary, as they use synchronization mechanisms and reduce performance.

The difference between StringBuffer, StringBuilder

Java.lang.StringBuffer A thread-safe sequence of variable characters. A String buffer similar to String, but not modifiable. The StringBuilder class should generally be used in preference to this class because it supports all the same operations, but is faster because it does not perform synchronization. For better performance, when constructing a StringBuffer or StringBuilder, try to specify its capacity. Of course not if it’s 16 characters or less. In the same case, using StringBuilder yields only a 10% to 15% performance improvement over using StringBuffer, but at the risk of multithreading insecurity. All things considered, StringBuffer is recommended.

Here are some examples of practical optimizations:

Avoid complex expressions in loop conditions

Without compiler optimization, loop conditions are evaluated repeatedly in loops, and programs run faster if they are left unchanged without complex expressions. Example:

import java.util.Vector; class CEL { void method (Vector vector) { for (int i = 0; i < vector.size (); i++) // Violation ; / /... }}}Copy the code

Correction:

class CEL_fixed { void method (Vector vector) { int size = vector.size () for (int i = 0; i < size; i++) ; / /... }}Copy the code

Define initial sizes for ‘Vectors’ and ‘Hashtables’

When the JVM augments a Vector, it recreates a larger array, copies the contents of the original array, and finally reclaims the original array. As you can see, expanding the size of a Vector is a time-consuming process.

In general, the default size of 10 elements is not enough. You’d better be able to accurately estimate the optimal size you need. Example:

import java.util.Vector; public class DIC { public void addObjects (Object[] o) { // if length > 10, Vector needs to expand for (int i = 0; i< o.length; i++) { v.add(o); // capacity before it can add more elements. } } public Vector v = new Vector(); // no initialCapacity. }Copy the code

Correction:

Set your own initial size.

public Vector v = new Vector(20);
public Hashtable hash = new Hashtable(10);
Copy the code

Close the Stream ina finally block

Resources used in the program should be released to avoid resource leakage. This is best done ina finally block. Regardless of the result of program execution, the finally block is always executed to ensure that the resource is closed properly.

4, use ‘system.arrayCopy ()’ instead of looping through arrays

Example:

public class IRB {
    void method () {
        int[] array1 = new int [100];
        for (int i = 0; i < array1.length; i++) {
            array1 [i] = i;
        }
        int[] array2 = new int [100];
        for (int i = 0; i < array2.length; i++) {
            array2 [i] = array1 [i]; // Violation
        }
    }
}
Copy the code

Correction:

public class IRB { void method () { int[] array1 = new int [100]; for (int i = 0; i < array1.length; i++) { array1 [i] = i; } int[] array2 = new int [100]; System.arraycopy(array1, 0, array2, 0, 100); }}Copy the code

5. Change getters/setters to “final” for instance variables

Simple getter/setter methods should be made final. This tells the compiler that the method is not loaded so it can be changed to “inlined”. Example:

class MAF {
    public void setSize (int size) {
        _size = size;
    }
    private int _size;
}
Copy the code

Correction:

class DAF_fixed {
    final public void setSize (int size) {
        _size = size;
    }
    private int _size;
}
Copy the code

6. For constant strings, replace ‘StringBuffer’ with ‘String’

Constant strings do not need to change their length dynamically.

Example:

public class USC {
    String method () {
        StringBuffer s = new StringBuffer ("Hello");
        String t = s + "World!";
        return t;
    }
}
Copy the code

Correction: Replace StringBuffer with String, which will reduce runtime overhead and improve performance if it is certain that the String will not change.

Use ‘ ‘instead of “” when adding strings, if the string has only one character

Example:

public class STR {
    public void method(String s) {
        String string = s + "d" // violation.
        string = "abc" + "d" // violation.
    }
}
Copy the code

Correction:

Replace a one-character string with ‘ ‘

public class STR {
    public void method(String s) {
        String string = s + 'd'
        string = "abc" + 'd'
    }
}
Copy the code

The above is only part of the Java programming in performance optimization, performance optimization is mostly in terms of time and efficiency, the code structure level of weighing, each have advantages and disadvantages, don’t put the above content as a dogma, perhaps some applicable to our actual work, some do not apply, still hope scenarios are based on the actual work, learning, living accommodation is advisable. Compiled a Java interview treasure book complete PDF