基于余弦定理实现商品推荐系统Java版本

本文介绍了一个基于余弦定理的Java版商品推荐系统,该系统能够根据用户购买历史,利用二值化处理和余弦相似度计算,为用户推荐可能感兴趣的商品。通过比较不同用户购买商品的相似度,筛选出与目标用户购买行为最接近的商品,实现个性化推荐。主要涉及数据处理、推荐算法和数据库查询操作。
摘要由CSDN通过智能技术生成

大家好,很高兴和大家分享源码。不管是什么样的需求。都希望各位计算机专业的同学们有一个提高。
大家可以通过常用的搜索引擎,以百度为例,搜索 源码乐园 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();
    }




}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值