Google Guava单次查询or批量查询

引子:

写代码中,如果在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提供了丰富的实现(从网上找了一个图)