See the assignment on github.
This assignment has been the hardest so far, I had to read a lot of documentation to complete this one.
I had to learn about these things:
- About the Scanner class, for reading files and receiving input from the console.
- About the Set interface and HashSet class, to use it like a dictionary in Python.
- About the Map interface and HashMap class.
- About how the String class operates and some methods.
- About CharSequence, just because String is an implementation of CharSequence.
- About handling Exceptions, for the file reading and the MovieQuery class.
- And finally, a little bit about regular expressions, for reading the query.
So when I read the the document in the link of the assignment, it says that we need to do set operations, and I found this on stack overflow.
It turns out that I didn’t need to implement any of the code for set operations, just imported the Set interface and the HashSet class.
The Set interface contains the methods addAll, retainAll and removeAll, which are equivalent to union, intersection and difference set operations, respectively. But the problem said: find the set of actors that the given movies don’t have in common. (or something by the way).
And so, this is equivalent to the difference of the union and the intersection of two sets. (A ∪ B) – (A ∩ B). And this is called the symmetric difference.
So I first created the Movie class and wrote several constructors supporting different data types, because why not. It has two fields, a String; representing the name of the movie, and a Set of Strings; representing the name of the actors. I wrote the methods for the operations I described above. It doesn’t makes much sense because it’s just returning the result of the call to the set methods, but at least I gave these methods a fancier name. But it makes sense in the getActorsNotInCommon method, because the symmetric difference is not implement in the Set interface. I also added getters and setters and bla bla bla.
Before using the File class I tested it.
But the code would not compile, and then, reading the docs of the File class, I realized I had to add “throws Exception” after the method parameters.
And there are a lot of different implementations of the Exception interface.
In the MovieLibrary class I used a Scanner to read the file where are the actors and movies. And the constructor can throw a FileNotFoundException, and it has to, because the File class can, and so the code where it is used has to as well. The class has a field for storing the movie objects in a Map, using its name as the key, so the program has to store the name of the movie twice, and I though it was stupid, but I didn’t found a better way to do it, but now I’m wondering if it is possible to use something like a pointer to the variable inside the Movie object, to use it as the key of the HasMap, but whatever.
And the code for reading the file with the scanner:
In the constructor of the MovieLibrary two scanners are used, one for reading the lines of the file, and another one for reading that line and separate the actor and movies, and then instantiating a Movie object -only if the name was not already in the map- and then pushing it into that map.
This class use the methods of the Movie class in all the methods.
And I tested what I had written up to this point, before moving into implementing the user input:
Then I was writing the main class, TheMovies, according to the description in the assignment (with the menus and option and shit). When I reached the part where says that I should ask the user for an input like: “movieName symbol moviewName”, I realized that it would be too much code, and it would be a mess with all the logic of user input, String processing and the use of the MovieLibrary class. So I decided to write another class.
In the MovieQuery class, given the description of the problem, I though I would need to use Regular Expressions somehow. I found this nice page to learn and test regular expressions.
I didn’t wanted for this class to be instantiated, and I was thinking of something like a “static class”, but it turns out there is no such thing, at least in the Java programming language, but you can simulate this behavior by adding some modifiers, like making the constructor private and some static methods and fields.
The class use a Scanner, with a regex delimiter like this: “( )|&^“. And what this is telling to the scanner is that it should identify a substring of that format, “()” means that the thing inside the parenthesis must appear in the string and the “” means that there must be any of the characters inside the braces. And by doing this, when I call the next() method of the scanner it returns the name of the first movie and calling next() again will return the second movie name.
When it finds the two name of the movies it searches for them in the MovieLibrary, and, if some of the movies is not there, throws an RuntimeException, because I don’t want neither keep executing the code nor return an empty Set.
It searches for which command is in the input, calls the appropriate method in the MovieLibrary instance and returns the result.
And so the only thing the TheMovies class does is using the previous classes to ask and execute the user input.
And here’s the output produced by the command line.