您的位置:首页 > 其它

“浏览过该商品的用户还浏览了”的商品推荐

2015-07-31 11:19 211 查看
该功能是基于数据库中persona_product表实现的,该表记录了用户的id以及该用户浏览过的商品,主要思路如下:



该功能主要用java实现,源代码如下:

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 BrowseAgain {

protected Map<String,HashMap<String,Integer>> dataMap;//对应用户及其所购买过的商品和数量
protected static HashMap<String,ArrayList<String>> proUsersMap;//对应商品及其购买该商品的用户
protected HashSet<String> productsIdSet;//商品id集
protected static LinkedHashMap<String,Float> userTreeMap;//基于用户比例,保存对应的结果,--productId_ratio
protected static LinkedHashMap<String,Float> itemTreeMap;//基于商品比例,保存对应的结果,--productId_ratio

public static void main(String[] args) {
// TODO Auto-generated method stub
String tableName="bi_product_browse_product";
new BrowseAgain().modelImport(tableName,30);

}

public BrowseAgain(){
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 browseAgainByUser(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 browseAgainByProduct(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>>();
productsIdSet=new HashSet<String>();
JDBCConnection jc=new JDBCConnection();
jc.startMySQLConn();
String sql = "select * from bi_persona_product";
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();
//System.out.println("key="+key);
value = jsonObj.getString(key);
int num=Integer.parseInt(value);
if(num!=0){
productsMap.put(key, num);
productsIdSet.add(key);
}
}
if( productsMap!=null){
dataMap.put(userId, productsMap);
}
}
System.out.println("从数据库获取的数据条数是:"+dataMap.size());
System.out.println("从数据库获取的商品种类数是:"+productsIdSet.size());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
jc.closeMySQLConn();

}

//获取product_users Map,key=productId-商品id,value=usersList-浏览过该商品的用户
public void getProUsersMap(){
proUsersMap=new HashMap<String,ArrayList<String>>();
Iterator<String> iterSet=productsIdSet.iterator();
while(iterSet.hasNext()){//遍历商品productsIdSet
String proId=iterSet.next();
ArrayList<String> userList=new ArrayList<String>();//对应的Users集
Iterator<Entry<String, HashMap<String,Integer>>> iter1= dataMap.entrySet().iterator();//重新遍历dataMap,获取用户集的id
Entry<String, HashMap<String,Integer>> entry1;
while(iter1.hasNext()){
entry1=iter1.next();
String userId=entry1.getKey();
Iterator<Entry<String,Integer>> productIter2=entry1.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.browseAgainByUser(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());
}
jsonObject1.put("pro_id", jsonArray1);
long proId=Long.parseLong(pId.trim());
String sql1="insert into "+tableName+"(product_id,by_user) values"+"("+proId+",'" +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.browseAgainByProduct(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());
}
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;
}

}

//根据用户集,得到产品集合及其对应数量(除去正在浏览的商品id)。
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>>> iter3= dataMap.entrySet().iterator();//重新遍历dataMap,获取用户集的id
Entry<String, HashMap<String,Integer>> entry3;
while(iter3.hasNext()){
entry3=iter3.next();
String userid=entry3.getKey();
if(userId.equals(userid)){
Iterator<Entry<String,Integer>> productIter3=entry3.getValue().entrySet().iterator();
Entry<String,Integer> productEntry3 ;
while(productIter3.hasNext()){
productEntry3=productIter3.next();
String pid= productEntry3.getKey();
int pnum= productEntry3.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 获取商品——比例Map
public 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;
}

public ArrayList<String> getTopNProducts(HashMap<String,Float> productNumMap,int topN){
ArrayList<String> 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;
}

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;
}
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息