该模块的主要思路是将现登录用户的个人信息(包括出行目的地、旅游类型、天数、花费等)与数据库中已有的其他用户信息进行相似度匹配,根据相似度值的大小进行排序,同时获得用户去过的景点,然后推荐给用户。这里的相似度计算采用的是余弦相似度,关于它是什么以及如何计算,我是参考的这个博客(侵删)。
里面是对一段文本先进行分词,但是该模块用到的数据都是像目的地、天数之类的,因此不需要进行分词操作。最后的效果如下:
核心代码:
RecommnedFragment
public class RecommendFragment extends Fragment { private String mCurrentUserName=UserCenterFragment.mUserName; //当前所登陆的用户,一定要保证已经登录,否则可能有问题 private UserLab mUserLab; private static List<SimilarityItem> mSimilarityItems=new ArrayList<>(); private RecyclerView mRecyclerView; public static RecommendFragment newInstance(){ return new RecommendFragment(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v=inflater.inflate(R.layout.fragment_recommend,container,false); mRecyclerView=(RecyclerView)v.findViewById(R.id.recommend_recycler_view); mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); getSimiliarity(mSimilarityItems); // 先准备数据,并进行排序 Collections.sort(mSimilarityItems, new Comparator<SimilarityItem>() { @Override public int compare(SimilarityItem similarityItem, SimilarityItem t1) { return (int) ((t1.getSimilarity()-similarityItem.getSimilarity())*100);//由于这里返回值必须是int型,而相似度都是小数,故先放大100倍 } }); int rank=1; for(SimilarityItem item:mSimilarityItems){ item.setRank(rank); rank++; } setupAdapter(); return v; } private class RecommendHolder extends RecyclerView.ViewHolder{ private TextView mRecommendRank; private TextView mRecommendSimilarity; private TextView mRecommendScenery; public RecommendHolder(View itemView){ super(itemView); mRecommendRank=(TextView)itemView.findViewById(R.id.recommend_rank); mRecommendSimilarity=(TextView)itemView.findViewById(R.id.recommend_similarity); mRecommendScenery=(TextView)itemView.findViewById(R.id.recommend_scenery); } public void bindItem(SimilarityItem item){ mRecommendRank.setText(item.getRank()+""); mRecommendSimilarity.setText("相似度:"+item.getSimilarity()); mRecommendScenery.setText(item.getScenery()); } } private class RecommendAdapter extends RecyclerView.Adapter<RecommendHolder>{ private List<SimilarityItem> mItems; public RecommendAdapter(List<SimilarityItem> items){ mItems=items; } @Override public RecommendHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view =LayoutInflater.from(getActivity()).inflate(R.layout.list_item_recommend,parent,false); return new RecommendHolder(view); } @Override public void onBindViewHolder(RecommendHolder holder, int position) { holder.bindItem(mItems.get(position)); } @Override public int getItemCount() { return mItems.size(); } } public void setupAdapter(){ mRecyclerView.setAdapter(new RecommendAdapter(mSimilarityItems)); } /** * 得到每条记录的相似度及对应景点,存储在Sinilarity类中最后存在容器里 * @param similarityItems */ private void getSimiliarity(List<SimilarityItem> similarityItems){ mUserLab=UserLab.get(getActivity()); List<String> words=mUserLab.getUserWords(mCurrentUserName); List<Words> wordsArray=mUserLab.getTripWordsArray(); CosineSimilarity cosineSimilarity = new CosineSimilarity(); for (Words w:wordsArray){ List<String> words1=w.getWordArray(); SimilarityItem item=new SimilarityItem(); item.setSimilarity(cosineSimilarity.cos(words, words1)); item.setScenery(w.getScenery()); similarityItems.add(item); } } /** * 得到推荐相似度最高的景点数组 * @return */ public static String[] getRecommendSceneries(){ String sceneries=mSimilarityItems.get(0).getScenery(); //获取相似度最高的,也就是排序后的第一个,这里得到的是字符串 sceneries.trim(); String[] recommendSceneries=sceneries.split(","); return recommendSceneries; } }整个工 程的源码在这找!