情景之computeIfAbsent()
# 前言
今天遇到一个比较有意思情景,将以前学过的知识,突然就用到了,轻松秒杀,记录一下。
# 情景描述
在评教系统中,现在有四张表分别是title、evaluate、course、content(表名称请不要在意>-<)。其中title表为题目表,evaluate表为course与content的关系表,course表为课程表,content表为题目回答表。表结构放最后。
现在要实现期末评教信息获取接口,前端传递的参数只有一个teacherId(教师id),需要向前端传递的参数的形式,要传递对应的题目及其答案(这个答案是评教信息),题目为评分题目则返回对应题目平均分,题目为主观题则返回答案列表。
# 解决思路
我心中想的结构如下面JSON所示。
{
"titleId": 6, // 题目id
"title": "是否核实学生出勤", // 题目内容
"type": 0, // 题目类型 0为评分 1为主观
"averageScore": 5, // 平均分
"contentTexts": null // 评论
},
{
"titleId": 10, // 题目id
"title": "任课老师是否布置过量作业", // 题目内容
"type": 1, // 题目类型 0为评分 1为主观
"averageScore": null,
"contentTexts": [ // 评论
"一般",
"作业超多根本写不完",
"题目太难"
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
一次查完感觉有些难度(写的我汗流浃背了😰),所以我准备分两次来查,第一次查出对应题目平均分,第二次查出主观题。
查平均分SQL如下:
SELECT
t.id AS title_id, t.title, c.type, AVG(c.score) as average_score
FROM
title AS t
JOIN content AS c ON c.title_id = t.id
JOIN evaluate AS e ON e.content_id = c.id
JOIN course AS ce ON ce.id = e.course_id
WHERE
c.type = 0 and ce.teacher_id = #{teacherId}
GROUP BY
t.id, t.title
2
3
4
5
6
7
8
9
10
11
查主观题SQL如下:
SELECT t.id AS title_id, t.title, c.type, c.text
FROM
title AS t
JOIN content AS c ON c.title_id = t.id
JOIN evaluate AS e ON e.content_id = c.id
JOIN course AS ce ON ce.id = e.course_id
WHERE
ce.teacher_id = #{teacherId}
AND c.type = 1;
2
3
4
5
6
7
8
9
分开查SQL就比较简单,当初想着一次查完光写个SQL就写了几个小时>-<。
存储的实体类如下:
public class EndContentTextTmp {
private Long titleId; // 题目id
private String title; // 题目信息
private Integer type; // 题目类型
private String Text; // 评论信息
}
public class EndContentTmp {
private Long titleId; // 题目id
private String title; // 题目信息
private Integer type; // 题目类型
private Float averageScore; // 平均分
private List<String> contentTexts; // 评论信息
}
2
3
4
5
6
7
8
9
10
11
12
13
其中EndContentTmp
用于接收评分查询返回值,同时返回给前端,因为titleId是不重复的。EndContentTextTmp
用于接收主观题信息。
我的想法是将EndContentTextTmp
中,同一题目的全部评论作为List存入EndContentTmp
中,其余对应信息依次填入就可以了。
具体程序如何实现?我的想法是这样的,先将对应信息存入Map中key为titleId,value为List<String>
。然后循环List<EndContentTextTmp>
将对应信息拿到然后插入List<EndContentTmp>
中就ok了。
代码如下:
@Override
public List<EndContentTmp> selectEndContentByTeacherId(Long teacherId) {
if (teacherId == null) {
return null;
}
List<EndContentTmp> endContentTmp = titleMapper.selectEndContentScore(teacherId);
if (endContentTmp.isEmpty()) {
return null;
}
List<EndContentTextTmp> endContentTextTmp = titleMapper.selectEndContentText(teacherId);
if (endContentTextTmp.isEmpty()) {
return null;
}
Map<Long, List<String>> textTmp = new HashMap<>();
for (EndContentTextTmp i: endContentTextTmp) {
Long titleId = i.getTitleId();
textTmp.computeIfAbsent(titleId, v -> new ArrayList<>()).add(i.getText());
}
Long tmp = 0L;
for (EndContentTextTmp i: endContentTextTmp) {
if (Objects.equals(i.getTitleId(), tmp)) {
continue;
}
EndContentTmp contentTmp = new EndContentTmp(i.getTitleId(), i.getTitle(), i.getType(),
null, textTmp.get(i.getTitleId()));
endContentTmp.add(contentTmp);
tmp = i.getTitleId();
}
return endContentTmp;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
醋找到了!textTmp.computeIfAbsent(titleId, v -> new ArrayList<>()).add(i.getText());
有点喜欢这个,当时困扰了我好久,然后突然发现宝贵方法。
# computeIfAbsent()
computeIfAbsent
方法,如果键已经存在,则返回该键对应的值,而不会执行提供的 lambda 表达式。
简洁又高效😀。十分喜欢