takeaway

There are only two kinds of substances: high efficiency and low efficiency; There are only two kinds of people: efficient people and inefficient people. – George Bernard shaw
Similarly, there are only two types of code: efficient code and inefficient code; There are only two kinds of people in the world: those who write efficient code and those who write inefficient code. How to write efficient code is a major problem facing every r&d team. Therefore, according to the actual experience, the author consulted a lot of information, summed up the “Java efficient code 50 cases “, so that every Java programmer can write “efficient code”.

1. Constants & variables

1.1. Assigning constant values directly disallows declaring new objects

Assigning a constant value directly simply creates an object reference that points to the constant value.

Example:

Long i = new Long(1L);
String s = new String("abc");Copy the code
Is:

Long i = 1L;
String s = "abc";Copy the code

1.2. When the value of a member variable does not need to change, try to define it as a static constant

In each object instance of a class, there is a copy of each member variable, whereas there is only one instance of a member static constant.

Example:

public class HttpConnection { private final long timeout = 5L; . }Copy the code
Is:

public class HttpConnection { private static final long TIMEOUT = 5L; . }Copy the code

1.3. Use basic data types as far as possible to avoid automatic packing and unpacking

Java basic data types double, float, long, int, short, char, Boolean, corresponding to the wrapper classes double, float, long, Integer, short, Character, Boolean, respectively. The JVM supports automatic conversions of base types to their corresponding wrapper classes, known as automatic boxing and unboxing. Packing and unpacking require CPU and memory resources, so avoid automatic packing and unpacking.

Example:

Integer sum = 0; int[] values = ... ;for(int value : values) { sum += value; Result = integer.valueof (result.intValue() + value); }Copy the code
Is:

int sum = 0; int[] values = ... ;for (int value : values) {
    sum += value;
}Copy the code

1.4. There is no need to assign an initial value to a variable if the initial value will be overwritten

Example:

List<UserDO> userList = new ArrayList<>();
if (isAll) {
    userList = userDAO.queryAll();
} else {
    userList = userDAO.queryActive();
}Copy the code
Is:

List<UserDO> userList;
if (isAll) {
    userList = userDAO.queryAll();
} else {
    userList = userDAO.queryActive();
}Copy the code

1.5. Use primitives as temporary variables as possible within functions

In functions, parameters of basic types and temporary variables are stored in the Stack, which is fast to access. Object type parameters and references to temporary variables are stored in the Stack, and the content is stored in the Heap, which is slow to access. In a class, member variables of any type are stored in the Heap and are accessed slowly.

Example:

Public Final Class Accumulator {private double Result = 0.0d; public void addAll(@NonNull double[] values) {for(double value : values) { result += value; }}... }Copy the code
Is:

Public Final Class Accumulator {private double Result = 0.0d; Public void addAll(@nonnull double[] values) {double sum = 0.0d;for(double value : values) { sum += value; } result += sum; }... }Copy the code

1.6. Try not to define variables outside the circulation

In the old JDK, it was recommended to “try not to define variables in the body of the loop”, but this has been optimized in the new JDK. After compiling bytecode analysis, there is no essential difference between variable definitions outside the loop and in the loop, and the efficiency is basically the same. On the contrary, according to the principle of “local variable scope minimization”, the definition of variables in the loop is more scientific and easier to maintain, avoiding the delay of recycling caused by extending the life cycle of large objects.

Example:

UserVO userVO; List<UserDO> userDOList = ... ; List<UserVO> userVOList = new ArrayList<>(userDOList.size());for(UserDO userDO : userDOList) { userVO = new UserVO(); userVO.setId(userDO.getId()); . userVOList.add(userVO); }Copy the code
Is:

List<UserDO> userDOList = ... ; List<UserVO> userVOList = new ArrayList<>(userDOList.size());for(UserDO userDO : userDOList) { UserVO userVO = new UserVO(); userVO.setId(userDO.getId()); . userVOList.add(userVO); }Copy the code

1.7. Immutable static constants. Use non-thread-safe classes whenever possible

Immutable static constants, although required to support multithreaded access, can also use non-thread-safe classes.

Example:

public static final Map<String, Class> CLASS_MAP;
static {
    Map<String, Class> classMap = new ConcurrentHashMap<>(16);
    classMap.put("VARCHAR", java.lang.String.class); . CLASS_MAP = Collections.unmodifiableMap(classMap); }Copy the code
Is:

public static final Map<String, Class> CLASS_MAP;
static {
    Map<String, Class> classMap = new HashMap<>(16);
    classMap.put("VARCHAR", java.lang.String.class); . CLASS_MAP = Collections.unmodifiableMap(classMap); }Copy the code

1.8. Immutable member variables. Use non-thread-safe classes whenever possible

Immutable member variables, although required to support multithreaded access, can also use non-thread-safe classes.

Example:

@Service
public class StrategyFactory implements InitializingBean {
    @Autowired
    private List<Strategy> strategyList;
    private Map<String, Strategy> strategyMap;
    @Override
    public void afterPropertiesSet() {
        if(CollectionUtils isNotEmpty (strategyList)) {int size = (int) Math. Ceil (strategyList. The size () * 4.0/3); Map<String, Strategy> map = new ConcurrentHashMap<>(size);for(Strategy strategy : strategyList) { map.put(strategy.getType(), strategy); } strategyMap = Collections.unmodifiableMap(map); }}... }Copy the code
Is:

@Service
public class StrategyFactory implements InitializingBean {
    @Autowired
    private List<Strategy> strategyList;
    private Map<String, Strategy> strategyMap;
    @Override
    public void afterPropertiesSet() {
        if(CollectionUtils isNotEmpty (strategyList)) {int size = (int) Math. Ceil (strategyList. The size () * 4.0/3); Map<String, Strategy> map = new HashMap<>(size);for(Strategy strategy : strategyList) { map.put(strategy.getType(), strategy); } strategyMap = Collections.unmodifiableMap(map); }}... }Copy the code

2. Objects & Classes

2.1. Do not convert objects using JSON

JSON provides the ability to convert objects to JSON strings and JSON strings to objects, and is therefore used by some people to convert objects. This method of object conversion, while functional, is not problematic, but performance is.

Example:

List<UserDO> userDOList = ... ; List<UserVO> userVOList = JSON.parseArray(JSON.toJSONString(userDOList), UserVO.class);Copy the code
Is:

List<UserDO> userDOList = ... ; List<UserVO> userVOList = new ArrayList<>(userDOList.size());for(UserDO userDO : userDOList) { UserVO userVO = new UserVO(); userVO.setId(userDO.getId()); . userVOList.add(userVO); }Copy the code

2.2. Try not to use reflection assignment objects

The main advantage of using reflection to assign objects is that it saves code, but the main disadvantage is that it reduces performance.

Example:

List<UserDO> userDOList = ... ; List<UserVO> userVOList = new ArrayList<>(userDOList.size());for (UserDO userDO : userDOList) {
    UserVO userVO = new UserVO();
    BeanUtils.copyProperties(userDO, userVO);
    userVOList.add(userVO);
}Copy the code
Is:

List<UserDO> userDOList = ... ; List<UserVO> userVOList = new ArrayList<>(userDOList.size());for(UserDO userDO : userDOList) { UserVO userVO = new UserVO(); userVO.setId(userDO.getId()); . userVOList.add(userVO); }Copy the code

2.3. Replace internal anonymous classes with Lambda expressions

For most students new to JDK8, Lambda expressions are the syntax-candy of anonymous inner classes. In fact, Lambda expressions are implemented in most virtual machines using invokeDynamic instructions, which are more efficient than anonymous inner classes.

Example:

List<User> userList = ... ; Collections.sort(userList, new Comparator<User>() { @Override public int compare(User user1, User user2) { Long userId1 = user1.getId(); Long userId2 = user2.getId(); .returnuserId1.compareTo(userId2); }});Copy the code
Is:

List<User> userList = ... ; Collections.sort(userList, (user1, user2) -> { Long userId1 = user1.getId(); Long userId2 = user2.getId(); .return userId1.compareTo(userId2);
});Copy the code

2.4. Try to avoid defining unnecessary subclasses

One more class requires one more class load, so try to avoid defining unnecessary subclasses.

Example:

public static final Map<String, Class> CLASS_MAP =
    Collections.unmodifiableMap(new HashMap<String, Class>(16) {
    private static final long serialVersionUID = 1L;
    {
        put("VARCHAR", java.lang.String.class); }});Copy the code
Is:

public static final Map<String, Class> CLASS_MAP;
static {
    Map<String, Class> classMap = new HashMap<>(16);
    classMap.put("VARCHAR", java.lang.String.class); . CLASS_MAP = Collections.unmodifiableMap(classMap); }Copy the code

2.5. Specify final modifiers for classes whenever possible

Specifying a final modifier for a class makes it uninheritable. If you specify a class as final, then all of its methods are final, and the Java compiler looks for opportunities to inline all final methods. For details, see Java Runtime Optimization, inlining can increase performance by an average of 50%.

Example:

public class DateHelper {
    ...
}Copy the code
Is:

public final class DateHelper {
    ...
}Copy the code
Note: When using Spring’s AOP features, beans need to be dynamically proxyed, which will result in an exception if final decorations are added to the Bean class.

Method 3.

Declare static methods that are independent of class member variables

The advantage of static methods is that they can be called directly without generating an instance of the class. A static method no longer belongs to an object, but to its class. It can be accessed only by its class name, and there is no need to consume resources to repeatedly create objects. Even private methods inside a class should be declared static if they do not use a class member variable.

Example:

public int getMonth(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    return calendar.get(Calendar.MONTH) + 1;
}Copy the code
Is:

public static int getMonth(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    return calendar.get(Calendar.MONTH) + 1;
}Copy the code

3.2. Try to use basic data types as method parameter types to avoid unnecessary boxing, unboxing and null pointer judgment

Example:

public static double sum(Double value1, Double value2) {
    double double1 = Objects.isNull(value1) ? 0.0D : value1;
    double double2 = Objects.isNull(value2) ? 0.0D : value2;
    return double1 + double2;
}
double result = sum(1.0D, 2.0D);Copy the code
Is:

public static double sum(double value1, double value2) {
    return value1 + value2;
}
double result = sum(1.0D, 2.0D);Copy the code

3.3. Use primitive data types as method return value types to avoid unnecessary boxing, unboxing, and null pointer judgment

In JDK class library methods, many methods return values using primitive data types, first to avoid unnecessary boxing and unboxing, and second to avoid null pointer judgment of return values. Examples include collection.isempty () and map.size ().

Example:

public static Boolean isValid(UserDO user) {
    if (Objects.isNull(user)) {
        return false;
    }
    returnBoolean.TRUE.equals(user.getIsValid()); } // call code UserDO user =... ; Boolean isValid = isValid(user);if (Objects.nonNull(isValid) && isValid.booleanValue()) { 
    ...
}Copy the code
Is:

public static boolean isValid(UserDO user) {
    if (Objects.isNull(user)) {
        return false;
    }
    returnBoolean.TRUE.equals(user.getIsValid()); } // call code UserDO user =... ;if (isValid(user)) {
    ...
}Copy the code

3.4. Protocol method parameter values are non-null to avoid unnecessary null pointer judgment

Protocol programming, can be @nonNULL and @nullable annotation parameters, whether to comply with the call is entirely conscious.

Example:

public static boolean isValid(UserDO user) {
    if (Objects.isNull(user)) {
        return false;
    }
    return Boolean.TRUE.equals(user.getIsValid());
}Copy the code
Is:

public static boolean isValid(@NonNull UserDO user) {
    return Boolean.TRUE.equals(user.getIsValid());
}Copy the code

3.5. The protocol method returns a non-null value to avoid unnecessary null pointer judgment

Protocol programming, @nonNULL and @nullable annotation parameters, whether to follow the implementation of the conscious.

Example:

Public interface OrderService {List<OrderVO> queryUserOrder(Long userId); } / / calling code List < OrderVO > orderList. = the orderService queryUserOrder (userId);if (CollectionUtils.isNotEmpty(orderList)) {
    for(OrderVO order : orderList) { ... }}Copy the code
Is:

Public interface OrderService {@nonNULL public List<OrderVO> queryUserOrder(Long userId); } / / calling code List < OrderVO > orderList. = the orderService queryUserOrder (userId);for (OrderVO order : orderList) {
    ...
}Copy the code

3.6. The called method already supports null processing, and the calling method does not need to perform null processing

Example:

UserDO user = null;
if (StringUtils.isNotBlank(value)) {
    user = JSON.parseObject(value, UserDO.class);
}Copy the code
Is:

UserDO user = JSON.parseObject(value, UserDO.class);Copy the code

3.7. Try to avoid unnecessary function encapsulation

Method calls cause loading and unloading, consuming more CPU and memory, and unnecessary function encapsulation should be avoided as much as possible. Of course, the performance penalty of adding a few method calls is worth it to make your code cleaner, cleaner, and more maintainable.

Example:

Public static Boolean isVip(Boolean isVip) {returnBoolean.TRUE.equals(isVip); } // Use code Boolean isVip = isVip(user.getvip ());Copy the code
Is:

boolean isVip = Boolean.TRUE.equals(user.getVip());Copy the code

3.8. Specify final modifiers for methods whenever possible

Methods specify final modifiers to prevent methods from being overridden, and the Java compiler looks for opportunities to inline all final methods. For details, see Java Runtime Optimization, inlining can increase performance by an average of 50%.

Note: All private methods implicitly specify a final modifier, so you do not need to specify a final modifier for them.

Example:

public class Rectangle {
    ...
    public double area() {... }}Copy the code
Is:

public class Rectangle {
    ...
    public final double area() {... }}Copy the code
Note: When using Spring’s AOP features, beans need to be dynamically proxied, and methods with final modifications will not be proxied.

4. The expression

4.1. Minimize the repetition of method calls

Example:

List<UserDO> userList = ... ;for (int i = 0; i < userList.size(); i++) {
    ...
}Copy the code
Is:

List<UserDO> userList = ... ; int userLength = userList.size();for (int i = 0; i < userLength; i++) {
    ...
}Copy the code

4.2. Try to avoid unnecessary method calls

Example:

List<UserDO> userList = userDAO.queryActive();
if (isAll) {
    userList = userDAO.queryAll();
}Copy the code
Is:

List<UserDO> userList;
if (isAll) {
    userList = userDAO.queryAll();
} else {
    userList = userDAO.queryActive();
}Copy the code

4.3. Use shifts instead of positive integer multiplication and division whenever possible

Performance can be greatly improved with a shift operation. For positive integer calculations of multiplication and division by 2^n(where n is a positive integer), a shift operation can be used instead.

Example:

int num1 = a * 4;
int num2 = a / 4;Copy the code
Is:

int num1 = a << 2;
int num2 = a >> 2;Copy the code

4.4. Extract common expressions to avoid double calculation

Extract the common expression, evaluate the value only once, and then reuse the value.

Example:

double distance = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));Copy the code
Is:

double dx = x2 - x1; double dy = y2 - y1; double distance = Math.sqrt(dx * dx + dy * dy); SQRT (math.pow (x2 - x1, 2) + math.pow (y2 - y1, 2));Copy the code

4.5. Try not to use conditional expressions! The not

Use! The inverse will be computed one more time, and optimized out if not necessary.

Example:

if(! (a >= 10)) { ... // 1}else{... // 2}Copy the code
Is:

if(a < 10) { ... // 1}else{... // 2}Copy the code

4.6. For multi-constant branch selection, use switch statements rather than if-else statements

If-else statements, each if condition statement is evaluated until the if condition statement is true. The switch statement is optimized for jump. Tableswitch or lookupswitch instruction is used in Java. The branch processing efficiency is higher for multi-constant. The experiment proves that when the probability of each branch is the same, the if-else statement is more efficient when the number of branches is lower than 5, and the switch statement is more efficient when the number of branches is higher than 5.

Example:

if(i == 1) { ... ; // branch 1}else if(i == 2) { ... ; // branch 2}else if(i == ...) {... ; // branch n}else{... ; // branch n+1}Copy the code
Is:

switch (i) {
    case1:... / / branch 1break;
    case2:... / / branch 2break;
    case. :... / / nbreak; default : ... / / branch n + 1break;
}Copy the code
Note: If the service is complex, you can use Map to implement the policy mode.

5. The string

5.1. Try not to use regular expression matching

The efficiency of regular expression matching is low. Therefore, string matching is recommended.

Example:

String source = "a::1,b::2,c::3,d::4";
String target = source.replaceAll("... ""."=");
Stringp[] targets = source.spit("... "");Copy the code
Is:

String source = "a::1,b::2,c::3,d::4";
String target = source.replace("... ""."=");
Stringp[] targets = StringUtils.split(source."... "");Copy the code

5.2. Replace strings with characters whenever possible

The length of a string is uncertain, but the length of a character is fixed at 1, so lookups and matches are naturally more efficient.

Example:

String source = "a:1,b:2,c:3,d:4";
int index = source.indexOf(":");
String target = source.replace(":"."=");Copy the code
Is:

String source = "a:1,b:2,c:3,d:4";
int index = source.indexOf(':');
String target = source.replace(':'.'=');Copy the code

5.3. Try to use StringBuilder for string concatenation

String is final and its contents cannot be modified, so each String concatenation generates a new object. The StringBuilder allocates a chunk of memory for initialization, where subsequent string concatenation is performed, without allocating new memory or generating new objects.

Example:

String s = "";
for (int i = 0; i < 10; i++) {
    if(i ! = 0) { s +=', ';
    }
    s += i;
}Copy the code
Is:

StringBuilder sb = new StringBuilder(128);
for (int i = 0; i < 10; i++) {
    if(i ! = 0) { sb.append(', ');
    }
    sb.append(i);
}Copy the code

5.4. Do not use “”+ to convert strings

Use “”+ to convert strings, which is convenient but inefficient. You are advised to use String.valueof.

Example:

int i = 12345;
String s = "" + i;Copy the code
Is:

int i = 12345;
String s = String.valueOf(i);Copy the code

An array of 6.

6.1. Do not copy arrays in a loop. Use System. Arraycopy instead

System. Arraycopy is recommended. You can also copy Arrays using array.copyof.

Example:

int[] sources = new int[] {1, 2, 3, 4, 5};
int[] targets = new int[sources.length];
for (int i = 0; i < targets.length; i++) {
    targets[i] = sources[i];
}Copy the code
Is:

int[] sources = new int[] {1, 2, 3, 4, 5};
int[] targets = new int[sources.length];
System.arraycopy(sources, 0, targets, 0, targets.length);Copy the code

6.2. When converting a collection to an array of type T, try to pass in an empty array T[0]

There are two forms for converting collections to arrays: toArray(new T[n]) and toArray(new T[0]). In older Java versions, toArray(new T[n]) was recommended because the reflection calls required to create an array were very slow. After OpenJDK6, reflection calls are built-in, resulting in performance improvements that toArray(new T[0]) is more efficient than toArray(new T[n]). In addition, toArray(new T[n]) obtains the list size one more time than toArray(new T[0]). If the calculation of the list size takes too long, the efficiency of toArray(New T[n]) will also be reduced.

Example:

List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, ...) ; Integer[] integers =integerList.toArray(new Integer[integerList.size()]);Copy the code
Is:

List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, ...) ; Integer[] integers =integerList.toArray(new Integer[0]); // Do not use new Integer[]{}Copy the code
Suggestion: Collections should provide a toArray(Class

clazz) method to avoid useless empty array initialization (new T[0]).

6.3. When converting collections to Object arrays, use the toArray() method whenever possible

ToArray [new Object[0]] is not necessary; toArray() can be used directly. Type judgments are avoided, and empty array requests are avoided, so efficiency is higher.

Example:

List<Object> objectList = Arrays.asList(1, "2", 3, "4", 5,...). ; Object[] objects = objectList.toArray(new Object[0]);Copy the code
Is:

List<Object> objectList = Arrays.asList(1, "2", 3, "4", 5,...). ; Object[] objects = objectList.toArray();Copy the code

Collection of 7.

7.1. When initializing a collection, try to specify the size of the collection

When the Java collection is initialized, a default size is specified. If the default size no longer meets the data requirements, the Java collection will be expanded. Each expansion time may be O(n). Therefore, it is possible to specify the predicted size of the collection to avoid or reduce the number of expansion of the collection.

Example:

List<UserDO> userDOList = ... ; Set<Long> userSet = new HashSet<>(); Map<Long, UserDO> userMap = new HashMap<>(); List<UserVO> userList = new ArrayList<>();for (UserDO userDO : userDOList) {
    userSet.add(userDO.getId());
    userMap.put(userDO.getId(), userDO);
    userList.add(transUser(userDO));
}Copy the code
Is:

List<UserDO> userDOList = ...;
int userSize = userDOList.size();
Set<Long> userSet = new HashSet<>(userSize);
Map<Long, UserDO> userMap = new HashMap<>((int) Math.ceil(userSize * 4.0 / 3));
List<UserVO> userList = new ArrayList<>(userSize);
for (UserDO userDO : userDOList) {
    userSet.add(userDO.getId());
    userMap.put(userDO.getId(), userDO);
    userList.add(transUser(userDO));
}Copy the code

7.2. Do not copy collections in a loop. Try to copy collections using methods provided by the JDK

The JDK provides methods to specify the size of a collection in one step, avoiding the time and space waste of multiple expansions. At the same time, the System. Arraycopy method is also called at the bottom of these methods, which makes the batch copy of data more efficient.

Example:

List<UserDO> user1List = ... ; List<UserDO> user2List = ... ; List<UserDO> userList = new ArrayList<>(user1List.size() + user2List.size());for (UserDO user1 : user1List) {
    userList.add(user1);
}
for (UserDO user2 : user2List) {
    userList.add(user2);
}Copy the code
Is:

List<UserDO> user1List = ... ; List<UserDO> user2List = ... ; List<UserDO> userList = new ArrayList<>(user1List.size() + user2List.size()); userList.addAll(user1List); userList.addAll(user2List);Copy the code

7.3. Use Arrays. AsList to convert Arrays to lists whenever possible

The principle is similar to “don’t copy collections in a loop, try to copy collections using methods provided by the JDK”.

Example:

List<String> typeList = new ArrayList<>(8);
typeList.add("Short");
typeList.add("Integer");
typeList.add("Long"); String[] names = ... ; List<String> nameList = ... ;for (String name : names) {
    nameList.add(name);
}Copy the code
Is:

List<String> typeList = Arrays.asList("Short"."Integer"."Long"); String[] names = ... ; List<String> nameList = ... ; nameList.addAll(Arrays.asList(names));Copy the code

7.4. Iterate directly over the collection to be used

Iterate directly over the collection you want to use without having to do anything else to get the data.

Example:

Map<Long, UserDO> userMap = ... ;for(Long userId : userMap.keySet()) { UserDO user = userMap.get(userId); . }Copy the code
Is:

Map<Long, UserDO> userMap = ... ;for(Map.Entry<Long, UserDO> userEntry : userMap.entrySet()) { Long userId = userEntry.getKey(); UserDO user = userEntry.getValue(); . }Copy the code

7.5. Do not use the size method to detect empty. You must use the isEmpty method to detect empty

Using the size method to detect empty logic is fine, but using the isEmpty method makes the code more readable and gives better performance. Any isEmpty method implementation has a time complexity of O(1), but some size method implementations may have a time complexity of O(n).

Example:

List<UserDO> userList = ... ;if(userList.size() == 0) { ... } Map<Long, UserDO> userMap = ... ;if (userMap.size() == 0) {
    ...
}Copy the code
Is:

List<UserDO> userList = ... ;if(userList.isEmpty()) { ... } Map<Long, UserDO> userMap = ... ;if (userMap.isEmpty()) {
    ...
}Copy the code

7.6. For non-random access List, try to use iteration instead of random access

For the list, can be divided into RandomAccess and non-random access two categories, can be used to realize RandomAccess interface to judge. Random access list, directly through get data does not affect the efficiency. Instead of randomly accessing lists, getting data through GET is extremely inefficient.

Example:

LinkedList<UserDO> userDOList = ... ; int size = userDOList.size();for(int i = 0; i < size; i++) { UserDO userDO = userDOList.get(i); . }Copy the code
Is:

LinkedList<UserDO> userDOList = ... ;for (UserDO userDO : userDOList) {
    ...
}Copy the code
In fact, the list should be iterated whether it supports random access or not.

7.7. Use HashSet whenever possible to determine the presence of values

In the Java collection library, the general time complexity of the contains method of List is O(n), while the time complexity of HashSet is O(1). If you need to call the Contains method frequently to find data, you can first convert the List into a HashSet.

Example:

List<Long> adminIdList = ... ; List<UserDO> userDOList = ... ; List<UserVO> userVOList = new ArrayList<>(userDOList.size());for (UserDO userDO : userDOList) {
    if(adminIdList.contains(userDO.getId())) { userVOList.add(transUser(userDO)); }}Copy the code
Is:

Set<Long> adminIdSet = ... ; List<UserDO> userDOList = ... ; List<UserVO> userVOList = new ArrayList<>(userDOList.size());for (UserDO userDO : userDOList) {
    if(adminIdSet.contains(userDO.getId())) { userVOList.add(transUser(userDO)); }}Copy the code

7.8. Avoid determining existence before obtaining

If you need to determine existence before obtaining, you can directly obtain and determine null, thus avoiding the second search operation.

Example:

public static UserVO transUser(UserDO user, Map<Long, RoleDO> roleMap) { UserVO userVO = new UserVO(); userVO.setId(user.getId()); .if(roleMap.contains(user.getRoleId())) { RoleDO role = roleMap.get(user.getRoleId()); userVO.setRole(transRole(role)); }}Copy the code
Is:

public static UserVO transUser(UserDO user, Map<Long, RoleDO> roleMap) { UserVO userVO = new UserVO(); userVO.setId(user.getId()); . RoleDO role = roleMap.get(user.getRoleId());if(Objects.nonNull(role)) { userVO.setRole(transRole(role)); }}Copy the code

Abnormal 8.

8.1. Catch the corresponding exception directly

Directly capture the corresponding exception, avoid using instanceof judgment, higher efficiency and more concise code.

Example:

try {
    saveData();
} catch (Exception e) {
    if (e instanceof IOException) {
        log.error("Saving data I/O exception", e);
    } else {
        log.error("Save data other exception", e); }}Copy the code
Is:

try {
    saveData();
} catch (IOException e) {
    log.error("Saving data I/O exception", e);
} catch (Exception e) {
    log.error("Save data other exception", e);
}Copy the code

8.2. Try to avoid catching exceptions in the loop

There is no need to catch an exception in the body of the loop when it has thrown an exception without the loop continuing. Because too many exceptions will reduce the efficiency of program execution.

Example:

Public Double sum(List<String> valueList) {Double sum = 0.0D;for (String value : valueList) {
        try {
            sum += Double.parseDouble(value);
        } catch (NumberFormatException e) {
            returnnull; }}return sum;
}Copy the code
Is:

Public Double sum(List<String> valueList) {Double sum = 0.0D; try {for (String value : valueList) {
            sum += Double.parseDouble(value);
        }
    } catch (NumberFormatException e) {
        return null;
    }
    return sum;
}Copy the code

8.3. Disable the use of exception control business processes

Compared to conditional expressions, exception processing is less efficient.

Example:

public static boolean isValid(UserDO user) {
    try {
        return Boolean.TRUE.equals(user.getIsValid());
    } catch(NullPointerException e) {
        return false; }}Copy the code
Is:

public static boolean isValid(UserDO user) {
    if (Objects.isNull(user)) {
        return false;
    }
    return Boolean.TRUE.equals(user.getIsValid());
}Copy the code

9. The buffer

9.1. Try to specify the buffer size during initialization

During initialization, you can specify the expected capacity of the buffer to avoid wasting time and space.

Example:

StringBuffer buffer = new StringBuffer();
StringBuilder builder = new StringBuilder();Copy the code
Is:

StringBuffer buffer = new StringBuffer(1024);
StringBuilder builder = new StringBuilder(1024);Copy the code

9.2. Try to reuse the same buffer

For buffers, the Java virtual machine takes time to generate objects and time to do garbage collection. So, reuse buffers as much as possible.

Example:

StringBuilder builder1 = new StringBuilder(128);
builder1.append("update t_user set name = '").append(userName).append("' where id = ").append(userId);
statement.executeUpdate(builder1.toString());
StringBuilder builder2 = new StringBuilder(128);
builder2.append("select id, name from t_user where id = ").append(userId); ResultSet resultSet = statement.executeQuery(builder2.toString()); .Copy the code
Is:

StringBuilder builder = new StringBuilder(128);
builder.append("update t_user set name = '").append(userName).append("' where id = ").append(userId);
statement.executeUpdate(builder.toString());
builder.setLength(0);
builder.append("select id, name from t_user where id = ").append(userId); ResultSet resultSet = statement.executeQuery(builder.toString()); .Copy the code
The setLength method is used to start the buffer from 0 again.

9.3. Try to use the same buffer by design

In order to improve the efficiency of the program, the same buffer is designed as far as possible.

Example:

Public static String toXml(UserDO) {StringBuilder Builder = new StringBuilder(128); builder.append("<UserDO>");
    builder.append(toXml(user.getId()));
    builder.append(toXml(user.getName()));
    builder.append(toXml(user.getRole()));
    builder.append("</UserDO>");
    returnbuilder.toString(); } public static String toXml(Long value) {StringBuilder Builder = new StringBuilder(128); builder.append("<Long>");
    builder.append(value);
    builder.append("</Long>");
    returnbuilder.toString(); }... // Use the code UserDO user =... ; String xml = toXml(user);Copy the code
Is:

Public static void toXml(StringBuilder Builder, UserDO user) {builder.append("<UserDO>");
    toXml(builder, user.getId());
    toXml(builder, user.getName());
    toXml(builder, user.getRole());
    builder.append("</UserDO>"); } // Convert XML(Long) public static void toXml(StringBuilder Builder, Long value) {builder.append("<Long>");
    builder.append(value);
    builder.append("</Long>"); }... // Use the code UserDO user =... ; StringBuilder builder = new StringBuilder(1024); toXml(builder, user); String xml = builder.toString();Copy the code
Remove the buffer request from each transform method and apply a buffer for each transform method. In terms of time, it saves a lot of buffer application release time. In terms of space, it saves a lot of temporary storage space for buffers.

9.4. Minimize IO operations by buffering streams

BufferedReader, BufferedWriter, BufferedInputStream, and BufferedOutputStream can greatly reduce I/O times and improve I/O speed.

Example:

try (FileInputStream input = new FileInputStream("a");
    FileOutputStream output = new FileOutputStream("b")) {
    int size = 0;
    byte[] temp = new byte[1024];
    while((size = input.read(temp)) ! = -1) { output.write(temp, 0, size); } } catch (IOException e) { log.error("Failed to copy file", e);
}Copy the code
Is:

try (BufferedInputStream input = new BufferedInputStream(new FileInputStream("a"));
    BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream("b"))) {
    int size = 0;
    byte[] temp = new byte[1024];
    while((size = input.read(temp)) ! = -1) { output.write(temp, 0, size); } } catch (IOException e) { log.error("Failed to copy file", e);
}Copy the code
You can manually specify the buffer flow size based on actual conditions to maximize the buffering effect of the buffer flow.

Thread 10.

10.1. Use non-thread-safe classes whenever possible in a single thread

Using non-thread-safe classes avoids unnecessary synchronization overhead.

Example:

StringBuffer buffer = new StringBuffer(128);
buffer.append("select * from ").append(T_USER).append(" where id = ?");Copy the code
Is:

StringBuilder buffer = new StringBuilder(128);
buffer.append("select * from ").append(T_USER).append(" where id = ?");Copy the code

10.2. In multithreading, use thread-safe classes whenever possible

Using thread-safe classes is much cleaner and more efficient than implementing your own synchronization code.

Example:

private volatile int counter = 0; public void access(Long userId) { synchronized (this) { counter++; }... }Copy the code
Is:

private final AtomicInteger counter = new AtomicInteger(0); public void access(Long userId) { counter.incrementAndGet(); . }Copy the code

10.3. Minimize the scope of synchronized code blocks

In a method, only a small part of the logic may need to be synchronized, and if synchronization controls the whole method, the execution efficiency will be affected. Therefore, minimize the scope of synchronized code blocks and synchronize only the code that needs to be synchronized.

Example:

private volatile int counter = 0; public synchronized void access(Long userId) { counter++; . // not synchronous}Copy the code
Is:

private volatile int counter = 0; public void access(Long userId) { synchronized (this) { counter++; }... // not synchronous}Copy the code

10.4. Try to merge into the same synchronized code block

Synchronized code blocks have a performance overhead, and if you determine that you can merge into the same synchronized code block, you should try to merge into the same synchronized code block.

Example:

Public synchronized handleOrder(OrderDO order) {... Public void handleOrder(List<OrderDO> orderList) {for(OrderDO order : orderList) { handleOrder(order); }}Copy the code
Is:

Public handleOrder(OrderDO order) {... Public synchronized void handleOrder(List<OrderDO> orderList) {for(OrderDO order : orderList) { handleOrder(order); }}Copy the code

10.5. Use thread pools to minimize thread overhead

There are two necessary overhead in multithreading: thread creation and context switching. With thread pools, you can avoid this overhead as much as possible.

Example:

public void executeTask(Runnable runnable) {
    new Thread(runnable).start();
}Copy the code
Is:

private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(10);
public void executeTask(Runnable runnable) {
    executorService.execute(runnable);
}Copy the code

Afterword.

As an “IT worker “who has been fighting in the front line of business for a long time, I have no chance to study any inscrutable” theory “, but can only focus on the “technology” that can be seen and felt at the moment, and devote myself to “do a line, love a line, specialize in a line, be good at a line”.





The original link

This article is the content of Ali Cloud, shall not be reproduced without permission.