“购买过该商品的用户还购买了”的商品推荐功能实现

来源:互联网 发布:软件测试原理 编辑:程序博客网 时间:2024/04/29 20:29

该功能是基于数据库中persona_order表实现的,该表记录了用户的id以及该用户购买过的商品,主要思路如下:


package bubugao.com.productRecommendation;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;import java.util.Map.Entry;import net.sf.json.JSONArray;import net.sf.json.JSONObject;/* * function:创建买了又买的模型,并将模型导入数据库 * author:shiwei */public class BuyAgain {protected Map<String,HashMap<String,Integer>> dataMap;//对应用户及其所购买过的商品和数量protected static HashMap<String,ArrayList<String>> proUsersMap;//对应商品及其购买该商品的用户protected HashSet<String> productsIdSet;//商品id集protected HashMap<String,String>  products;//商品id_nameprotected static LinkedHashMap<String,Float> userTreeMap;//基于用户比例,保存对应的结果,--productId_ratioprotected static LinkedHashMap<String,Float> itemTreeMap;//基于商品比例,保存对应的结果,--productId_ratioArrayList<String> productTopNIds;public static void main(String[] args) {// TODO Auto-generated method stubString tableName="bi_product_order_product";new BuyAgain().modelImport(tableName,30);}public BuyAgain(){long time1=System.currentTimeMillis();this.getDataMap();long time2=System.currentTimeMillis();System.out.println("获取数据库所需时间"+(time2-time1)+"ms");this.getProUsersMap();long time3=System.currentTimeMillis();System.out.println("固定统计p_users的时间"+(time3-time1)+"ms");}//基于用户比例推荐商品public void buyAgainByUser(String productId,int topN){ArrayList<String> userList=this.getUsersByProductId(productId);HashMap<String,Float> productsNUserRatioMap=this.getProductsUserRatioMap(userList,productId);userTreeMap=this.getTopNProductsMap(productsNUserRatioMap, topN);}//基于商品比例推荐商品public void buyAgainByProduct(String productId,int topN){ArrayList<String> userList=this.getUsersByProductId(productId);HashMap<String,Integer> productNumMap=this.getProductsMap(userList,productId);HashMap<String,Float> productsNumRatioMap=this.getProductsNumRatioMap(productNumMap);itemTreeMap=this.getTopNProductsMap(productsNumRatioMap, topN);}//从数据库中获取数据,存入Map中public void getDataMap(){dataMap=new HashMap<String,HashMap<String,Integer>>();products=new HashMap<String,String>();JDBCConnection jc=new JDBCConnection();jc.startMySQLConn();      String sql = "select * from bi_persona_order";               try {                ResultSet rs=  jc.selectSQL(sql); while (rs.next()){ HashMap<String,Integer> productsMap=new HashMap<String,Integer>(); String userId=rs.getString(2); //获取用户id String productsTemp=rs.getString(3);//获取用户id对应的Json JSONObject jsonObj = JSONObject.fromObject(productsTemp); Iterator<String> keys = jsonObj.keys(); String key = null;     String value = null;           while (keys.hasNext()) {                                     key = (String) keys.next();            value = jsonObj.getString(key);                        JSONObject jsonObj1  =(JSONObject)jsonObj.get(key);            String num = jsonObj1.getString("num");            String name=jsonObj1.getString("name");                        //System.out.println(key+"===>"+num+name);            if(!num.equals("0")){              productsMap.put(key, Integer.parseInt(num));              products.put(key, name);            }                  }        if( productsMap!=null){         dataMap.put(userId,  productsMap);        }                } System.out.println("从数据库获取的数据条数是:"+dataMap.size()); System.out.println("所有商品种类数是:"+products.size());} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}        jc.closeMySQLConn();        }//获取product_users Map,key=productId-商品id,value=usersList-购买过该商品的用户public void getProUsersMap(){    proUsersMap=new HashMap<String,ArrayList<String>>();    productsIdSet=new HashSet<String>();//保存商品的ID    Iterator<Entry<String,String>> iter=products.entrySet().iterator();    Entry<String,String> entry;    while(iter.hasNext()){    entry=iter.next();    String productId=entry.getKey();    productsIdSet.add(productId);    }//System.out.println("所有商品的种类数:"+productsIdSet.size());Iterator<String> iterSet=productsIdSet.iterator();while(iterSet.hasNext()){//遍历商品productsIdSetString proId=iterSet.next();ArrayList<String> userList=new ArrayList<String>();//创建对应的Users集Iterator<Entry<String, HashMap<String,Integer>>> iter2= dataMap.entrySet().iterator();//重新遍历dataMap,获取用户集的idEntry<String, HashMap<String,Integer>> entry2;while(iter2.hasNext()){entry2=iter2.next();String userId=entry2.getKey();Iterator<Entry<String,Integer>> productIter2=entry2.getValue().entrySet().iterator();Entry<String,Integer> productEntry2 ;while(productIter2.hasNext()){ productEntry2=productIter2.next(); String pid= productEntry2.getKey(); Integer num= productEntry2.getValue(); if( proId.equals(pid)&&num!=0){ userList.add(userId); break; }}}proUsersMap.put(proId, userList);}}//将模型结果导入数据库public void  modelImport(String tableName,int topN){JDBCConnection jc=new JDBCConnection();jc.startMySQLConn();//模型导入前先清空表中的数据String sql="truncate table "+tableName;jc.deleteSQL(sql);//按用户比例导入Iterator<String> iterIdSet=this.productsIdSet.iterator();while(iterIdSet.hasNext()){String pId=iterIdSet.next();//System.out.println("基于用户的Id="+pId);this.buyAgainByUser(pId,topN);Iterator<Entry<String,Float>> iterUser=this.userTreeMap.entrySet().iterator();Entry<String,Float> entryUser;JSONObject jsonObject1 = new JSONObject();JSONArray jsonArray1 = new JSONArray();while(iterUser.hasNext()){entryUser=iterUser.next();jsonArray1.put(entryUser.getKey());}if(jsonArray1.length()!=0){ jsonObject1.put("pro_id", jsonArray1); String sql1="insert into "+tableName+"(product_id,by_user) values"+"(" +Long.parseLong(pId)+",'" +jsonObject1.get("pro_id").toString()+"')"; jc.insertSQL(sql1);}}//按商品比例导入Iterator<String> iterIdSet2=this.productsIdSet.iterator();while(iterIdSet2.hasNext()){String proId=iterIdSet2.next();//System.out.println("基于Item的Id="+proId);this.buyAgainByProduct(proId,topN);Iterator<Entry<String,Float>> iterItem=this.itemTreeMap.entrySet().iterator();Entry<String,Float> entryItem;JSONObject jsonObject2 = new JSONObject();JSONArray jsonArray2 = new JSONArray();while(iterItem.hasNext()){entryItem=iterItem.next();//System.out.println(entryItem.getKey()+" "+entryItem.getValue());jsonArray2.put(entryItem.getKey());}if(jsonArray2.length()!=0){jsonObject2.put("pro_id", jsonArray2); String sql2="update "+tableName+" set by_item="+"( '" +jsonObject2.get("pro_id").toString()+"') where product_id="+Long.parseLong(proId);jc.insertSQL(sql2);}} jc.closeMySQLConn();}//根据商品id,获取购买过该商品的用户集public ArrayList<String> getUsersByProductId(String  productId){if(productsIdSet.contains(productId)){ArrayList<String> usersList=new ArrayList<String>();Iterator<Entry<String,ArrayList<String>>> iter=proUsersMap.entrySet().iterator();Entry<String,ArrayList<String>> entry;while(iter.hasNext()){entry=iter.next();if(productId.equals(entry.getKey())){usersList=entry.getValue();break;}}//System.out.println("购买该商品的用户有"+usersList.size()+"个用户");    return usersList;}else{System.out.println("该商品id="+productId+"不在购买商品集中!");return null;}}//根据用户集,得到产品集合及其对应数量public HashMap<String,Integer> getProductsMap(ArrayList<String> usersList,String pId){HashMap<String,Integer> productsNumMap=new HashMap<String,Integer>();    if(usersList!=null){    for(int i=0;i<usersList.size();i++){//遍历用户集    String userId=usersList.get(i);//获取用户id    Iterator<Entry<String, HashMap<String,Integer>>> iter= dataMap.entrySet().iterator();//重新遍历dataMap,获取用户集的id    Entry<String, HashMap<String,Integer>> entry;    while(iter.hasNext()){    entry=iter.next();    String userid=entry.getKey();    if(userId.equals(userid)){    Iterator<Entry<String,Integer>> productIter=entry.getValue().entrySet().iterator();    Entry<String,Integer> productEntry ;    while(productIter.hasNext()){     productEntry=productIter.next();     String pid= productEntry.getKey();      int   pnum= productEntry.getValue();     if(!productsNumMap.containsKey(pid)){     productsNumMap.put(pid, pnum) ;     }else{    int numTemp=productsNumMap.get(pid);    int num=pnum+numTemp;    productsNumMap.put(pid, num);         }    }    break;    }        }        }    }    productsNumMap.remove(pId);   return  productsNumMap;}//根据用户集,得到商品集合及其对应购买商品的用户数量public HashMap<String,Float> getProductsUserRatioMap(ArrayList<String> usersList,String pId){HashMap<String,Float> productsNUserRatioMap=new HashMap<String,Float>();HashSet<String> productSet=new HashSet<String>(); //购买指定商品的所有用户购买的其他商品集for(int i=0;i<usersList.size();i++){String userId=usersList.get(i);Iterator<Entry<String,ArrayList<String>>> iter= proUsersMap.entrySet().iterator();Entry<String,ArrayList<String>> entry;while(iter.hasNext()){entry=iter.next();String productId=entry.getKey();ArrayList<String> users=entry.getValue();if(users.contains(userId)){productSet.add(productId);}}}   Iterator<String> iter=productSet.iterator();while(iter.hasNext()){String pid=iter.next();int userNo=0;    ArrayList<String> userAllList=proUsersMap.get(pid);    for(int j=0;j<userAllList.size();j++){    String user=userAllList.get(j);    if(usersList.contains(user)){    userNo++;    }    } float ratioTemp=userNo/(float)usersList.size();    float ratio= (float)(Math.round(ratioTemp*10000))/10000;    productsNUserRatioMap.put(pid, ratio);}productsNUserRatioMap.remove(pId);   return  productsNUserRatioMap;}//根据productsNumMap 商品—数量Map  获取商品——比例Mappublic HashMap<String,Float> getProductsNumRatioMap(HashMap<String,Integer>  productsNumMap){HashMap<String,Float> productsNumRatioMap=new HashMap<String,Float>();Iterator<Entry<String,Integer>> iter1= productsNumMap.entrySet().iterator();Entry<String,Integer> entry1;int sum=0;//统计总共的商品数while(iter1.hasNext()){entry1=iter1.next();sum+=entry1.getValue();}System.out.println("用户集中买了又买的商品总数:"+sum);Iterator<Entry<String,Integer>> iter2= productsNumMap.entrySet().iterator();Entry<String,Integer> entry2;while(iter2.hasNext()){entry2=iter2.next();String productId=entry2.getKey();float ratioTemp=entry2.getValue()/(float)sum;float ratio = (float)(Math.round(ratioTemp*10000))/10000;//浮点型保留4位小数//System.out.println("ratioTemp="+ratioTemp+" "+"ratio"+ratio);productsNumRatioMap.put(productId, ratio);}return productsNumRatioMap;}//返回topN的产品ID;public void getTopNProducts(HashMap<String,Float> productNumMap,int topN){    productTopNIds=new ArrayList<String>(); ByValueComparator bvc = new ByValueComparator(productNumMap); List<String> keys = new ArrayList<String>(productNumMap.keySet()); int i=0;     Collections.sort(keys, bvc);     for(String key : keys) {     if(i<topN){     productTopNIds.add(key);     // System.out.println("topN的商品id"+key);     i++;     }else{     break;     }        //System.out.printf("%s -> %d\n", key, productNumMap.get(key));     }    // return productTopNIds;}//对结果集进行排序并获取topN的结果public LinkedHashMap<String,Float> getTopNProductsMap(HashMap<String,Float> productNumMap,int topN){LinkedHashMap<String,Float> resultTreeMap=new LinkedHashMap<String,Float>(); //System.out.println("用户集中买了还买商品种数是:"+productNumMap.size()); ByValueComparator bvc = new ByValueComparator(productNumMap); List<String> keys = new ArrayList<String>(productNumMap.keySet()); int i=0; System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");    Collections.sort(keys, bvc);    for(String key : keys) {    if(i<topN){    float num=productNumMap.get(key);   // System.out.println("排名前"+(i+1)+"名的是"+key+" "+ productNumMap.get(key));    resultTreeMap.put(key, num) ;    i++;    }else{    break;    }    }    return  resultTreeMap;}//内部类,用来将hashMap根据value进行排序static class ByValueComparator implements Comparator<String> {  HashMap<String, Float> base_map;  public ByValueComparator(HashMap<String, Float> base_map) {      this.base_map = base_map;  }  public int compare(String arg0, String arg1) {      if (!base_map.containsKey(arg0) || !base_map.containsKey(arg1)) {          return 0;      }      if (base_map.get(arg0) < base_map.get(arg1)) {          return 1;      } else if (base_map.get(arg0) == base_map.get(arg1)) {          return 0;      } else {          return -1;      }  }}}



0 0