大家好,很高兴和大家分享源码。不管是什么样的需求。都希望各位计算机专业的同学们有一个提高。 大家可以通过常用的搜索引擎,以百度为例,搜索 源码乐园 code51 ,然后再次搜索 自己想要的即可。更多的管理系统等,欢迎大家百度搜索源码乐园。
项目运行截图
部分说明
资料说明
基于余弦定理实现商品推荐系统Java版本,几乎每个人都已经在使用了,如果你是一个购物狂你肯定使用过淘宝,每个人的首页肯定是不一样的,为什么我的首页关于电子产品的比较多,因为我搜索过;如果你喜欢听音乐,不难发现,也会根据你所听过的歌,给你推荐一些类型相似的歌;如果你喜欢看电视或着电影,会根据你在看的和历史看的记录,给你推荐一些相似的视频;如果你经常泡在博客系统或者其他看书的网站会发现也会有推荐;等等,这些都是推荐,只是推荐的方法不一样。可以根据用户的特征推荐,也可以根据物品的特征推荐。这就是传说中的 基于用户 的推荐系统和 基于物品 的推荐系统。
package com.recommender;
import com.db.DBHelp;
import com.entity.MemberUser;
import com.entity.ProductOrder;
import com.entity.ProductTable;
import com.entity.UserR;
import com.util.MapSortUtil;
import com.util.QJ;
import java.util.*;
public class RecommenderSystem {
RecommenderSystem(){
login(2);
}
//推荐算法开始
/**
* 登录后推荐接口
* @param userId 模拟登录的用户ID
*/
public void login(Integer userId){
//1,使用该用户的名字获取订单信息
System.out.println("----------------");
//查询登录用户的订单信息
List<ProductOrder> productOrderList = DBHelp.getProductOrderList(userId);
//存储个人 购买的所有的商品id
Integer[] ints = new Integer[productOrderList.size()];
//存储个人信息,封装成对象,方便计算
UserR userR = new UserR();
//筛选出来个人订单中的商品的id
System.out.println("个人的:");
for (int i = 0; i < productOrderList.size(); i++) {
ints[i] = productOrderList.get(i).getProduct_id();
System.out.println(productOrderList.get(i).toString());
}
userR.setUserId(productOrderList.get(0).getUser_id());
userR.setProductIds(ints);
//2,拿到所有用户的订单信息
List<ProductOrder> productOrderLists = DBHelp.getProductOrderList(null);
//存储所有人的订单信息
List<UserR> userRS = new ArrayList<>();
//利用map的机制,计算出来其余用户的所有的购买商品的id Map<用户id,商品ID拼接的字符串(1,2,3,4)>
Map<Integer,String> map = new HashMap<>();
System.out.println("所有人的:");
//筛选出来订单中的商品的id
for (int i = 0; i < productOrderLists.size(); i++) {
System.out.println(productOrderLists.get(i).toString());
map.put(productOrderLists.get(i).getUser_id(),
map.containsKey(productOrderLists.get(i).getUser_id())?
map.get(productOrderLists.get(i).getUser_id())+","+productOrderLists.get(i).getProduct_id():
productOrderLists.get(i).getProduct_id()+"");
}
//开始封装每个人的数据
for (Integer key:map.keySet() ) {
//new出来一个新的个人的对象,后面要塞到list中
UserR userR2 = new UserR();
//把其他每个人购买的商品的id 分割成数组
String[] split = map.get(key).split(",");
//转换成int数组 进行存储,方便后期计算
Integer[] ints1 = new Integer[split.length];
for (int i = 0; i < split.length; i++) {
ints1[i] = Integer.valueOf(split[i]);
}
//用户id 就是key
userR2.setUserId(key);
//用户购买的商品id的数组
userR2.setProductIds(ints1);
//塞到list中
userRS.add(userR2);
}
//二值化 处理数据
List<UserR> userRList = jisuan(userR, userRS);
System.out.println("得出的结果:");
for (int i = 0; i < userRList.size(); i++) {
System.out.println(userRList.get(i).toString());
}
System.out.println("过滤处理数据之后:");
//过滤处理
String sqlId = chuli(userRList, userR);
System.out.println("推荐的商品:");
//通过拿到的拼接的被推荐商品的id,去查数据库
List<ProductTable> productList = DBHelp.getProductList(sqlId);
//最终拿到被推荐商品的信息
for (int i = 0; i < productList.size(); i++) {
System.out.println(productList.get(i).toString());
}
}
/**
* 过滤处理
* @param userRList 所有用户的订单数据
* @param userR 当前登录用户的订单数据
* @return
*/
private String chuli(List<UserR> userRList,UserR userR) {
//为了方便下面过滤数据,预先把登录用户的订单购物的商品的id做一个map,在过滤的时候,只需要查一下map中是否存在key就ok
Map<Integer,Integer> map1 = new HashMap<>();
for (int i = 0; i < userR.getProductIds().length; i++) {
map1.put(userR.getProductIds()[i],userR.getProductIds()[i]);
}
//盛放最终过滤出来的数据 Map<商品id,出现的次数>
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < userRList.size(); i++) {
//userRList.get(i).getCos_th()>0:过滤掉相似度等于0,也就是完全不匹配的
//userRList.get(i).getUserId()!=userR.getUserId():过滤掉当前用户的订单信息
if(userRList.get(i).getCos_th()>0 && userRList.get(i).getUserId()!=userR.getUserId()){
//求当前登录用户的购买商品的id和其他用户的所购买商品的差集,例如:A=[1, 2],B=[1, 2, 3] 那么这个3就是最终想要的结果
Integer[] j = QJ.getC(userRList.get(i).getProductIds(), userR.getProductIds());
//遍历求差集之后的结果
for (int i1 = 0; i1 < j.length; i1++) {
//如果其余的用户所购买撒谎那个品的id不在当前用的所购买商品的id,那么就存起来
if(!map1.containsKey(j[i1])){
//存储时,数量每次都+1,方便后面排序,出现的次数多,说明被推荐的机会越高
map.put(j[i1],map.containsKey(j[i1])?(map.get(j[i1])+1):1);
}
}
}
}
System.out.println("处理之后的map:");
for (Integer key:map.keySet()) {
System.out.println("商品id="+key+"--用户所购数量="+map.get(key));
}
//把map进行降序排序
Map<Integer, Integer> map2 = MapSortUtil.sortByKeyDesc(map);
System.out.println("按降序" + map2);
//拼接成一个sql,方便去查数据库
String sqlId = "";
for (Integer key:map2.keySet()) {
sqlId = sqlId+key +",";
}
sqlId = sqlId.substring(0,sqlId.length()-1);
System.out.println("最终拿到的被推荐给当前用户的商品id--->"+sqlId);
return sqlId;
}
/**
* 二值化 处理数据
* @param userR 当前登录用户的订单信息
* @param userRS 其他用户的订单信息
* @return 二值化处理之后的结果
*/
private List<UserR> jisuan(UserR userR, List<UserR> userRS) {
//对个人做二值化处理,为了好计算 [0,0,0,0,0,1,1,0,1]这种
//个人的
int userErzhihua[] = new int[10];
for (int i = 0; i < userR.getProductIds().length; i++) {
userErzhihua[userR.getProductIds()[i]]=1;
}
//库里所有人的
int erzhihua[] = new int[10];
//对其他人,做二值化处理,为了好计算 [0,0,0,0,0,1,1,0,1]这种
for (int i = 0; i < userRS.size(); i++) {
UserR product = userRS.get(i);
for (int j = 0; j < product.getProductIds().length; j++) {
erzhihua[product.getProductIds()[j]]=1;
}
//计算当前登录用户与其余每个人的余弦值 cos_th
Double compare = compare( erzhihua,userErzhihua);
product.setCos_th(compare);
//把计算好的值,重新塞到原来的位置,替换到旧的数据
userRS.set(i,product);
//防止数组中的值重复,起到清空的作用
erzhihua = new int[10];
}
return userRS;
}
/**
* 代码核心内容
* @param o1 当前登录用户的
* @param o2 其他用户的 n1 n2 n3 n4 n....
* @return
*/
private static Double compare(int[] o1, int[] o2) {
//分子求和
Double fenzi = 0.0 ;
for (int i = 0; i < o1.length; i++) {
fenzi += o1[i]*o2[i];
}
//分母第一部分
Double fenmu1 = 0.0;
for (int i = 0; i < o1.length; i++) {
fenmu1 += o1[i] * o1[i];
}
fenmu1 = Math.sqrt(fenmu1);
//分母第二部分
Double fenmu2 = 0.0;
for (int i = 0; i < o2.length; i++) {
fenmu2 += o2[i] * o2[i];
}
fenmu2 = Math.sqrt(fenmu2);
return fenzi / (fenmu1 * fenmu2);
}
public static void main(String[] args) {
new RecommenderSystem();
}
}
|