Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package nearsoft.academy.bigdata.recommendation;


import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.neighborhood.ThresholdUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.UserBasedRecommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;


import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MovieRecommender {
String path;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define right access modifier for class attributes

int repMovies,repUsers;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declaration should go on single line

int user,product,review;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, declaration should go on single lines

HashMap<String, Integer> userId = new HashMap<String, Integer>();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using implementations, use an interface instead

HashMap<String, Integer> products = new HashMap<String, Integer>();
HashMap<Integer,String> productId = new HashMap<Integer,String>();

public MovieRecommender(String pathUrl) throws IOException {
this.path = pathUrl;
convert();
}

public void convert() throws IOException {
this.user=0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initialization should be part of constructor. Also, default values of int attributes is zero

this.product=0;
this.review=0;
this.repMovies=0;
this.repUsers=0;
String idUser="",idProduct="", scoreReview="";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declaration should be single line


BufferedReader reader = new BufferedReader(new FileReader(path));
String line;

String uRegex = "review\\/userId: ([\\D\\d]+)";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can be converted to class attributes

String pRegex = "product\\/productId: ([\\D\\d]+)";
String rRegex = "review\\/score: ([\\D\\d]+)";

Pattern userPattern = Pattern.compile(uRegex);
Pattern productPattern = Pattern.compile(pRegex);
Pattern reviewPattern = Pattern.compile(rRegex);


FileWriter csvWriter = new FileWriter("list.csv");

Matcher matcher;

boolean match;

line= reader.readLine();

while (line != null){

matcher = productPattern.matcher(line);
match = matcher.matches();

if (match){
String[] parts = line.split(": ",2);
idProduct= parts[1];
if(products.containsKey(idProduct))
this.repMovies++;
else{
this.product++;
products.put(idProduct,this.product);
productId.put(this.product,idProduct);
}

}

matcher = userPattern.matcher(line);
match = matcher.matches();

if (match){
String[] parts = line.split(": ",2);
idUser= parts[1];
if(userId.containsKey(idUser))
this.repUsers++;
else{
this.user++;
userId.put(idUser,this.user);
}

}

matcher = reviewPattern.matcher(line);
match = matcher.matches();

if (match){

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see three different if statements for matches, does it mean that a single line can match with all three patterns at the same time?

String[] parts = line.split(": ",2);
scoreReview= parts[1];
this.review++;
}

if(idProduct != "" && idUser != "" && scoreReview != "") {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use equals method to compare Objects

csvWriter.append(userId.get(idUser).toString());
csvWriter.append(",");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using string literals, you can use a static String or an enum

csvWriter.append(products.get(idProduct).toString());
csvWriter.append(",");
csvWriter.append(scoreReview);
csvWriter.append("\n");
idUser="";
idProduct="";
scoreReview="";
}
line=reader.readLine();

}
csvWriter.flush();
csvWriter.close();
reader.close();

}

public int getTotalReviews(){ return this.review; }
public int getTotalProducts(){ return this.product; }
public int getTotalUsers(){ return this.user; }

public List <String> getRecommendationsForUser(String id) throws IOException, TasteException {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this function being called?

DataModel model = new FileDataModel(new File("list.csv"));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid hardcoding file names

UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
UserNeighborhood neighborhood = new ThresholdUserNeighborhood(0.1, similarity, model);
UserBasedRecommender recommender = new GenericUserBasedRecommender(model, neighborhood, similarity);

List<String> recommendations = new ArrayList<String>();

for (RecommendedItem recommendation : recommender.recommend(userId.get(id), 3)) {
recommendations.add(productId.get((int)(recommendation.getItemID())));
}

return recommendations;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class MovieRecommenderTest {
public void testDataInfo() throws IOException, TasteException {
//download movies.txt.gz from
// http://snap.stanford.edu/data/web-Movies.html
MovieRecommender recommender = new MovieRecommender("/path/to/movies.txt.gz");
MovieRecommender recommender = new MovieRecommender("movies.txt");
assertEquals(7911684, recommender.getTotalReviews());
assertEquals(253059, recommender.getTotalProducts());
assertEquals(889176, recommender.getTotalUsers());
Expand Down