Code optimization, a very important topic. Maybe some people think it is useless, some small places what is good to modify, change or not change the code for the operation of the efficiency of what impact? This problem I am so considering, like the whale in the sea, it ate a small shrimp useful? No, but after eating a lot of shrimp, the whale will be fed.
Code optimization is the same, if the project focuses on as soon as possible without bugs on the line, then at this point you can grasp the big and put the small, the details of the code can not be fine-tuned; but if there is enough time to develop, maintain the code, this time you must consider each detail can be optimized, a small optimization point cumulative, for the code of the operational efficiency is definitely improved.
The goal of code optimization is to
Code Optimization Details
Classes with the final modifier are non-derivable. There are many examples of applications of final in the Java core API, such as java.lang.String, where the entire class is final. Specifying the final modifier for a class makes the class uninheritable, and specifying the final modifier for a method makes the method unoverridable. If a class is specified as final, all methods of the class are final, and the Java compiler looks for opportunities to inline all final methods, which can be a significant improvement in the efficiency of Java operation, see Java Runtime Optimization. This can improve performance by an average of 50%.
In particular, the use of String objects should be replaced with StringBuilder/StringBuffer when string concatenation occurs. Since the Java Virtual Machine not only spends time generating objects, but may also need to spend time garbage collecting and processing these objects later, generating too many objects will have a great impact on the performance of the program.
Parameters passed during a method call and temporary variables created during the call are saved on the stack which is faster, while other variables, such as static variables, instance variables, etc., are created in the heap which is slower. In addition, the variables created in the stack, with the end of the run of the method, these contents are gone, no additional garbage collection is needed.
Java programming process, database connections, I / O flow operations must be careful, in the use of the end, timely closure to release resources. Because the operation of these large objects will cause a large system overhead, a little carelessness, will lead to serious consequences.
To clarify a concept, calls to methods, even if there is only one statement in the method, are consumed, including the creation of stack frames, protection of the site when the method is called, and restoration of the site when the call to the method finishes. So for example the following operation:
for (int i = 0; i < list.size(); i++)
{...}
Suggested replacement:
for (int i = 0, int length = list.size(); i < length; i++)
{...}
This reduces consumption a lot when list.size() is large
例如:
String str = "aaa";if (i == 1)
{
list.add(str);
}
Suggested replacement:
if (i == 1)
{
String str = "aaa";
list.add(str);
}
Exceptions are bad for performance. Throwing an exception first creates a new object, and the constructor of the Throwable interface calls a local synchronization method called fillInStackTrace(), which examines the stack and collects call trace information. Whenever an exception is thrown, the Java Virtual Machine must adjust the call stack because a new object is created during processing. Exceptions should only be used for error handling and should not be used to control program flow.
8, do not use try … catch … in the loop, it should be placed in the outermost level
Unless you have to. If you write it for no reason at all, your leader, if he or she is a little more senior and obsessive-compulsive, is going to yell at you for writing this crap.
9. If you can estimate the length of the content to be added, specify the initial length for the underlying collection and tool class implemented as an array.
For example, ArrayList, LinkedList, StringBuilder, StringBuffer, HashMap, HashSet and so on, take StringBuilder for example:
(1) StringBuilder() // Allocate 16 characters by default.
(2) StringBuilder(int size) // Allocate space for size characters by default.
(3) StringBuilder(String str) // Default allocation of 16 characters + str.length() character space
You can set the initialization capacity of a class (not just the StringBuilder above), which can significantly improve performance. For example, in the case of StringBuilder, length is the number of characters that the current StringBuilder can hold. Because when StringBuilder reaches its maximum capacity, it will increase its own capacity to 2 times the current capacity plus 2, whenever StringBuilder reaches its maximum capacity, it will have to create a new character array and copy the contents of the old character array to the new character array – this is a very performance intensive operation. This is a very performance-intensive operation. Imagine if you can predict that the character array will hold about 5000 characters without specifying the length, and the closest power of 2 to 5000 is 4096, and each expansion adds 2 whatever, then:
(1) On the basis of 4096, and then apply for 8194 size of the character array, adding up to the equivalent of an application for the size of the character array of 12,290, if you can specify the size of the character array of 5,000 at the beginning, more than double the space savings;
(2) Copy the original 4096 characters into the new character array.
This wastes memory space and reduces code efficiency. Therefore, to the underlying array implementation of the collection, tool class set a reasonable initialization capacity is not wrong, this will bring immediate effect. However, note that, such as HashMap is an array + chained table implementation of the collection, do not put the initial size and you estimate the size of the same set, because a table connected to only one object on the possibility of almost 0. Initial size is recommended to be set to the Nth power of 2, if you can estimate that there are 2,000 elements, set up as a new HashMap (128), new HashMap(256) can be.
10, when copying large amounts of data, use System.arraycopy () command11. Multiplication and division using shift operations
例如:
for (val = 0; val < 100000; val += 5)
{
a = val * 8;
b = val / 2;
}
Performance can be greatly improved by using shift operations, because at the bottom of the computer, the manipulation of bits is the easiest and fastest, so it is recommended to modify it to:
for (val = 0; val < 100000; val += 5)
{
a = val << 3;
b = val >> 1;
}
Shift operations, although fast, may make the code less comprehensible, so it is best to comment them accordingly.
例如:
for (int i = 1; i
This approach will result in count copies of Object object references existing in memory, count is very large, it will consume memory, it is recommended for the change:
Object obj = null;for (int i = 0; i
In this case, there is only one copy of Object object reference in memory, each time new Object(), Object object reference points to a different Object just, but there is only one copy of memory, which greatly saves memory space.
13, based on efficiency and type checking considerations, should be used as much as possible array, can not determine the size of the array before using ArrayList
14, try to use HashMap, ArrayList, StringBuilder, unless thread-safe needs, otherwise not recommended to use Hashtable, Vector, StringBuffer, the latter three due to the use of synchronization mechanisms that lead to a performance overhead
15, do not declare the array as public static final
Because it makes no sense, this just defines the reference as static final, the contents of the array can still be changed at will, declaring the array as public is even more of a security hole, which means that the array can be changed by external classes.
The use of a single case can reduce the burden of loading, shorten the loading time, and improve the efficiency of loading, but not all places are applicable to the single case, in short, the single case is mainly applicable to the following three aspects:
(1) Controlling the use of resources and controlling concurrent access to resources through thread synchronization
(2) Controlling the generation of instances to achieve resource conservation
(3) Control the sharing of data to allow communication between multiple unrelated processes or threads without establishing a direct association
It is important to realize that when an object is referenced by a variable defined as static, then gc usually does not reclaim the heap memory occupied by this object, for example:
public class A
{
private static B b = new B();
}
At this point, static variable b has the same life cycle as class A. If class A is not uninstalled, then the B object pointed to by reference B is resident in memory until program termination.
In order to purge sessions that are no longer active, many application servers have a default session timeout, typically 30 minutes. When the application server needs to save more sessions, if there is not enough memory, then the operating system will move some of the data to disk, and the application server may also dump some of the inactive sessions to disk based on the MRU (Most Recently Used) algorithm, or it may even throw an out-of-memory exception. If sessions are to be dumped to disk, they must first be serialized, and serializing objects is expensive in large-scale clusters. Therefore, when the session is no longer needed, the invalidate() method of HttpSession should be called to clear the session.
19. A collection that implements the RandomAccess interface, such as an ArrayList, should be traversed using the most common for loop rather than a foreach loop.
This is recommended by the JDK, and the JDK API explains the RandomAccess interface as follows: Implementing the RandomAccess interface is used to indicate support for fast random access, and the main purpose of the interface is to allow general algorithms to change its behavior in order to provide good performance when applying it to random or sequential access lists. Experience has shown that if an instance of a class that implements the RandomAccess interface is accessed randomly, it is more efficient to use a normal for loop than a foreach loop; conversely, if it is accessed sequentially, it is more efficient to use an Iterator. You can use the following code to make a judgment:
if (list instanceof RandomAccess)
{ for (int i = 0; i < list.size(); i++){}
}else{
Iterator iterator = list.iterable(); while (iterator.hasNext()){iterator.next()}
}
The underlying principle of the foreach loop is the iterator Iterator, see Java Syntax Sugar 1: Variable-Length Arguments and the Principle of the Foreach Loop. So the second half of the sentence, “Conversely, if accessed sequentially, it is more efficient to use an Iterator” means that the class instances that are accessed sequentially are traversed using the foreach loop.
This point in the multi-threaded module in the synchronized lock method block article has been made very clear, unless you can determine a whole method is required to synchronize, otherwise try to use synchronized code block, to avoid those who do not need to synchronize the code is also synchronized, affecting the efficiency of code execution.
21. Declare constants as static final and name them in uppercase
This allows these to be put into the constant pool during compilation, avoiding the need to calculate the value of the generated constant during runtime. Also, naming constants in uppercase makes it easier to distinguish constants from variables
22. Do not create some unused objects, do not import some unused classes
This makes no sense, if the code has “The value of the local variable i is not used”, “The import java.util is never used “, then remove them.
For, see Reflection. Reflection is a very powerful feature that Java provides to its users; powerful often means inefficient. It is not recommended to use reflection, especially the Method’s invoke method, very often during program execution. If it is necessary, a recommended practice is to instantiate the classes that need to be loaded by reflection and put them into memory at project startup – the user only cares about getting the fastest possible response time when interacting with the other end. The user only cares about getting the fastest response time when interacting with the other end, not how long it takes for the other end to start the project.
Both pools are used to reuse objects, the former to avoid frequent opening and closing of connections and the latter to avoid frequent creation and destruction of threads
Input and output streams with buffering, i.e. BufferedReader, BufferedWriter, BufferedInputStream, BufferedOutputStream, which can greatly improve IO efficiency
26, sequential insertion and random access to the more scenarios using ArrayList, element deletion and insertion in the middle of the more scenarios using LinkedList
This, understand the principle of ArrayList and LinkedList know
There are two main disadvantages of giving too many formal parameters to public methods, i.e., methods that are available to the public:
1, in violation of the object-oriented programming ideas, Java is all about objects, too many formal parameters, and object-oriented programming ideas do not fit!
2, too many parameters will inevitably lead to an increase in the probability of error method calls
As for the “too many” refers to how many, 3 or 4 it. For example, we use JDBC to write an insertStudentInfo method, there are 10 student information fields to be inserted in the Student table, you can encapsulate the 10 parameters in an entity class, as the insert method of the formal parameter.
28, string variables and string constants equals when the string constant will be written before the string constant
This is a relatively common tip now, if the following code is available:
String str = "123";if (str.equals("123")) {...}
Suggested revision:
String str = "123";if ("123".equals(str))
{...}
The main reason for doing this is to avoid null pointer exceptions.
29. Please know that there is no difference between if (i == 1) and if (1 == i) in java, but the former is recommended from a reading habit point of view
People usually ask if there’s a difference between “if (i == 1)” and “if (1== i)”, and that starts with C/C++.
In C/C++, “if (i == 1)” determines that the condition is valid in terms of 0 vs. non-0, with 0 indicating false and non-0 indicating true, if there is such a code:
int i = 2;if (i == 1)
{...}else{...}
C/C++ determines that “i==1″ does not hold, so it is represented as 0, i.e. false. but if:
int i = 2;if (i = 1) { ... }else{ ... }
In case the programmer is not careful and writes “if (i == 1)” as “if (i = 1)”, there is a problem. This situation is very likely to happen in the development of C/C++ and will lead to some difficult to understand errors, so in order to avoid incorrect assignment operations in the if statement, it is recommended to write the if statement as follows: “if (i == 1)” as “if (i = 1)”. statement is written as:
int i = 2;if (1 == i) { ... }else{ ... }
This way, even if the developer accidentally writes “1 = i”, the C/C++ compiler will be able to check it at the first time, because we can assign i to a variable, but we can’t assign 1 to a constant.
However, in Java, the C/C++ “if (i = 1)” syntax is not possible, because if you write this syntax, Java will compile with the error “Type mismatch: cannot convert from int to boolean”. However, although there is no semantic difference between Java’s “if (i == 1)” and “if (1 == i)”, it is better to use the former from a reading perspective.
Look at what is printed out using toString() on an array:
public static void main(String[] args)
{ int[] is = new int[]{1, 2, 3};
System.out.println(is.toString());
}
The result:
[I@18a992f
The intention is to print out the contents of the array, but there is a possibility that the array reference is null, resulting in a null pointer exception. However, although the array toString () does not make sense, but the collection toString () is able to print out the contents of the collection, because the collection of the parent class AbstractCollections overrides the Object toString () method.
This will never get the desired result:
public static void main(String[] args)
{
long l = 12345678901234L;int i = (int)l;
System.out.println(i);
}
We might have expected to get some of these, but it turned out to be:
1942892530
Explain. long in Java is 8 bytes and 64 bits, so 12345678901234 should be represented in the computer:
0000 0000 0000 0000 0000 1011 0011 1010 0111 0011 1100 1110 0010 1111 1111 0010
An int-type data is 4 bytes of 32 bits, the first 32 bits of the above string of binary data taken from the lower bit are:
0111 0011 1100 1110 0010 1111 1111 0010
This string is represented in binary as decimal 1942892530, so that’s what we output on the console above. There are two other conclusions to be drawn in passing from this example:
1, the default data type of integer is int, long l = 12345678901234L, this number is out of the range of int, so there is a L at the end, indicating that this is a long number. By the way, the default type of a float type is double, so define float by writing “”float f = 3.5f””
2, then write a sentence “int ii = l + i;” will report an error, because long + int is a long, can not be assigned to int
32, the public collection of data not used in the class must be removed in a timely manner
If a collection class is public (i.e., not a property inside a method), then the elements of the collection will not be automatically freed, because there will always be references to them. So, if some data in a public collection is not used and not removed, then the public collection will grow in size, making the system vulnerable to memory leaks.
33, a basic data type to a string, basic data type.toString () is the fastest way, String.valueOf (data) second, data + “” slowest
Turn a basic data type to general there are three ways, I have an Integer type data i, you can use i.toString (), String.valueOf (i), i + “” three ways, three ways of efficiency, look at a test:
public static void main(String[] args)
{
int loopTime = 50000;
Integer i = 0; long startTime = System.currentTimeMillis(); for (int j = 0; j < loopTime; j++)
{
String str = String.valueOf(i);
}
System.out.println("String.valueOf():" + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis(); for (int j = 0; j < loopTime; j++)
{
String str = i.toString();
}
System.out.println("Integer.toString():" + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis(); for (int j = 0; j < loopTime; j++)
{
String str = i + "";
}
System.out.println("i + \"\":" + (System.currentTimeMillis() - startTime) + "ms");
}
The results of the run are:
String.valueOf():11ms Integer.toString():5ms i + "":25ms
So in the future, when you encounter a basic data type to String, you should prioritize the use of the toString() method. As for why, it’s simple:
1, String.valueOf () method underlying the call to the Integer.toString () method, but will do before the call null judgment
2, Integer.toString () method is not to say, directly call the
3, i + “” underlying the use of StringBuilder implementation, the first append method to splice, and then use the toString () method to get the string
When comparing the three, it’s clear that 2 is the fastest, 1 is second, and 3 is the slowest
There are many ways to traverse the Map, usually the scenario we need is to traverse the Key and Value in the Map, then the recommended and most efficient way to use is:
public static void main(String[] args)
{
HashMap hm = new HashMap();
hm.put("111", "222");Set> entrySet = hm.entrySet();
Iterator> iter = entrySet.iterator(); while (iter.hasNext())
{
Map.Entry entry = iter.next();
System.out.println(entry.getKey() + "\t" + entry.getValue());
}
}
If you just want to iterate through the key values of the map, then “Set keySet = hm.keySet();” would be more appropriate.
Meaning, for example, I have this piece of code:
try{
XXX.close();
YYY.close();
}catch (Exception e)
{...}
Suggested revision:
try{ XXX.close(); }catch (Exception e) { ... }try{ YYY.close(); }catch (Exception e) { ... }
It’s a bit of a pain in the ass, but it prevents resource leaks. I think, if there is no modified code, in case XXX.close() throws an exception, then it enters the cath block, YYY.close() won’t be executed, and the resource YYY won’t be reclaimed, and it will keep occupying it, so there are many codes, it is possible to cause resource handle leakage. After changing to the above, it is guaranteed that XXX and YYY will be closed no matter what.