package book.task;
import book.dao.BookDao;
import book.dao.BorrowDao;
import book.dao.RecommendDao;
import book.dao.UserDao;
import book.domain.dataobject.*;
import book.domain.exception.BusinessException;
import book.util.LoggerUtil;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.*;
import static com.google.common.collect.Lists.newArrayList;
/**
* @author xlong
* @date 2022-3-25
*/
@Component
public class KMeansRecommendation {
private static final Logger LOGGER = LoggerFactory.getLogger(KMeansRecommendation.class);
@Resource(name = "bookDao")
private BookDao bookDao;
@Resource(name = "userDao")
private UserDao userDao;
@Resource(name = "borrowDao")
private BorrowDao borrowDao;
@Resource(name = "recommendDao")
private RecommendDao recommendDao;
@Resource(name = "transactionTemplate")
private TransactionTemplate transactionTemplate;
private List<String> professionList;
/*
1、用户注册时要求填写年龄,性别,职业;
2、首先计算各个职业之间的相似度P:将看过这本书且职业相同的人的评分求平均值,作为这个职业
(相当于一个用户,有多少个职业类别就有多少个用户)对这本书的评分,然后根据皮尔孙系数求相似度;
3、年龄之间的相似度A:7岁产生代沟的可能性较大,B(u,v)=7/(|Bu-Bv|),当|Bu-Bv|>7时;当|Bu-Bv|≤7时,B(u,v)=1;
4、性别相似度F:相同为0,不相同为1;
5、两个用户之间的距离即为A+F-P;
*/
public void KmeansRecommend()
{
LoggerUtil.info(LOGGER,"enter in KmeansRecommend");
recommendDao.deleteBefore(1);
InitProfession();
//待分类的原始值
List<UserDO> userDOList=userDao.listAllUsers();
//将要分成的类别数
int k=(int)Math.sqrt(userDOList.size());
//定义最大迭代次数
int maxClusterTimes=500;
//迭代次数
int count=1;
//聚类的结果
List<List<UserDO>> clusterList=Lists.newArrayListWithCapacity(k);
for (int i=0;i<k;i++){
clusterList.add(Lists.newArrayList());
}
//质心
List<UserDO> clusterCenteringList=Lists.newArrayList();
//随机选择初始的质心
Collections.shuffle(userDOList);
for(int i=0;i<k;i++)
clusterCenteringList.add(userDOList.get(i));
//计算每个用户最靠近哪个质心,并将其加入相应的类中
boolean Change=true;
while(Change&&count<=maxClusterTimes) {
Change=false;
for (int i = 0; i < userDOList.size(); i++) {
//定义一个最小堆,存放用户到质心的距离
PriorityQueue<Map.Entry<Integer, Double>> priorityQueue = new PriorityQueue<Map.Entry<Integer, Double>>(new Comparator<Map.Entry<Integer, Double>>() {
@Override
public int compare(Map.Entry<Integer, Double> o1, Map.Entry<Integer, Double> o2) {
return (int) (o1.getValue() - o2.getValue());
}
});
Map<Integer, Double> map = Maps.newHashMap();
for (int j = 0; j < k&&j<clusterCenteringList.size(); j++) {
double distance = CalDistance(userDOList.get(i), clusterCenteringList.get(j));
map.put(j, distance);
}
priorityQueue.addAll(map.entrySet());
//从堆顶获得最短距离对应的质心下标,将用户加到对应的质心的那一类中
clusterList.get(priorityQueue.poll().getKey()).add(userDOList.get(i));
}
System.out.println(count);
List<UserDO> newCenterList = CenterUpdate(clusterList);
if(isChange(clusterCenteringList,newCenterList))
{
Change=true;
clusterCenteringList=newCenterList;
}
count++;
System.out.println(count);
}
System.out.println(clusterList);
//销量的最大堆
Queue<Map.Entry<String,Integer>> priorityQueue=new PriorityQueue<>((a,b)->(b.getValue().compareTo(a.getValue())));
Map<String, Integer> bookCountMap=CountSale();
priorityQueue.addAll(bookCountMap.entrySet());
//遍历每一个用户,找出他属于哪一类
//对于这一类中其他用户看过的书,求并集去重
//然后这些书和他看过的书求差集,存放在最小堆里面
for(UserDO userDO:userDOList)
{
//推荐书籍的数量
int recommendCount=0;
priorityQueue.clear();
//兜底,每次都重新计算借阅量最大堆,防止为这个用户推荐的图书不够三本
priorityQueue.addAll(bookCountMap.entrySet());
//记录用户所在类的下标
int ClusterIndex=0;
//扫描每一个类
for(int i=0;i<clusterList.size();i++)
{
//扫描这一类中的用户
for(int j=0;j<clusterList.get(i).size();j++)
{
if(userDO.getUserId()==clusterList.get(i).get(j).getUserId()) {
ClusterIndex=i;
break;
}
}
}
//存放其他其他用户看过的书:bookName-author集合
Set<String> bookSet=Sets.newHashSet();
//该用户自己已经看过的书
Set<String> MyBookSet=Sets.newHashSet();
for(UserDO userDO1:clusterList.get(ClusterIndex))
{
//计算和该用户同一类的其他用户看过的书籍
if(userDO.getUserId()!=userDO1.getUserId())
{
List<BorrowDO> borrowDOList=borrowDao.listByUserId(userDO1.getUserId());
for(BorrowDO borrowDO:borrowDOList)
{
BookDO bookDO=bookDao.queryBookByBookId(borrowDO.getBookId());
bookSet.add(Joiner.on("-").skipNulls().join(bookDO.getBookName(),bookDO.getAuthor()));
}
}
//计算本人已经看过的书籍
else
{
List<BorrowDO> borrowDOList=borrowDao.listByUserId(userDO.getUserId());
for(BorrowDO borrowDO:borrowDOList)
{
BookDO bookDO=bookDao.queryBookByBookId(borrowDO.getBookId());
MyBookSet.add(Joiner.on("-").skipNulls().join(bookDO.getBookName(),bookDO.getAuthor()));
}
}
}
//求出bookSet中有的而MyBookSet中没有的书
bookSet=Sets.difference(bookSet,MyBookSet);
List<BookDO> bookDOList=Lists.newArrayList();
for(String bookAuthor:bookSet)
{
//分离出书名和作者
Iterator<String> iterator = Splitter.on("-").split(bookAuthor).iterator();
List<String> stringList = Lists.newArrayList();
while (iterator.hasNext()) {
stringList.add(iterator.next());
}
//根据书名和作者名查询这本书
List<BookDO> bookDOList1=bookDao.listBooksByAuthorAndName(stringList.get(0),stringList.get(1));
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
基于Mahout协同过滤实现图书推荐系统_书籍推荐系统源码+项目说明.zip 基于协同过滤的书籍推荐系统,图书推荐系统 最新版本,在原先手动计算皮尔逊相似度和评分矩阵的基础上添加了Mahout实现的协同过滤推荐算法. 【备注】 主要针对计算机相关专业的正在做毕设的学生和需要项目实战的Java学习者。 也可作为课程设计、期末大作业。包含:项目源码、数据库脚本、项目说明等,该项目可以直接作为毕设使用。 也可以用来学习参考借鉴!
资源推荐
资源详情
资源评论
收起资源包目录
基于Mahout协同过滤实现图书推荐系统-书籍推荐系统源码+项目说明.zip (114个子文件)
bootstrap.css 143KB
bootstrap.min.css 118KB
animate.css 81KB
bootstrap-theme.css 26KB
bootstrap-theme.min.css 23KB
book_index.css 2KB
glyphicons-halflings-regular.eot 20KB
.gitignore 367B
KMeansRecommendation.java 21KB
MyRecommendation.java 15KB
AdminController.java 14KB
BookInfoServiceImpl.java 9KB
BorrowServiceImpl.java 9KB
BookController.java 7KB
MahoutRecommendation.java 7KB
BorrowController.java 5KB
test.java 5KB
UserServiceImpl.java 4KB
DateUtils.java 4KB
BookDaoImpl.java 4KB
UserController.java 3KB
LoginController.java 3KB
UserDO.java 3KB
UserDaoImpl.java 3KB
BookDTO.java 3KB
PageResult.java 2KB
BookDO.java 2KB
UserDTO.java 2KB
BorrowDaoImpl.java 2KB
RecommendServiceImpl.java 2KB
Recommend.java 2KB
BorrowDO.java 2KB
BorrowDTO.java 2KB
LoggerUtil.java 2KB
LoginServiceImpl.java 2KB
ValidateUtils.java 2KB
RecommendationDO.java 2KB
RecommendDaoImpl.java 2KB
RegisterServiceImpl.java 1KB
UnionBookDaoImpl.java 1KB
RecommendDO.java 1KB
RecommendDTO.java 1KB
ExceptionHandler.java 1KB
TastePrefDaoImpl.java 1KB
BookDao.java 1KB
UnionBookServiceImpl.java 1KB
UnionBookDO.java 1KB
RegisterController.java 1KB
TastePrefDO.java 904B
BusinessException.java 876B
BaseResult.java 842B
BookInfoService.java 777B
UnionBookDao.java 768B
ListAndB.java 757B
TastePrefDao.java 744B
TestKemans.java 700B
BaseObject.java 639B
BorrowDao.java 569B
CommonDao.java 543B
UnionBookService.java 531B
UserDao.java 471B
RecommendDao.java 459B
StatusEnum.java 457B
SimpleResult.java 455B
BorrowService.java 419B
UserService.java 311B
RecommendService.java 238B
LoginService.java 200B
RegisterService.java 134B
show.js 82KB
bootstrap.js 68KB
bootstrap.min.js 36KB
bootstrap-notify.min.js 12KB
iframe.js 5KB
inform.js 1KB
login.js 1KB
npm.js 484B
evaluate.js 16B
admin_multiply.jsp 18KB
admin_index.jsp 17KB
admin_query.jsp 16KB
admin_user.jsp 13KB
reader_myborrow.jsp 9KB
reader_detail.jsp 8KB
admin_order.jsp 7KB
admin_order_name.jsp 7KB
reader_information.jsp 6KB
reader_index.jsp 4KB
register.jsp 3KB
login.jsp 2KB
bootstrap.min.css.map 529KB
bootstrap.css.map 380KB
bootstrap-theme.css.map 47KB
bootstrap-theme.min.css.map 25KB
项目说明.md 547B
db.properties 344B
glyphicons-halflings-regular.svg 106KB
glyphicons-halflings-regular.ttf 44KB
glyphicons-halflings-regular.woff 23KB
glyphicons-halflings-regular.woff2 18KB
共 114 条
- 1
- 2
资源评论
- 枫红沐白2024-03-03资源太好了,解决了我当下遇到的难题,抱紧大佬的大腿~
- 码蜂窝编程官方2023-07-06这个资源总结的也太全面了吧,内容详实,对我帮助很大。
- junkultimate2023-03-04非常有用的资源,可以直接使用,对我很有用,果断支持!Make程序设计2023-06-29感谢对资源的认可!互相学习,加油
Make程序设计
- 粉丝: 5623
- 资源: 3567
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功