@Override
public List<UserVO> matchUser(long num, User loginUser) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
// 只查询有标签的用户
queryWrapper.isNotNull("tags");
queryWrapper.select("id", "tags");
List<User> userList = this.list(queryWrapper);
// 序列化登录用户的标签
String loginUserTags = loginUser.getTags();
Gson gson = new Gson();
List<String> tagList = gson.fromJson(loginUserTags, new TypeToken<List<String>>() {
}.getType());
// 用户列表的下标 => 相似度
List<Pair<User, Long>> list = new ArrayList<>();
// 依次计算当前用户和所有用户的相似度
for (int i = 0; i < userList.size(); i++) {
User user = userList.get(i);
String userTags = user.getTags();
//无标签的 或当前用户为自己
if (StringUtils.isBlank(userTags) || Objects.equals(user.getId(), loginUser.getId())) {
continue;
}
List<String> userTagList = gson.fromJson(userTags, new TypeToken<List<String>>() {
}.getType());
//计算分数
long distance = AlgorithmUtils.minDistance(tagList, userTagList);
list.add(new ImmutablePair<>(user, distance));
}
// 按编辑距离由小到大排序
List<Pair<User, Long>> topUserPairList = list.stream()
.sorted((a, b) -> (int) (a.getValue() - b.getValue()))
.limit(num)
.toList();
// 有顺序的userID列表
List<Long> userIdList = topUserPairList.stream().map(pari -> pari.getKey().getId()).toList();
//根据id查询user完整信息
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.in("id", userIdList);
Map<Long, List<UserVO>> userIdUserListMap = this.list(userQueryWrapper).stream()
.map(this::getUserVO)
.collect(Collectors.groupingBy(UserVO::getId));
// 因为上面查询打乱了顺序,这里根据上面有序的userID列表赋值
List<UserVO> finalUserListVO = new ArrayList<>();
for (Long userId : userIdList) {
finalUserListVO.add(userIdUserListMap.get(userId).getFirst());
}
return finalUserListVO;
}