The usage of merge() of Map clever operation in Java 8

The biggest feature of Java 8 is no different from being more function-oriented, such as the introduction of lambda, etc., which can better perform functional programming. I accidentally discovered the map.merge() method some time ago, and it feels very useful. This article briefly introduces it. First, let’s look at an example.

merge() 怎么用?

Suppose we have such a piece of business logic. I have a list of student achievement objects. The object contains three attributes: student name, subject, and subject score. It is required to obtain the total score of each student. Join the list as follows:

private List<StudentScore> buildATestList() { 
List<StudentScore> studentScoreList = new ArrayList<>(); 
StudentScore studentScore1 = new StudentScore() {{ 
setStuName("Zhang San"); 
setSubject("Chinese"); 
setScore(70); 
}}; 
StudentScore studentScore2 = new StudentScore() {{ 
setStuName("Zhang San"); 
setSubject("Mathematics"); 
setScore(80); 
}}; 
StudentScore studentScore3 = new StudentScore() {{ 
setStuName("Zhang San"); 
setSubject("English"); 
setScore(65); 
}}; 
StudentScore studentScore4 = new StudentScore() {{ 
setStuName("lisi"); 
setSubject("Chinese"); 
setScore(68); 
}}; 
StudentScore studentScore5 = new StudentScore() {{ 
setStuName("lisi"); 
setSubject("Mathematics"); 
setScore(70); 
}}; 
StudentScore studentScore6 = new StudentScore() {{ 
setStuName("lisi"); 
setSubject("English"); 
setScore(90); 
}}; 
StudentScore studentScore7 = new StudentScore() {{ 
setStuName("Wang Five"); 
setSubject("Chinese"); 
setScore(80); 
}}; 
StudentScore studentScore8 = new StudentScore() {{ 
setStuName("Wang Five"); 
setSubject("Mathematics"); 
setScore(85); 
}}; 
StudentScore studentScore9 = new StudentScore() {{ 
setStuName("Wang Five"); 
setSubject("English"); 
setScore(70); }}; 
studentScoreList.add(studentScore1); studentScoreList.add(studentScore2); studentScoreList.add(studentScore3); studentScoreList.add(studentScore4); studentScoreList.add(studentScore5); studentScoreList.add(studentScore6); studentScoreList.add(studentScore7); studentScoreList.add(studentScore8); studentScoreList.add(studentScore9); return studentScoreList; }

Let’s take a look at conventional practices first:

 ObjectMapper objectMapper = new ObjectMapper();        
List<StudentScore> studentScoreList = buildATestList();
        Map<String, Integer> studentScoreMap = new HashMap<>();        studentScoreList.forEach(studentScore -> {            
if (studentScoreMap.containsKey(studentScore.getStuName())) {                studentScoreMap.put(studentScore.getStuName(),                                     studentScoreMap.get(studentScore.getStuName()) + studentScore.getScore());            
} else {
                
studentScoreMap.put(studentScore.getStuName(), studentScore.getScore());            
}        });
        System.out.println(objectMapper.writeValueAsString(studentScoreMap));
// The results are as follows:
// {"Li Si": 228, "Zhang San": 215, "Wang Wu": 235} 

Then look at how merge() does it:

Map<String, Integer> studentScoreMap2 = new HashMap<>();

studentScoreList.forEach(studentScore -> studentScoreMap2.merge(

studentScore.getStuName(),

studentScore.getScore(), Integer::sum)); System.out.println(objectMapper.writeValueAsString(studentScoreMap2));

// The results are as follows: // {"Li Si": 228, "Zhang San": 215, "Wang Wu": 235}

Introduction to merge()

merge() can be understood like this: it assigns a new value to the key (if it does not exist) or updates the value corresponding to the given key value. The source code is as follows:

default V merge(K key, V value, BiFunction<? super V,? super V,?

extends V> remappingFunction) {

Objects.requireNonNull(remappingFunction);

Objects.requireNonNull(value);

V oldValue = this.get(key);

V newValue = oldValue == null? Value:

remappingFunction.apply(oldValue, value);

if (newValue == null) {

this.remove(key);

} else {

this.put(key, newValue);

}

return newValue; }

We can see that the principle is also very simple. The method receives three parameters, a key value, a value, and a remappingFunction. If the given key does not exist, it becomes put(key, value).

However, if the key already has some value, we can choose the way of merging with remappingFunction, and then assign the merged newValue to the original key.

scenes to be used

There are relatively many use cases for this, such as grouping and summing operations. Although there are related groupingBy() methods in stream, if you want to do some other operations in the loop, merge() is still quite a bit. Good choice.

other

In addition to the merge() method, I also saw some other map-related methods in Java 8, such as putIfAbsent, compute(), computeIfAbsent(), computeIfPresent. We should know what these methods mean by looking at the name, so here I won’t introduce too much. If you’re interested, you can simply read the source code (all of which are quite easy to understand). Here we post the source code of compute()(Map.class). The return value is the new value obtained after the calculation. :

default V compute(K key, BiFunction<? super K,? super V,? extends V>

remappingFunction) {

Objects.requireNonNull(remappingFunction);

V oldValue = this.get(key);

V newValue = remappingFunction.apply(key, oldValue);

if (newValue == null) {

if (oldValue == null && !this.containsKey(key)) {

return null;

} else {

this.remove(key); return null;

}

} else {

this.put(key, newValue); return newValue;

} }

Summarize

This article briefly introduces the Map.merge() method. In addition, the HashMap implementation method in Java 8 uses TreeNode and red-black trees. It may be a bit difficult to read the source code, but the principle is still similar. Compute () Same thing. Therefore, the source code must be looked at, and if you don’t understand, read and practice more and you will understand it naturally.

Leave a Reply

Your email address will not be published.

en_USEnglish