Reposted an article on how to optimize Java code and improve efficiency

Source: Internet
Author: User

Resources available for the Program (memory, CPU time, network bandwidth, etc.) are limited. The purpose of optimization is to allow the program to complete the scheduled tasks with as few resources as possible. Optimization usually involves two aspects: reducing the size of the code and improving the code running efficiency. This article focuses on how to improve code efficiency.
In Java programs, most of the performance problems are not caused by the Java language, but by the program itself. It is very important to develop good coding habits. For example, to use Java. Lang. String and Java. util. Vector correctly and skillfully, it can significantly improve the program performance. Next we will analyze this problem in detail.

1,   It is recommended that the final modifier of a class with the final modifier be specified. There are many examples of final applications in the Java core API, such as Java. Lang. String. Specifying final for the string class prevents people from overwriting the length () method. In addition, if you specify a class as final, all the methods of this class are final. The Java compiler will look for opportunities to inline (Inline) All final methods (this is related to the specific compiler implementation ). This can increase the performance by an average of 50%.

2,   Reuse objects as much as possible. In particular, when a String object is used, use stringbuffer instead when a string connection occurs. Because the system not only takes time to generate objects, it may take time to recycle and process these objects. Therefore, generating too many objects will greatly affect the program performance.

3,   Use local variables whenever possible. The parameters passed during method calling and the temporary variables created in the call are saved in the stack, which is faster. Other variables, such as static variables and instance variables, are created in heap, which is slow. In addition, local variables may be further optimized depending on the specific compiler/JVM. See use stack variables whenever possible.

4,   Do not reinitialize Variables By default, Java initializes the variable to a definite value when calling the class constructor: all objects are set to null, and integer variables (byte, short, Int, long) set it to 0, float and double variables to 0.0, and logical value to false. This is especially important when a class is derived from another class, because when an object is created using the new keyword, all constructors in the constructor chain are automatically called.

5,   In the development of Java + Oracle application systems, SQL statements embedded in Java should be written in uppercase to reduce the parsing burden on the Oracle parser.

6,   During Java programming, be careful when performing database connection and I/O Stream operations. after use, release resources even if it is disabled. Because the operations on these large objects will cause a large system overhead, a slight carelessness, and cause serious consequences.

7,   Because JVM has its own GC mechanism, it does not need to be considered too much by program developers. This reduces the burden on developers to a certain extent, but also omits hidden risks, excessive object creation will consume a large amount of system memory, which may cause memory leakage in severe cases. Therefore, it is important to ensure timely collection of expired objects. The condition for JVM garbage collection is that the object is not referenced. However, jvm gc is not very witty, and even if the object meets the condition of garbage collection, it cannot be immediately recycled. Therefore, we recommend that you manually set it to null after the object is used.

8,   When using the synchronization mechanism, we should try to use synchronous methods instead of code block synchronization.

9,   Minimize repeated calculation of Variables
For example: for (INT I = 0; I <list. size; I ++ ){
            ...
}
Should be replaced:
For (INT I = 0, int Len = List. Size (); I <Len; I ++ ){
            ...
}

10. Use the lazy loading policy as much as possible, that is, to create it only when necessary.
    For example:   String STR = "AAA ";
            If (I = 1 ){
                List. Add (STR );
}
Should be replaced:
            If (I = 1 ){
String STR = "AAA ";
                List. Add (STR );
}
11. Use exceptions with caution
Exceptions are detrimental to performance. To throw an exception, you must first create a new object. The constructor of the throwable interface calls the local (native) method named fillinstacktrace (), the fillinstacktrace () method checks the stack, and collects Call trace information. As long as an exception is thrown, the VM must adjust the call stack because a new object is created during processing. Exceptions can only be used for error handling and should not be used to control program processes.

12. Do not use the following in a loop:
Try {
} Catch (){
}
Should be placed in the outermost layer.

13. Use of stringbuffer:
        Stringbuffer indicates a variable and writable string.
There are three constructor methods:
Stringbuffer ();           // A space of 16 characters is allocated by default.
Stringbuffer (INT size ); // Allocate space with size characters
Stringbuffer (string Str ); // Allocate 16 characters + Str. Length () character space
You can use the stringbuffer constructor to set its initialization capacity, which can significantly improve performance. The constringbuffer (intlength) is the constringbuffer. The length parameter indicates the number of characters that the stringbuffer can hold. You can also use the ensurecapacity (intminimumcapacity) method to set its capacity after the stringbuffer object is created. First, let's look at the default behavior of stringbuffer, and then find a better way to improve performance.
Stringbuffer maintains an internal character array. When you use the default constringbuffer to create a stringbuffer object, the capacity of stringbuffer is initialized to 16 characters because no initialization character length is set, that is to say, the default capacity is 16 characters. When the stringbuffer reaches the maximum capacity, it will increase its capacity to 2 times of the current plus 2, that is, (2 * old value + 2 ). If you use the default value, after initialization, append characters to it. When you append 16th characters, it will increase the capacity to 34 (2*16 + 2 ), when it is appended to 34 characters, the capacity will be increased to 70 (2*34 + 2 ). Whatever the matter, as long as the stringbuffer reaches its maximum capacity, it has to create a new character array and copy the old and new characters again-this is too expensive. Therefore, it is impossible to set a reasonable initial capacity value for stringbuffer, which will bring immediate performance gains.
The adjustment of the stringbuffer initialization process is evident. Therefore, using a suitable capacity value to initialize stringbuffer is always the best advice.

14. Properly use Java. util. vector.
Simply put, a vector is an array of Java. Lang. object instances. A vector is similar to an array. Its elements can be accessed through an integer index. However, after a vector object is created, the object size can be expanded or reduced based on the addition or deletion of elements. Consider the following example of adding elements to a vector:
Object OBJ = new object ();
Vector v = new vector (100000 );
For (INT I = 0;
I <100000; I ++) {v. Add (0, OBJ );}

Unless there are absolutely good reasons to require that the new elements be inserted before the vector each time, the above Code is not good for performance. In the default constructor, the initial storage capacity of the vector is 10 elements. If the storage capacity of the new element is insufficient when it is added, the storage capacity will be doubled each time. Like the stringbuffer class, the vector class copies all existing elements to the new storage space each time it expands the storage capacity. The following code snippets are several orders of magnitude faster than the previous example:
Object OBJ = new object ();
Vector v = new vector (100000 );
For (INT I = 0; I <100000; I ++) {v. Add (OBJ );}

The same rule applies to the remove () method of the Vector class. Because each element in a vector cannot contain a "gap", deleting any element other than the last element causes the element to move forward after it is deleted. That is to say, deleting the last element from a vector is several times less overhead than deleting the first element.

We can use this code to delete all elements from the previous vector:
For (INT I = 0; I <100000; I ++)
{
V. Remove (0 );
}

However, compared with the following code, the previous code is several orders of magnitude slower:
For (INT I = 0; I <100000; I ++)
{
V. Remove (V. Size ()-1 );
}

The best way to delete all elements from Vector object V is:
V. removeallelements ();

Assume that the vector object V contains the string "hello ". Consider the following code. It will delete the "hello" string from this vector:
String S = "hello ";
Int I = V. indexof (s );
If (I! =-1) v. Remove (s );

These codes seem to have no errors, but they are also detrimental to performance. In this Code, the indexof () method searches for the string "hello" in sequence, and the remove (s) method also performs the same sequential search. The improved version is:
String S = "hello ";
Int I = V. indexof (s );
If (I! =-1) v. Remove (I );

In this version, the exact index position of the element to be deleted is directly given in the remove () method, thus avoiding the second search. A better version is:
String S = "hello"; V. Remove (s );

Finally, let's look at a code snippet about the Vector class:
For (INT I = 0; I ++; I <v. length)

If V contains 100,000 elements, the code snippet calls the v. Size () method 100,000 times. Although the size method is a simple method, it still requires the overhead of a method call. At least JVM needs to configure and clear the stack environment for it. Here, the code inside the for loop does not modify the V Size of the vector object in any way, so the above Code should be rewritten to the following form:
Int size = V. Size (); For (INT I = 0; I ++; I <size)

Although this is a simple change, it still wins the performance. After all, every CPU cycle is precious.

15. When copying a large amount of data, use the system. arraycopy () command.

16. Code refactoring: enhances code readability.
    For example:
Public class shopcart {
        Private list carts;
        ...
        Public void add (Object item ){
            If (carts = NULL ){
                Carts = new arraylist ();
}
CRTS. Add (item );
}
Public void remove (Object item ){
    If (carts. Contains (item )){
        Carts. Remove (item );
}
}
Public list getcarts (){
    // Returns the read-only list.
    Return collections. unmodifiablelist (carts );
}

// This method is not recommended
// This. getcarts (). Add (item );
    }

17. Create a class instance without the New Keyword
When you create an instance with the New Keyword, all constructors in the constructor chain are automatically called. But if an object implements the cloneable interface, we can call its clone () method. The clone () method does not call any class constructor.
When using the design pattern, if you use the factory mode to create an object, it is very easy to use the clone () method to create a new object instance. For example, the following is a typical Implementation of the factory mode:
Public static credit getnewcredit (){
    Return new credit ();
}
The improved code uses the clone () method as follows:
Private Static credit basecredit = new credit ();
Public static credit getnewcredit (){
    Return (credit) basecredit. Clone ();
}
The above idea is also useful for Array Processing.

18. multiplication and division
Consider the following code:
For (val = 0; Val <100000; Val + = 5 ){
Alterx = Val * 8; myresult = Val * 2;
}
Replacing multiplication with shift operations can greatly improve performance. The modified code is as follows:
For (val = 0; Val <100000; Val + = 5 ){
Alterx = Val <3; myresult = Val <1;
}
The modified code does not multiply by 8. Instead, it uses the equivalent three-bit left shift operation, and one-bit left shift operation is equivalent to multiplying 2. Correspondingly, the one-bit operation on the right is equivalent to dividing by 2. It is worth mentioning that, although the shift operation is fast, it may make the code more difficult to understand, so it is best to add some comments.

19. Disable useless sessions on the JSP page.
    A common misunderstanding is that the session is created when a client accesses it. However, the fact is that the session is created until a server program calls httpservletrequest. A statement such as getsession (true) is created. Note that if JSP is not displayed, <% @ pagesession = "false" %> disable the session, when the JSP file is compiled into servlet, the following statement is automatically added: httpsession session = httpservletrequest. getsession (true); this is also the source of the implicit Session Object in JSP. Because the session consumes memory resources, if you do not plan to use the session, you should disable it in all JSPs.
For pages that do not need to track session Status, disabling automatically created sessions can save some resources. Run the following page command: <% @ page session = "false" %>

20. JDBC and I/O
If an application needs to access a large dataset, consider using block extraction. By default, JDBC extracts 32 rows of data each time. For example, if we want to traverse a 5000-row record set, JDBC must call the database 157 times to extract all the data. If the block size is changed to 512, the number of database calls will be reduced to 10.
[P] [/P] 21. servlet and memory usage
Many developers store a large amount of information in user sessions at will. In some cases, objects stored in sessions are not recycled in a timely manner by the garbage collection mechanism. In terms of performance, the typical symptom is that the user feels the system slows down cyclically, but cannot attribute the cause to any specific component. If you monitor the heap space of the JVM, the memory usage may fluctuate abnormally.
There are two main ways to solve such memory problems. The first method is to implement httpsessionbindinglisten in all beans with the scope of the session.ER interface. In this way, the bean resources can be explicitly released as long as the valueunbound () method is implemented. Another method is to invalidate the session as soon as possible. Most application servers have the option of setting the session expiration time. In addition, you can call the setmaxinactiveinterval () method of the session programmatically. This method is used to set the maximum interval of customer requests allowed by the servlet container before the session is voided, in seconds.

22. Use the buffer tag
Some application servers have added the JSP-oriented buffer tag function. For example, the WebLogic Server of BEA supports this function from version 6.0, and the opensymphony project also supports this function. The JSP buffer tag can buffer both page fragments and the whole page. When the JSP page is executed, if the target segment is already in the buffer, the code that generates the segment will no longer need to be executed. Page-level buffer captures requests to a specified URL and caches the entire result page. This feature is extremely useful for shopping baskets, directories, and portals. For such applications, page-level buffering can save the results of page execution for subsequent requests.

23. select an appropriate reference mechanism
In a typical JSP application system, the page header and footer are often extracted, and the page header and footer are introduced as needed. Currently, there are two main methods to introduce external resources in JSP pages: include commands and include actions.
Include command: for example, <% @ include file = "copyright.html" %>. This command introduces specified resources during compilation. Before compilation, the page with the include command and the specified resource are merged into a file. The referenced external resources are determined at compilation, which is more efficient than the resources determined at runtime.
Include action: for example, <JSP: Include page = "Copyright. jsp"/>. This action introduces the result generated after the specified page is executed. Because it is completed at runtime, the control of output results is more flexible. However, the include action is cost-effective only when the referenced content changes frequently or the referenced page cannot be determined before the request to the home page appears.

24. Clear unnecessary sessions in time
To clear sessions that are no longer active, many application servers have the default session timeout time, usually 30 minutes. When the application server needs to save more sessions, if the memory capacity is insufficient, the operating system will transfer part of the memory data to the disk, and the application server may also use mostrecentlyused according) the algorithm dumps some inactive sessions to the disk, and may even throw an "out-of-memory" exception. In large-scale systems, serialized sessions are expensive. When the session is no longer needed, you should promptly call httpsession. invalidate () to clear the session. The httpsession. invalidate () method can be called on the exit page of the application.

25. Do not declare the array as public static final.

26. Discussion on the traversal efficiency of hashmap
We often encounter traversal operations on key and value pairs in hashmap. There are two methods: Map <string, string []> paramap = newhashmap <string, string []> ();
...... // The first loop
Set <string> appfielddefids = paramap. keyset ();
For (string appfielddefid: appfielddefids ){
String [] values = paramap. Get (appfielddefid );
......
}

// The second loop
For (Entry <string, string []> entry: paramap. entryset ()){
String appfielddefid = entry. getkey ();
String [] values = entry. getvalue ();
.......
}

The first implementation is obviously less efficient than the second implementation.
The analysis is as follows: Set <string> appfielddefids = paramap. keyset (); The keyset is obtained from hashmap first.

The Code is as follows:
Public set <k> keyset (){
Set <k> Ks = keyset;
Return (Ks! = NULL? KS: (keyset = new keyset ()));
}

Private class keyset extendsimplements actset <k> {
Public iterator <k> iterator (){
Return newkeyiterator ();
}
Public int size (){
Return size;
}
Public Boolean contains (Object O ){
Return containskey (O );
}
Public Boolean remove (Object O ){
Return hashmap. This. removeentryforkey (o )! = NULL;
}
Public void clear (){
Hashmap. This. Clear ();
}
}
Actually, a private keyset class is returned, which is inherited from abstractset and implements the set interface.

Let's take a look at the for/in loop syntax.
For (Declaration: expression_r)
Statement

It is translated into the following types during the execution phase:
For (iterator <E> # I = (expression_r). iterator (); # I. hashnext ();){
Declaration = # I. Next ();
Statement
}

Therefore, hashmap. keyset (). iterator () is called in the first for statement for (string appfielddefid: appfielddefids), and newkeyiterator () is called in this method ()

Iterator <k> newkeyiterator (){
Return new keyiterator ();
}
Private class keyiterator extendshashiterator <k> {
Public K next (){
Return nextentry (). getkey ();
}
}

So it is still called in.
The iterator used in the second loop for (Entry <string, string []> entry: paramap. entryset () is one of the following internal classes:

Private class entryiterator extendshashiterator <map. Entry <K, V >> {
Public map. Entry <K, V> next (){
Return nextentry ();
}
}

In this case, the first loop gets the key, and the second loop gets the entry of hashmap.
Efficiency is the second loop embodied in the loop. Therefore, the key and value values can be directly obtained.
The first loop still needs to use the get (Object key) of hashmap to get the value.

Now let's take a look at the get (Object key) method of hashmap.
Public v get (Object key ){
Object K = masknull (key );
Int hash = hash (k );
Int I = indexfor (hash, table. Length); // entry [] Table
Entry <K, V> E = table;
While (true ){
If (E = NULL)
Return NULL;
If (E. Hash = hash & eq (K, E. Key ))
Return e. value;
        E = E. Next;
}
}
In fact, we use the hash value to retrieve the corresponding entry for comparison and obtain the result. Therefore, using the first loop is equivalent to entering the hashmap entry twice.
In the second loop, the key and value are directly obtained after the entry value is obtained, which is more efficient than the first loop. In fact, according to the concept of map, it should also be better to use the second loop. It is originally a value pair of key and value. It is not a good choice to separate the key and value.

27. Use of array and arrylist
Array ([]): the most efficient, but its capacity is fixed and cannot be changed dynamically;
Arraylist: The capacity can be dynamically increased, but the efficiency is sacrificed;
Based on the efficiency and type test, array should be used as much as possible. The array size cannot be determined before arraylist is used!
Arraylist is a complex version of array.
Arraylist encapsulates an array of the object type. In general, it has no essential difference with the array, and even many methods of arraylist, for example, index, indexof, contains, and sort all directly call the corresponding method of Array Based on the internal array.
When arraylist is saved to an object, the type information is discarded. All objects are blocked as objects. The type is not checked during compilation, but an error is reported during running.
Note: Support for generics is added to JDK 5. You can check the type when using arraylist.
From this point of view, the difference between arraylist and array is mainly due to the efficiency of dynamic resizing.

28. Use hashmap and arraylist whenever possible. Unless necessary, hashtable and vector are not recommended. The latter causes performance overhead due to synchronization mechanism.

29. Differences between stringbuffer and stringbuilder:
    Java. Lang. stringbuffer thread-safe variable character sequence. A string buffer similar to a string, but cannot be modified. Stringbuilder. Compared with this class, java. Lang. stringbuilder class should be used first, because it supports all the same operations, but because it does not execute synchronization, It is faster. To achieve better performance, specify the capacity of stirngbuffer or stirngbuilder as much as possible. Of course, if the length of the string you operate is no longer than 16 characters. Use in the same situation
Compared with stringbuffer, stirngbuilder can only achieve performance improvement of about 10%-15%, but it is subject to the risk of multi-thread insecurity. In practical Modular programming, the programmer in charge of a module may not be able to clearly determine whether the module will be run in a multi-threaded environment. Therefore: unless you are sure that the bottleneck of your system is on stringbuffer and that your module is not running in multi-threaded mode, use stringbuffer.

I hope this article will be helpful to everyone's learning.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.