Java实现利用标签相似度匹配用户,匹配度由上到下( 编辑距离算法实现)

1.首先就是编辑距离算法,此处匹配的是两个字符串,由于标签不止一个,我们需要进行适当的修改

 /**
     * 编辑距离算法,(用于计算距离相近的字符串)
     * @param word1
     * @param word2
     * @return
     */
    public int minDistance(String word1, String word2){
        int n = word1.length();
        int m = word2.length();

        if(n * m == 0)
            return n + m;

        int[][] d = new int[n + 1][m + 1];
        for (int i = 0; i < n + 1; i++){
            d[i][0] = i;
        }

        for (int j = 0; j < m + 1; j++){
            d[0][j] = j;
        }

        for (int i = 1; i < n + 1; i++){
            for (int j = 1; j < m + 1; j++){
                int left = d[i - 1][j] + 1;
                int down = d[i][j - 1] + 1;
                int left_down = d[i - 1][j - 1];
                if (word1.charAt(i - 1) != word2.charAt(j - 1))
                    left_down += 1;
                d[i][j] = Math.min(left, Math.min(down, left_down));
            }
        }
        return d[n][m];
    }
}

修改过后的匹配算法

/**
     * 编辑距离算法,(用于计算距离相近的标签)
     * @param tagList1
     * @param tagList2
     * @return
     */
    public static int minDistance(List<String> tagList1, List<String> tagList2){
        int n = tagList1.size();
        int m = tagList2.size();

        if(n * m == 0)
            return n + m;

        int[][] d = new int[n + 1][m + 1];
        for (int i = 0; i < n + 1; i++){
            d[i][0] = i;
        }

        for (int j = 0; j < m + 1; j++){
            d[0][j] = j;
        }

        for (int i = 1; i < n + 1; i++){
            for (int j = 1; j < m + 1; j++){
                int left = d[i - 1][j] + 1;
                int down = d[i][j - 1] + 1;
                int left_down = d[i - 1][j - 1];
                if (!Objects.equals(tagList1.get(i-1), tagList2.get(j - 1)))
                    left_down += 1;
                d[i][j] = Math.min(left, Math.min(down, left_down));
            }
        }
        return d[n][m];
    }

我的项目是每个用户都会有标签,设置开启匹配模式,也就是说展示匹配之后的用户,实现方法如下

controller层

/**
     * 匹配用户
     * @param num
     * @param request
     * @return
     */
    @GetMapping("/match")
    public List<User> matchUsers(long num, HttpServletRequest request){
        if (num==0 || num>20){
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        return userService.matchUsers(num,loginUser);
    }

service层

   List<User> matchUsers(long num, User loginUser);

serviceimpl层

  @Override
    public List<User> matchUsers(long num, User loginUser) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //选择要查询的列
        queryWrapper.select("id","tags");
        queryWrapper.isNotNull("tags");
        //遍历所有用户
        List<User> userList = this.list(queryWrapper);
        //获取当前用户的tags,并且将字符串转换为列表形式
        String tags = loginUser.getTags();
        Gson gson = new Gson();
        List<String> tagList = gson.fromJson(tags, 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();
            //如果userTags或者遍历到当前登录用户,返回
            if (StringUtils.isBlank(userTags) || user.getId()==loginUser.getId()){
                continue;
            }
            //将gson格式的字符串转化为java对象列表
            List<String> userTagList = gson.fromJson(userTags, new TypeToken<List<String>>() {
            }.getType());
            //与当前登录用户进行比较,返回分数
            long distance = AlgorithmUtils.minDistance(tagList, userTagList);
           list.add(new Pair<>(user,distance));
        }
        //将编辑距离由小到大排序
        List<Pair<User, Long>> topUserPairList = list.stream()
                .sorted((a, b) -> (int) (a.getValue() - b.getValue()))
                .limit(num)
                .collect(Collectors.toList());
//         获取id列表
        List<Long> userIdlist =topUserPairList.stream().map(pair -> pair.getKey().getId()).collect(Collectors.toList());
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        //查询id是否包含在useridlist
        userQueryWrapper.in("id",userIdlist);
        //用户脱敏,转换为key是id的map
        Map<Long, List<User>> userIdUserListMap = this.list(userQueryWrapper)
                .stream()
                .map(user -> getSafetyUser(user))
                .collect(Collectors.groupingBy(User::getId));
        //创建一个新的列表,
        List<User> finalUserList = new ArrayList<>();
        for (Long userId : userIdlist) {
        //获取map的值
            finalUserList.add(userIdUserListMap.get(userId).get(0));
        }
        return finalUserList;
        }

其中num这个参数指的是你所要展示的条数,就是匹配出来的之后展示的由大到小前几条

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值