java map join_HashMap 常见应用:实现 SQL JOIN
在我的上一篇文章中,講到了我自己初步認(rèn)識 HashMap 的一個經(jīng)驗分享:HashMap 淺析 —— LeetCode Two Sum 刷題總結(jié)。作為一個 CRUD 工程師,平時很少接觸到基礎(chǔ)組件的涉及,那么是不是很難有機(jī)會用到 HashMap 呢?
今天,就舉一個常見的查詢例子,來看看我們?nèi)绾问褂?HashMap 來提高代碼的效率。
已知一個 Student 類:
public class Student {
private Long id;
private String name;
public Student(Long id, String name) {
this.id = id;
this.name = name;
}
// ---Getters And Setters---
}
和一個 Score 類:
public class Score {
private Long studentId;
private String mathScore;
private String englishScore;
public Score(Long studentId, String mathScore, String englishScore) {
this.studentId = studentId;
this.mathScore = mathScore;
this.englishScore = englishScore;
}
// ---Getters And Setters---
}
我們需要把 Student 和 Score 合并到一起,即類 Report:
public class Report {
private Long studentId;
private String studentName;
private String mathScore;
private String englishScore;
public Report(Long studentId, String studentName, String mathScore, String englishScore) {
this.studentId = studentId;
this.studentName = studentName;
this.mathScore = mathScore;
this.englishScore = englishScore;
}
}
看類的屬性我們就明白了,這里其實相當(dāng)于在 Student 和 Score 之間做一個 Join,得到 Report。這是我們在編程中常見的場景(例如查詢了訂單中心,用戶中心,支付中心,合并各個中心返回的結(jié)果形成一個表單,因為各個中心是獨立的微服務(wù),無法使用 SQL JOIN)。
現(xiàn)有兩個 List:List 和 List:
List students = Arrays.asList(
new Student(1L, "Angle"),
new Student(2L, "Baby")
);
List scores = Arrays.asList(
new Score(1L, "90", "87"),
new Score(2L, "92", "78")
);
在學(xué)會使用 HashMap 之前,我可能會做一次雙重循環(huán):
List reports = new ArrayList<>();
for (Student student : students) {
for (Score score : scores) {
if (!student.getId().equals(score.getStudentId())) {
continue;
}
reports.add(
new Report(student.getId(), student.getName(), score.getMathScore(), score.getEnglishScore())
);
break;
}
}
時間復(fù)雜度最差的情況下是O(n * m)。
但是使用 HashMap 來改善程序,就能得到不錯的效果:
Map map = new HashMap<>();
for (Student student : students) {
map.put(student.getId(), student);
}
List reports = new ArrayList<>();
for (Score score : scores) {
Student student = map.get(score.getStudentId());
if(student == null){ // 避免 NPE
continue;
}
reports.add(
new Report(student.getId(), student.getName(), score.getMathScore(), score.getEnglishScore())
);
}
雙重循環(huán),變成了兩次循環(huán),時間復(fù)雜度是O(n + m)。
顯然要比前面的方法效果要好一些。筆者寫了測試代碼分別測試兩個方法的效率,在 10w 數(shù)據(jù)下,執(zhí)行時間如下:
差距好像挺大。想了解為什么 HashMap 能夠得到如此好的效果,可以看我的這篇文章:HashMap 淺析 —— LeetCode Two Sum 刷題總結(jié)。如果讀者有更好的解法歡迎留言交流,筆者水平有限,在算法上研究不多。
10w 數(shù)據(jù)的測試源碼見下方,各位讀者可以自行試驗下效果:
package com.xiangyu.demo.hashmap;
import com.xiangyu.java.hashmap.Report;
import com.xiangyu.java.hashmap.Score;
import com.xiangyu.java.hashmap.Student;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HashMapTest {
private List students = new ArrayList<>();
private List scores = new ArrayList<>();
@Before
public void before() {
// 每個list 里放 10w 數(shù)據(jù)
for (long i = 0; i < 100000; i++) {
students.add(new Student(i, "test"));
scores.add(new Score(i, "95", "95"));
}
}
@Test
public void TestHashMap() {
Map map = new HashMap<>();
for (Student student : students) {
map.put(student.getId(), student);
}
List reports = new ArrayList<>();
for (Score score : scores) {
Student student = map.get(score.getStudentId());
if (student == null) {
continue;
}
reports.add(
new Report(student.getId(), student.getName(), score.getMathScore(), score.getEnglishScore())
);
}
System.out.println(reports.size());
}
@Test
public void testFor2() {
List reports = new ArrayList<>();
for (Student student : students) {
for (Score score : scores) {
if (!student.getId().equals(score.getStudentId())) {
continue;
}
reports.add(
new Report(student.getId(), student.getName(), score.getMathScore(), score.getEnglishScore())
);
break;
}
}
System.out.println(reports.size());
}
}
總結(jié)
以上是生活随笔為你收集整理的java map join_HashMap 常见应用:实现 SQL JOIN的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: git 开源 java_开源中国GIT中
- 下一篇: php面试带项目_PHP面试常用算法(推