Hello, and welcome to the next part of our Capstone Project. You'll leverage the power of Java interfaces to make things more efficient and more general, while using software design principles you've seen before. You wrote code to find recommendations for all movies. Although you could specify the number of rater views in calculating averages, using all movies is too general. Suppose you just want recommendations for new movies, like those after 2012 or for action movies, or romances, or comedies. Or even for movies under two hours directed by Steven Spielberg. In this part of the capstone, you'll be able to get just such recommendations. At the same time, you'll make the code more efficient for accessing movie information and rating information about movies. You'll use a HashMap rather than an ArrayList. This will allow your program to find a movie, given its ID immediately, rather than looping through an ArrayList. In making your programs more general and more efficient you'll be using Java interfaces, and you'll practice the open closed principle of extending the program while insuring the modifications aren't externally visible whenever that's possible. The first modification you'll do is to refactor the Rater.java class. Refactoring means you won't add new functionality. And you'll make minimal or no changes to the external interface, what's called the API of the existing class. Refactoring is an important part of making code more readable, more efficient and more maintainable. The current coding Rater.java stores rating objects in an ArrayList. To find a rating for the movie whose ID is 1201607, or even whether there is a rating for a movie with that ID. The code in Rater.java loops over the ArrayList of rating objects. This will be inefficient with thousands of raters who each might rate hundreds of movies. So, I'll work to change this approach while minimizing visible changes to other parts of the program that use rater objects. The first step in refactoring is to create an interface rather than a class. To create an efficient rater, while minimizing other changes, we'll first create this interface rather than a class. We'll make a copy of Rater.java and we'll call it PlainRater.java. We'll need to change the code in that class so the constructor is named appropriately. Then we'll create an interface out of Rater.java by removing the method implementations leaving the interface you see here with just the method declarations. We'll see what else needs to change in our recommendation framework after creating the rater interface. Programs rely on rater as a type in reading data and creating recommendations, that code will largely still work. The code to rate make recommendations for example calls has rating and get rating, those calls will still work. The code to rerating data will need to change. The creation of the rater objects will need to use plain rater in creation. But assign the reference to the new object created to a variable whose type is rater. This single line is the only change needed to make the code work. We've minimized the changes to client programs by creating an interface. The program was open to extension with minimal modification. Now we can create an EfficientRater.java class and use this new version in the recommendation framework. The interface will be the same, but has rating, and get rating will be efficient. Because they'll search in a HashMap for a rating ID rather than looping over an ArrayList. The only line we need to change is the creation of an efficient rater object, which is a side to the rater you see here. We've used an interface to make code efficient. We'll use the filter interface to get better recommendations. You've seen an interface like this Filter.java before in searching through earthquake data. We'd like to filter movies, like getting those created after 2012 or those over three hours long, or those that are action adventure movies. How will we create filters like the year after filter shown here, or a genre filter shown here. These constructors look minimal. But we'll need to think about how the satisfies method works in a filter class that you implement. How will the satisfies method look up a movie given the movie's ID to determine if the movie meets the filter specification, like weather the movie was created after 2012. The year here is in an instance variable, but how will the movie with a given ID be accessed? Access to movies must be given via a filter's constructor or accessed some other way. To keep things simple and efficient, we'll create and use a movie database class that allows efficient queries given a movie ID. This will be both efficient and easy to use in our filter classes as well as by the other classes in our recommendation framework. The class MovieDatabase is an efficient, though simple, class that helps in writing code to access movie information. The class is designed to be easy to use but also very efficient. In these ways it's similar to a simple database. The same concept is used in EfficientRater in which a movies ID is a key in a HashMap to access movie information used in the MovieDatabase class. The movie ID is the key. But now the movie is the corresponding value rather than a rating, as was the case in EfficientRater.java. All the methods in the movie database class are static. So no movie database objects are created using new. Instead access to movies is provided via static methods. Just as math.square root and other math functions are used without creating a math object. Conceptually, the classes like a real database supporting queries based on movie IDs as keys and returning one movie or all those that satisfy, or pass a filter. When you've all these recommendations, you'll have use filters, interfaces and created efficient database classes. In the new recommendation framework, movies won't be access via an instance variable, that's an ArrayList of movie objects as you did before. Instead the static MovieDatabase.filterBy method is used to get all movie IDs that satisfy a filter. This method returns an array list of movie IDs. To get all movies, you'll pass a filter that always returns true. So every movie satisfies this filter. In the code you start with, this is the true filter class. You'll be able to get other kinds of recommendations by looking for averages of something like romance movies created on or after 2012. You can create a year after filter for example as shown here. And a GenreFilter as shown here to find romance movies. Then these filters can be added to an AllFilters object that combines several filters into a single filter. After adding the GenreFilter and the YearFilter, the average recommendations shows romance movies on or after 2012 as seen in this list of recommendations. These recommendations are generated by using the power of Java interfaces. And refactoring code to help insure that already tested programs continue to work even in new contexts. Adding more efficient code is an extra bonus here. Happy programming.