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