Map 中ConcurrentHashMap是線程安全的,但不是所有操作都是,例如get()之后再put()就不是了,這時(shí)使用merge()確保沒有更新會(huì)丟失。
創(chuàng)新互聯(lián)建站專注于君山企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,商城開發(fā)。君山網(wǎng)站建設(shè)公司,為君山等地區(qū)提供建站服務(wù)。全流程按需求定制設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)建站專業(yè)和態(tài)度為您提供的服務(wù)
因?yàn)镸ap.merge()意味著我們可以原子地執(zhí)行插入或更新操作,它是線程安全的。
一、源碼解析
default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) { Objects.requireNonNull(remappingFunction); Objects.requireNonNull(value); V oldValue = get(key); V newValue = (oldValue == null) ? value : remappingFunction.apply(oldValue, value); if(newValue == null) { remove(key); } else { put(key, newValue); } return newValue; }
該方法接收三個(gè)參數(shù),一個(gè) key 值,一個(gè) value,一個(gè) remappingFunction 。如果給定的key不存在,它就變成了put(key, value);但是,如果key已經(jīng)存在一些值,我們 remappingFunction 可以選擇合并的方式:
二、使用場(chǎng)景
merge()方法在統(tǒng)計(jì)時(shí)用的場(chǎng)景比較多,例如:有一個(gè)學(xué)生成績(jī)對(duì)象的列表,對(duì)象包含學(xué)生姓名、科目、科目分?jǐn)?shù)三個(gè)屬性,求得每個(gè)學(xué)生的總成績(jī)。
2.1 準(zhǔn)備數(shù)據(jù)
學(xué)生對(duì)象StudentEntity.java
@Data public class StudentEntity { /** * 學(xué)生姓名 */ private String studentName; /** * 學(xué)科 */ private String subject; /** * 分?jǐn)?shù) */ private Integer score; }
學(xué)生成績(jī)數(shù)據(jù)
private ListbuildATestList() { List studentEntityList = new ArrayList<>(); StudentEntity studentEntity1 = new StudentEntity() {{ setStudentName("張三"); setSubject("語(yǔ)文"); setScore(60); }}; StudentEntity studentEntity2 = new StudentEntity() {{ setStudentName("張三"); setSubject("數(shù)學(xué)"); setScore(70); }}; StudentEntity studentEntity3 = new StudentEntity() {{ setStudentName("張三"); setSubject("英語(yǔ)"); setScore(80); }}; StudentEntity studentEntity4 = new StudentEntity() {{ setStudentName("李四"); setSubject("語(yǔ)文"); setScore(85); }}; StudentEntity studentEntity5 = new StudentEntity() {{ setStudentName("李四"); setSubject("數(shù)學(xué)"); setScore(75); }}; StudentEntity studentEntity6 = new StudentEntity() {{ setStudentName("李四"); setSubject("英語(yǔ)"); setScore(65); }}; StudentEntity studentEntity7 = new StudentEntity() {{ setStudentName("王五"); setSubject("語(yǔ)文"); setScore(80); }}; StudentEntity studentEntity8 = new StudentEntity() {{ setStudentName("王五"); setSubject("數(shù)學(xué)"); setScore(85); }}; StudentEntity studentEntity9 = new StudentEntity() {{ setStudentName("王五"); setSubject("英語(yǔ)"); setScore(90); }}; studentEntityList.add(studentEntity1); studentEntityList.add(studentEntity2); studentEntityList.add(studentEntity3); studentEntityList.add(studentEntity4); studentEntityList.add(studentEntity5); studentEntityList.add(studentEntity6); studentEntityList.add(studentEntity7); studentEntityList.add(studentEntity8); studentEntityList.add(studentEntity9); return studentEntityList; }
2.2 一般方案
思路:用Map的一組key/value存儲(chǔ)一個(gè)學(xué)生的總成績(jī)(學(xué)生姓名作為key,總成績(jī)?yōu)関alue)
Map中不存在指定的key時(shí),將傳入的value設(shè)置為key的值;
當(dāng)key存在值時(shí),取出存在的值與當(dāng)前值相加,然后放入Map中。
public void normalMethod() { Long startTime = System.currentTimeMillis(); // 造一個(gè)學(xué)生成績(jī)列表 ListstudentEntityList = buildATestList(); Map studentScore = new HashMap<>(); studentEntityList.forEach(studentEntity -> { if (studentScore.containsKey(studentEntity.getStudentName())) { studentScore.put(studentEntity.getStudentName(), studentScore.get(studentEntity.getStudentName()) + studentEntity.getScore()); } else { studentScore.put(studentEntity.getStudentName(), studentEntity.getScore()); } }); log.info("各個(gè)學(xué)生成績(jī):{},耗時(shí):{}ms",studentScore, System.currentTimeMillis() - startTime); }
2.3 Map.merge()
很明顯,這里需要采用remappingFunction的合并方式。
public void mergeMethod() { Long startTime = System.currentTimeMillis(); // 造一個(gè)學(xué)生成績(jī)列表 ListstudentEntityList = buildATestList(); Map studentScore = new HashMap<>(); studentEntityList.forEach(studentEntity -> studentScore.merge( studentEntity.getStudentName(), studentEntity.getScore(), Integer::sum)); log.info("各個(gè)學(xué)生成績(jī):{},耗時(shí):{}ms",studentScore, System.currentTimeMillis() - startTime); }
2.4 測(cè)試及小結(jié)
測(cè)試方法
@Test public void testAll() { // 一般寫法 normalMethod(); // merge()方法 mergeMethod(); }
測(cè)試結(jié)果
00:21:28.305 [main] INFO cn.van.jdk.eight.map.merge.MapOfMergeTest - 各個(gè)學(xué)生成績(jī):{李四=225, 張三=210, 王五=255},耗時(shí):75ms
00:21:28.310 [main] INFO cn.van.jdk.eight.map.merge.MapOfMergeTest - 各個(gè)學(xué)生成績(jī):{李四=225, 張三=210, 王五=255},耗時(shí):2ms
結(jié)果小結(jié)
三、總結(jié)
3.1 示例源碼
Github 示例代碼
總結(jié)
以上所述是小編給大家介紹的JDK 1.8 中的 Map.merge(),希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)創(chuàng)新互聯(lián)網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!