代码优化

This commit is contained in:
tarzan
2023-02-02 15:35:02 +08:00
parent 7b8fedacbd
commit 57e8f17e6e
8 changed files with 81 additions and 70 deletions

8
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@@ -1,8 +1,7 @@
package com.tarzan.recommend;
import com.tarzan.recommend.Service.Recommend;
import com.tarzan.recommend.service.Recommend;
import com.tarzan.recommend.dto.ItemDTO;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.List;

View File

@@ -12,49 +12,57 @@ import java.util.stream.IntStream;
*
* @author tarzan
* @version 1.0
* @company 洛阳图联科技有限公司
* @copyright (c) 2019 LuoYang TuLian Co'Ltd Inc. All rights reserved.
* @date 2020/7/31$ 15:21$
* @since JDK1.8
*/
public class CoreMath {
/**
* 方法描述: 推荐电影id列表
*
* @param userId 当前用户
* @param list 用户电影评分数据
* @return {@link List<Integer>}
* @date 2023年02月02日 14:51:42
*/
public List<Integer> recommend(Integer userId, List<RelateDTO> list) {
//找到最近邻用户id
Map<Double, Integer> distances = computeNearestNeighbor(userId, list);
Integer nearest = distances.values().iterator().next();
//按用户分组
Map<Integer, List<RelateDTO>> userMap=list.stream().collect(Collectors.groupingBy(RelateDTO::getUseId));
//获取其他用户与当前用户的关系值
Map<Double, Integer> distances = computeNeighbor(userId, userMap);
//取关系最近的用户
Integer nearestUserId = distances.values().iterator().next();
//最近邻用户看过电影列表
List<Integer> neighborItemList = userMap.get(nearest).stream().map(e->e.getModuleId()).collect(Collectors.toList());
List<Integer> neighborItems = userMap.get(nearestUserId).stream().map(RelateDTO::getModuleId).collect(Collectors.toList());
//指定用户看过电影列表
List<Integer> userItemList = userMap.get(userId).stream().map(e->e.getModuleId()).collect(Collectors.toList());;
List<Integer> userItems = userMap.get(userId).stream().map(RelateDTO::getModuleId).collect(Collectors.toList());
//找到最近邻看过,但是该用户没看过的电影,计算推荐,放入推荐列表
List<Integer> recommendList = new ArrayList<>();
for (Integer item : neighborItemList) {
if (!userItemList.contains(item)) {
for (Integer item : neighborItems) {
if (!userItems.contains(item)) {
recommendList.add(item);
}
}
Collections.sort(recommendList);
// Collections.sort(recommendList);
return recommendList;
}
/**
* 在给定userId的情况下计算其他用户和它的相关系数并排序
* @param userId
* @param list
* @return
* @param userId 用户id
* @param userMap 用户电影评分关系mqp
* @return Map<Double, Integer>
*/
private Map<Double, Integer> computeNearestNeighbor(Integer userId, List<RelateDTO> list) {
Map<Integer, List<RelateDTO>> userMap=list.stream().collect(Collectors.groupingBy(RelateDTO::getUseId));
private Map<Double, Integer> computeNeighbor(Integer userId, Map<Integer,List<RelateDTO>> userMap) {
Map<Double, Integer> distances = new TreeMap<>();
List<RelateDTO> userItems=userMap.get(userId);
userMap.forEach((k,v)->{
if(k!=userId){
double distance = pearson_dis(v,userMap.get(userId));
//排除此用户
if(!k.equals(userId)){
//关系距离
double distance = pearsonDis(v,userItems);
distances.put(distance, k);
}
});
@@ -65,16 +73,16 @@ public class CoreMath {
/**
* 计算两个序列间的相关系数
*
* @param xList
* @param yList
* @return
* @param xList 用户1喜欢的电影
* @param yList 用户2喜欢的电影
* @return double
*/
private double pearson_dis(List<RelateDTO> xList, List<RelateDTO> yList) {
private double pearsonDis(List<RelateDTO> xList, List<RelateDTO> yList) {
List<Integer> xs= Lists.newArrayList();
List<Integer> ys= Lists.newArrayList();
xList.forEach(x->{
yList.forEach(y->{
if(x.getModuleId()==y.getModuleId()){
if(x.getModuleId().equals(y.getModuleId())){
xs.add(x.getIndex());
ys.add(y.getIndex());
}
@@ -86,14 +94,13 @@ public class CoreMath {
/**
* 方法描述: 皮尔森pearson相关系数计算
*
* @param xs
* @param ys
* @Return {@link Double}
* @throws
* @param xs x集合
* @param ys y集合
* @Return {@link double}
* @author tarzan
* @date 2020年07月31日 17:03:20
*/
public static Double getRelate(List<Integer> xs, List<Integer> ys){
public static double getRelate(List<Integer> xs, List<Integer> ys){
int n=xs.size();
double Ex= xs.stream().mapToDouble(x->x).sum();
double Ey=ys.stream().mapToDouble(y->y).sum();
@@ -102,7 +109,9 @@ public class CoreMath {
double Exy= IntStream.range(0,n).mapToDouble(i->xs.get(i)*ys.get(i)).sum();
double numerator=Exy-Ex*Ey/n;
double denominator=Math.sqrt((Ex2-Math.pow(Ex,2)/n)*(Ey2-Math.pow(Ey,2)/n));
if (denominator==0) return 0.0;
if (denominator==0) {
return 0D;
}
return numerator/denominator;
}

View File

@@ -7,10 +7,8 @@ import lombok.NoArgsConstructor;
/**
* 业务项
*
* @author liu yapeng
* @author TARZAN
* @version 1.0
* @company 洛阳图联科技有限公司
* @copyright (c) 2019 LuoYang TuLian Co'Ltd Inc. All rights reserved.
* @date 2020/7/31$ 15:02$
* @since JDK1.8
*/
@@ -18,9 +16,13 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
public class ItemDTO {
/** 主键 */
private Integer id;
/** 名称 */
private String name;
/** 日期 */
private String date;
/** 链接 */
private String link;
}

View File

@@ -7,10 +7,8 @@ import lombok.NoArgsConstructor;
/**
* 关系数据
*
* @author liu yapeng
* @author tarzan
* @version 1.0
* @company 洛阳图联科技有限公司
* @copyright (c) 2019 LuoYang TuLian Co'Ltd Inc. All rights reserved.
* @date 2020/7/31$ 14:51$
* @since JDK1.8
*/
@@ -18,11 +16,11 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
public class RelateDTO {
//用户id
/** 用户id */
private Integer useId;
//业务id
/** 业务id */
private Integer moduleId;
//指数
/** 指数 */
private Integer index;

View File

@@ -7,7 +7,7 @@ import lombok.NoArgsConstructor;
/**
* 用户对象
*
* @author liu yapeng
* @author TARZAN
* @version 1.0
* @company 洛阳图联科技有限公司
* @copyright (c) 2019 LuoYang TuLian Co'Ltd Inc. All rights reserved.
@@ -18,15 +18,15 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO {
//主键
/** 主键 */
private Integer id;
//年纪
/** 年纪 */
private Integer age;
//性别
/** 性别 */
private String sex;
//职业
/** 职业 */
private String profession;
//邮编
/** 邮编 */
private String postcode;
}

View File

@@ -1,4 +1,4 @@
package com.tarzan.recommend.Service;
package com.tarzan.recommend.service;
import com.tarzan.recommend.dto.ItemDTO;
import com.tarzan.recommend.dto.RelateDTO;
@@ -10,7 +10,11 @@ import org.assertj.core.util.Lists;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
/**
* @author tarzan
*/
@Data
@Slf4j
public class FileDataSource {
@@ -22,20 +26,18 @@ public class FileDataSource {
/**
* 方法描述: 读取基础数据
*
* @param
* @Return {@link List<RelateDTO>}
* @throws
* @author tarzan
* @date 2020年07月31日 16:53:40
*/
public static List<RelateDTO> getData() {
folderPath=new FileDataSource().getClass().getResource("/ml-100k").getPath();
folderPath= Objects.requireNonNull(FileDataSource.class.getResource("/ml-100k")).getPath();
List<RelateDTO> relateList = Lists.newArrayList();
try {
FileInputStream out = new FileInputStream(folderPath+"\\u.data");
InputStreamReader reader = new InputStreamReader(out, StandardCharsets.UTF_8);
BufferedReader in = new BufferedReader(reader);
String line = null;
String line;
while ((line = in.readLine()) != null) {
String newline = line.replaceAll("[\t]", " ");
String[] ht = newline.split(" ");
@@ -54,20 +56,18 @@ public class FileDataSource {
/**
* 方法描述: 读取用户数据
*
* @param
* @Return {@link List<UserDTO>}
* @throws
* @author tarzan
* @date 2020年07月31日 16:54:51
*/
public static List<UserDTO> getUserData() {
folderPath=new FileDataSource().getClass().getResource("/ml-100k").getPath();
folderPath= Objects.requireNonNull(FileDataSource.class.getResource("/ml-100k")).getPath();
List<UserDTO> userList = Lists.newArrayList();
try {
FileInputStream out = new FileInputStream(folderPath+"\\u.user");
InputStreamReader reader = new InputStreamReader(out, StandardCharsets.UTF_8);
BufferedReader in = new BufferedReader(reader);
String line = null;
String line;
while ((line = in.readLine()) != null) {
String newline = line.replaceAll("[\t]", " ");
String[] ht = newline.split("\\|");
@@ -89,20 +89,18 @@ public class FileDataSource {
/**
* 方法描述: 读取电影数据
*
* @param
* @Return {@link List<ItemDTO>}
* @throws
* @author tarzan
* @date 2020年07月31日 16:54:22
*/
public static List<ItemDTO> getItemData() {
folderPath=new FileDataSource().getClass().getResource("/ml-100k").getPath();
folderPath= Objects.requireNonNull(FileDataSource.class.getResource("/ml-100k")).getPath();
List<ItemDTO> itemList = Lists.newArrayList();
try {
FileInputStream out = new FileInputStream(folderPath+"\\u.item");
InputStreamReader reader = new InputStreamReader(out, StandardCharsets.UTF_8);
BufferedReader in = new BufferedReader(reader);
String line = null;
String line;
while ((line = in.readLine()) != null) {
String newline = line.replaceAll("[\t]", " ");
String[] ht = newline.split("\\|");

View File

@@ -1,4 +1,4 @@
package com.tarzan.recommend.Service;
package com.tarzan.recommend.service;
import com.tarzan.recommend.core.CoreMath;
import com.tarzan.recommend.dto.ItemDTO;
@@ -10,9 +10,8 @@ import java.util.stream.Collectors;
/**
* 推荐服务
*
* @author liu yapeng
* @author TARZAN
* @version 1.0
* @copyright (c) 2019 LuoYang TuLian Co'Ltd Inc. All rights reserved.
* @date 2020/7/31$ 16:18$
* @since JDK1.8
*/
@@ -21,9 +20,8 @@ public class Recommend{
/**
* 方法描述: 猜你喜欢
*
* @param
* @param userId 用户id
* @Return {@link List<ItemDTO>}
* @throws
* @author tarzan
* @date 2020年07月31日 17:28:06
*/
@@ -31,8 +29,7 @@ public class Recommend{
CoreMath coreMath = new CoreMath();
List<RelateDTO> data= FileDataSource.getData();
List<Integer> recommendations = coreMath.recommend(userId, data);
List<ItemDTO> itemList= FileDataSource.getItemData().stream().filter(e->recommendations.contains(e.getId())).collect(Collectors.toList());
return itemList;
return FileDataSource.getItemData().stream().filter(e->recommendations.contains(e.getId())).collect(Collectors.toList());
}