引子:
寫代碼中,如果在for中有查詢數據的,一般大多數公司,都要求批量查詢,或者說不讓在for中查詢太多的數據庫。今天簡單說一下
1.需求:
學生和科目。學生和科目是一對的關係。現在要求查詢出全班學生的所有科目的成績。
實體:
student :學生實體
subject:科目實體
<code>public class Student {
private Long id;
private String name;
private Integer age;
private Integer sex;
private List<subject> subjectList;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public List<subject> getSubjectList() {
return subjectList;
}
public void setSubjectList(List<subject> subjectList) {
this.subjectList = subjectList;
}
}
public class Subject {
private Long id;
private Long studentId;
private String name;
private Float age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getStudentId() {
return studentId;
}
public void setStudentId(Long studentId) {
this.studentId = studentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getAge() {
return age;
}
public void setAge(Float age) {
this.age = age;
}
}/<subject>/<subject>/<subject>/<code>
<code>/** * 查詢學生信息 * @param studentIds * @return */
private List<student> queryStudent(List<long> studentIds) {
// 查詢數據庫
return new ArrayList<>();
}
/** * 查詢科目信息 * @param subjectIds * @return */
private List<subject> querySubject(List<long> subjectIds) {
// 查詢數據庫
return Lists.newArrayList();
}
/** * 查詢科目信息 * @param subjectId * @return */
private List<subject> querySubject(Long subjectId) {
// 查詢數據庫
return Lists.newArrayList();
}/<subject>/<long>/<subject>/<long>/<student>/<code>
2.不同方案
2.1單次查詢:
<code>/** * 單次查詢 * @param ids * @return */
private List<student> queryStudentAndSubject(List<long> ids){
List<student> students = queryStudent(ids);
students.forEach(student->{
List<subject> subjects = querySubject(student.id);
student.setSubjectList(subjects);
});
return students;
}/<subject>/<student>/<long>/<student>/<code>
2.2批量查詢:
<code>/** * 批量查詢 * @param ids * @return */private List<student> queryBatchStudentAndSubject(List<long> ids){
List<student> students = queryStudent(ids);
List<subject> subjects = querySubject(ids);
Map<long>> studentMap=new HashMap<>();
subjects.forEach(subject -> {
Long studentId = subject.getStudentId();
List<subject> subjectsList = studentMap.get(studentMap);
if(CollectionUtils.isEmpty(subjectsList)){
subjectsList=new ArrayList<>();
studentMap.put(studentId,subjectsList);
}
subjectsList.add(subject);
});
students.forEach(student->{
List<subject> subjects1 = studentMap.get(student.getId());
student.setSubjectList(subjects1);
});
return students;
}/<subject>/<subject>/<long>/<subject>/<student>/<long>/<student>/<code>
2.3批量查詢:使用Guava寫法1
<code>/** * 批量查詢 * @param ids * @return */
private List<student> queryBatchStudentAndSubject2(List<long> ids){
List<student> students = queryStudent(ids);
List<subject> subjects = querySubject(ids);
ArrayListMultimap<long> map=new ArrayListMultimap<>();
subjects.forEach(subject -> {
map.put(subject.getStudentId(),subject);
});
students.forEach(student->{
List<subject> subjectList = map.get(student.getId());
student.setSubjectList(subjectList);
});
return students;
}/<subject>/<long>/<subject>/<student>/<long>/<student>/<code>
2.4批量查詢:使用Guava寫法2
<code>/** * 批量查詢 * @param ids * @return */
private List<student> queryBatchStudentAndSubject3(List<long> ids){
List<student> students = queryStudent(ids);
List<subject> subjects = querySubject(ids);
Map<long>> map = Multimaps.index(subjects, Subject::getStudentId).asMap();
students.forEach(student->{
Collection<subject> subjectsList = map.get(student.getId());
student.setSubjectList(new ArrayList<>(subjectsList));
});
return students;
}/<subject>/<long>/<subject>/<student>/<long>/<student>/<code>
2.5對比
2.1和2.2
<code>ArrayListMultimap<long> map=new ArrayListMultimap<>();
subjects.forEach(subject -> {
map.put(subject.getStudentId(),subject);
});
students.forEach(student->{
List<subject> subjectList = map.get(student.getId());
student.setSubjectList(subjectList);
});/<subject>/<long>/<code>
<code>Map<long>> studentMap=new HashMap<>();
subjects.forEach(subject -> {
Long studentId = subject.getStudentId();
List<subject> subjectsList = studentMap.get(studentMap);
if(CollectionUtils.isEmpty(subjectsList)){
subjectsList=new ArrayList<>();
studentMap.put(studentId,subjectsList);
}
subjectsList.add(subject);
});/<subject>/<long>/<code>
2.1和2.3
<code>Map<long>> map = Multimaps.index(subjects, Subject::getStudentId).asMap();
students.forEach(student->{
Collection<subject> subjectsList = map.get(student.getId());
student.setSubjectList(new ArrayList<>(subjectsList));
});/<subject>/<long>/<code>
<code>Map<long>> studentMap=new HashMap<>();
subjects.forEach(subject -> {
Long studentId = subject.getStudentId();
List<subject> subjectsList = studentMap.get(studentMap);
if(CollectionUtils.isEmpty(subjectsList)){
subjectsList=new ArrayList<>();
studentMap.put(studentId,subjectsList);
}
subjectsList.add(subject);
});
students.forEach(student->{
List<subject> subjects1 = studentMap.get(student.getId());
student.setSubjectList(subjects1);
});/<subject>/<subject>/<long>/<code>
可以看出代碼越來越精簡。
這就是為什麼強烈推薦Java程序員使用Google Guava編程。
上面只是其中的點點。Guava還有其他優雅的寫法。以後再說。
http://code.google.com/p/guava-libraries/wiki/GuavaExplained
最後附上Multimap提供了豐富的實現(從網上找了一個圖)
閱讀更多 閒著沒事聊會 的文章