You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

61 lines
2.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.example.entity;
import cn.hutool.core.collection.CollectionUtil;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
// 功能:基于用户的协同过滤推荐算法
public class UserCF {
/**
* 方法描述: 推荐商品id列表
* 基于用户的协同过滤算法,找到与当前用户最相似的用户,推荐相似用户喜欢而当前用户未看过的商品
* @param userId 当前用户ID
* @param list 用户商品评分数据列表
* @return {@link List<Integer>} 推荐的商品ID列表
*/
public static List<Integer> recommend(Integer userId, List<RelateDTO> list) {
// 按用户ID分组构建用户-商品评分映射
Map<Integer, List<RelateDTO>> userMap = list.stream().collect(Collectors.groupingBy(RelateDTO::getUseId));
// 获取其他用户与当前用户的相似度关系值
Map<Integer, Double> userDisMap = CoreMath.computeNeighbor(userId, userMap, 0);
// 如果没有找到相似用户,返回空列表
if (CollectionUtil.isEmpty(userDisMap)) {
return Collections.emptyList();
}
// 获取相似度最高的用户(关系最近的用户)
double maxValue = Collections.max(userDisMap.values());
Set<Integer> userIds = userDisMap.entrySet().stream()
.filter(e -> e.getValue() == maxValue)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
// 取任意一个相似度最高的用户
Integer nearestUserId = userIds.stream().findAny().orElse(null);
if (nearestUserId == null) {
return Collections.emptyList();
}
// 获取最近邻用户看过的商品列表
List<Integer> neighborItems = userMap.get(nearestUserId).stream()
.map(RelateDTO::getGoodsId)
.collect(Collectors.toList());
// 获取当前用户看过的商品列表
List<Integer> userItems = userMap.get(userId).stream()
.map(RelateDTO::getGoodsId)
.collect(Collectors.toList());
// 找到最近邻用户看过但当前用户没看过的商品(差集)
neighborItems.removeAll(userItems);
return neighborItems;
}
}