• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Using Comparator to sort HashMap with ArrayList values

 
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm working on an exercise in the Univ of Helsinki's Java MOOC course and have a problem.  Here are the instructions for part 6 of the problem:
"Create the class FilmComparator in the package reference.comparator. The class FilmComparator has to implement the interface Comparator<Film>, and it has to have the constructor public FilmComparator(Map<Film, List<Rating>> ratings). The class FilmComparator will be used later on to sort films according to their ratings.
The class FilmComparator has to allow for film sorting according to the average of the rating values they have received. The films with the greatest average should be placed first, and the ones with the smallest average should be the last."

The film ratings (words - "GOOD, BAD, etc, of type Rating) are entries in an enumerator class and are associated with numeric values in the class constructor:


The film rating HashMap for the exercise prints like so:
{Gone with the Wind=[FINE], Eraserhead=[BAD], The Bridges of Madison County=[GOOD, BAD]}

So the problem solution appears to be:
1. get the ratings arrayList for each film.
2. call the enum list to get numeric values for each rating in the ArrayList, and compute the average of each ArrayList.
3. use a comparator to sort the arrayList ratings from highest average to lowest average, ensuring that the entire HashMap for each film (i.e. Map<Film, List(<Rating>) is included in the sorting


Here is the code so far:


...and now I'm lost.  I can't directly compare the HashMaps, so I have tried to obtain the ArrayList averages as the first step - but they get "unlinked" from the HashMap and I'm not sure how to address that.  I don't want to "hard code" new HashMaps for o1 and o2, i.e. create a new HashMap named o1Avg (or whatever) with HashMap<Map<Film>, double> o1Avg = new HashMap(); but I think I need some form of new HashMap in the form of <Film, double> (with double being the average value of the film's ratings) in order to use the comparator.  The internet has a million examples of sorting HashMaps by values using comparator, but the fact that the value is a list is really screwing up my day(s).  Thanks in advance for help/suggestions.
 
Al Davis
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Apologies for the double post - the first one didn't seem to go up initially.
Staff note (Henry Wong) :

Duplicate topic has been deleted

 
Marshal
Posts: 79151
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I couldn't find a double post, but we sometimes get that if the forum software gets a migraine.

I am not going to say a lot about your map, but you can't sort a hash map. It sorts by h & c − 1 where h is the K's hash code and c is the capacity of the map, which is always expressible by 2ⁿ. If you want to sort your Map, consider a different Map implementation, which you can read about in the Java™ Tutorials. As for adding Lists, try going through the other Map link in the Java™ Tutorials. I am not certain, but I think that has a List example in.
 
Saloon Keeper
Posts: 10687
85
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Are you able to modify the Film class? If so, I suggest adding a field: avgRating. If not, then you could sort by using a comparator like this.
 
Al Davis
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Campbell - thanks for the rapid response.  I know that HashMaps can't be sorted using the Collections.sort methods, but the problem specified the map structure I've posted ( FilmComparator(Map<Film, List<Rating>> ratings) ) and I'm stuck with it.  I simply don't have a handle on the correct approach to dealing with the ArrayList of values.  Those values are ultimately the sort criteria for the problem, but I don't know the best way to pull out the values and sort them while still maintaining the HashMap's Key/Value pairings.  I can use any intermediate structures needed, but eventually I have to return the names of Films sorted by their average ratings.
 
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Al Davis wrote:I know that HashMaps can't be sorted using the Collections.sort methods, but the problem specified the map structure I've posted ( FilmComparator(Map<Film, List<Rating>> ratings) ) and I'm stuck with it.  



The problem specified that you need to use a Map ... but where does it say that you have to use a HashMap? Why can't you use a Map type that can be sorted?

Henry
 
Carey Brown
Saloon Keeper
Posts: 10687
85
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Henry Wong wrote:The problem specified that you need to use a Map ... but where does it say that you have to use a HashMap? Why can't you use a Map type that can be sorted?


If you were sorting by the key you could use a TreeMap, but that doesn't help you if you need to sort by value.
 
Carey Brown
Saloon Keeper
Posts: 10687
85
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You can't sort a HashMap by value but you can sort Map.Entry<K,V> using a comparator similar to above but using Map.Entry<K,V> as the Comparator type.
 
Saloon Keeper
Posts: 15485
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
No map is appropriate for sorting by value.

I suggest transforming the map to a list of key-value pairs and sorting them by value:
 
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There is talking about sorting a (Hash)Map, but that is not the question. The idea is to create a class FilmComparator, where the comparing of Films must be done based on the list of Ratings, given in the constructor-Map. That means also that that Map can hardly be a TreeMap, since you would need a FilmComparator for that TreeMap (or let the Film class implement Comparable<Film>, but that sorting would be useless for this exercise).

To simplify things, I suggest to add a static method to the Rating enum, that determines the average of a List of Ratings. You could use the avarage method of an IntStream here, but it is easy enough to determine the average "manually".
 
Al Davis
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Henry - a hashMap is what is supplied in the exercise, e.g. {Gone with the Wind=[FINE], Eraserhead=[BAD], The Bridges of Madison County=[GOOD, BAD]}.

Carey and Stephan - converting to a key/value entry set is the approach I've been playing with; it's what the majority of web sites that address sorting HashMaps recommend.  Once that's done, though, I'm still forced to deal with obtaining the individual ArrayList entries for the values so that I can get their averages - this is where I'm breaking down.  How can I get the values, obtain their averages and sort them, while still maintaining the key /value linkage between the film name and its ratings?  As I mentioned above, I don't think hard-coding new hashMaps is a good approach.  Ultimately, I have to return only a list of film names sorted by the order of the average ratings, but not the ratings themselves nor the averages.

Piet - It does seem like figuring the averages in the Rating Enum might simplify things; I haven't tried that yet, but I will.  Any suggestions as to how I should handle re-associating the averages with the HashMap keys?  I'm thinking I'll need to create another map (or a set, or something) to pair up the keys and averages for the actual sort.

 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[quote=Al Davis](...)
Piet - It does seem like figuring the averages in the Rating Enum might simplify things; I haven't tried that yet, but I will.  Any suggestions as to how I should handle re-associating the averages with the HashMap keys?  I'm thinking I'll need to create another map (or a set, or something) to pair up the keys and averages for the actual sort.
[/quote]
You can create a separate Map, if you like. If you have a Map<Film, List<Rating>>, then it is an easy matter to create a Map<Film, Double>, where the Double represents the average value of all the Ratings. If you only want to, say, print the averages, then you can do something like:
[code=java]ratings.forEach((k, v) -> System.out.format("Film: %s, average rating: %f %n", k, Rating.averageRating(v));[/code]
 
Campbell Ritchie
Marshal
Posts: 79151
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Who has told you to use a Map, or even worse, a specific Map implementation? You appear to have some conflicting requirements there.
You mentioned K‑V pairs. All Maps contain K‑V pairs, and in the case of Java® Maps, they are implemented as instances of the Map.Entry<K, V> interface, as you already know. Unfortunately, that doesn't help you sorting your Map. Yes, you can get the entry set, and you can pass that to a Stream and get that Stream sorted; Stephan has shown you an example. Yes, you can use different features of the K‑V pair to do the sorting. Yes, you can put all those pairs into a Set that supports sorting, e.g. TreeSet. Yes, you can transfer all the contents of your Map to a Map supporting sorting, e.g. TreeMap, but (I think) that only supports sorting by the Ks not the Vs. Yes, you can create a Pair class and put each of your Map.Entries into a Pair object, and put those all into sorted lists or sorted sets You can use any features of the K or of the V for sorting if you can get any sort of ordering for it.
But you can't sort a Java® Map by its Vs, nor can you apply any sorting directly to a HashMap. it is however worth searching Google Guava and Apache Commons. I don't know, but they might have a Map implementation with different capabilities, which will do what you want.

In your first post, you wrote:The class FilmComparator has to implement the interface Comparator<Film>, and it has to have the constructor public FilmComparator(Map<Film, List<Rating>> ratings).

That is strange too. It is not usual for a Comparator to have any fields. It is usually implemented as a class with one method (compare(T, T)). I can see how you might want a class that will sort your Films, but that isn't the usual use of a Comparator<Film>. I think, maybe you should query the requirements with whoever gave you them.
 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Again, I do not quite understand this reply. The whole issue is to come up with a class that implements a Comparator<Film>, where the comparing is based on the average rating of a film, supplied by a Map<Film. List<Rating>>.
So, the only thing about Maps is the Map that is input to the FilmComparator class.

That is all. There is no mentioning of 'sorting a HashMap' or similar. Given that we have that FilmComparator class, and let comp be an instance of that class, then we can simply do:
films.sort(comp).
 
Campbell Ritchie
Marshal
Posts: 79151
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Piet Souris wrote:. . . come up with a class that implements a Comparator<Film> . . .
films.sort(comp).

That is my idea of how you use a Comparator. So why pass a Map to its constructor?
 
Carey Brown
Saloon Keeper
Posts: 10687
85
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
 
Al Davis
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Maybe I need to clarify things a little bit.

In the 1st paragraph of my original post I have included, in quotation marks, the complete set of instructions I have for this section of the problem.

The Rating Enum class instructions (from an earlier section of the problem) are :
"Create the enumerated type Rating in reference.domain. The enum class Rating has a public method public int getValue(), which returns the value of the rating. The value names and their grades have to be the following:"

Rating Value
BAD -5
MEDIOCRE -3
NOT_WATCHED 0
NEUTRAL 1
FINE 3
GOOD 5

I posted a minimal amount of code because I'm so unsure of what to do.  Other than the package, class name and interface, and the class constructor - all described in the instructions in the first paragraph - none of the other code I included is required by the course.  But the class declaration and the constructor are required, and are copied verbatim from the instructions.  I inferred that the constructor intends the use of a HashMap because of the form in which the constructor parameter (ratings) printed using the code:
System.out.println("ratings is " + ratings);
Also, the course has not covered any Map data structures other than Map and HashMap (although they have on a couple of occasions pushed us out into the java API to find info for other stuff).

So anyway - Piet is correct that there is no requirement to "sort a HashMap".  That's my phrasing, but more specifically perhaps I should have said "return a list of the Film names used as Map Keys based on the film Ratings found in the Map Value ArrayList."  The final objective is simply to return a list of the movies in the order of highest average rating to lowest average rating.  The example output provided is :
The films before sorting: [Gone with the Wind, The Bridges of Madison County, Eraserhead]
The films after sorting: [The Bridges of Madison County, Gone with the Wind, Eraserhead]
so it appears the course expects the films to be returned as some sort of list.

I apologize if I have caused any confusion.

On a (perhaps) related topic, can anyone recommend a good source of information for the use of the Comparator interface?  Much of my problem arises because the Oracle information (Java Tutorials and Java Language Specification) is obtuse, the API gives no examples for its declaration and use and info on the internet is conflicting and confusing.  At least some sites conflate Comparator and Comparable.  FWIW I have a college textbook I use as a reference, and their info on Comparator sucks, too.

Again, I thank you all for your help and apologize if I've caused any confusion.
 
Rancher
Posts: 4801
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
OK, so do you knw what a Comparator is used for?

I'll say anyway.  The sort method of a List expects to be given a Comparator.  it then uses that Comparator to help it order the elements, handing the compare method two instances of the elements it is comparing.
The compare method then returns a negative number if the first argument is "less than" the second argument, a zero if they are equal, or a positive number if the first argument is "higher than" the second argument.

What classes as "less than", "equal to" or "higher than" is determined by the requirements.

So, in your case it looks like it uses the average Rating for a Film as it's initial comparison.

What if the films have an equal average?  I suppose to could then sort by title maybe?  Or just ignore that for now.
 
Campbell Ritchie
Marshal
Posts: 79151
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Apology accepted I got confused myself and posted some confusing information too. Sorry.
Now the cold light of morning has come, I have realised that you are passing a film to your compare() method and you will have to get a score average from your Map. Calculating a score average like that is statistically wrong, but we aren't teaching statistics, we are teaching computing, so you can get away with it. In your compare() method you will have to find out the average from the Map. I would create a private findAverage() method or similar.

If the film isn't in the Map as a “K”, I think you will have to take some sort of action. Maybe the simplest would be to impute that film an average score of 0.0; I think 0.0 would be appropriate.
Remind yourself of the details of the Double class and remember that it implements Comparable<Double>.
 
Stephan van Hulst
Saloon Keeper
Posts: 15485
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's not appropriate to write any kind of comparator based on live values from a Map, because you have to perform x in O(n log n) lookups, which for any Map that is not based on a hash will be expensive. And that's just when you use it to sort a different data structure without modifying the original map. Constructing a TreeMap with a Comparator that will order items based on the map itself will lead to undefined behavior.

So no, don't write comparators based on values of a map. Convert the map to a list, and sort the list.

It's otherwise fine and even makes sense to use maps to keep a list of ratings with films, because you can then efficiently retrieve the ratings for other purposes than just displaying a list of films sorted by average rating.
 
Campbell Ritchie
Marshal
Posts: 79151
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I was thinking the idea of the Map passed to the constructor was simply to provide access to the Rating lists. Presumably it would be all right to take all the films out of a hash map and use those averages to sort it into a tree map (or similar)? Or, as you said, a List.
But what is going to happen if you take the Films out of the Map and concurrently scores are added to a film which later alter the sorting?
 
Stephan van Hulst
Saloon Keeper
Posts: 15485
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:I was thinking the idea of the Map passed to the constructor was simply to provide access to the Rating lists.


Yes, and this is a bad idea, because the only situation in which sorting anything at all will be at least as performant as sorting a list of key-value pairs will be if the map is hash-based, meaning you have a hard requirement on HashMap or LinkedHashMap.

Presumably it would be all right to take all the films out of a hash map and use those averages to sort it into a tree map (or similar)?


If you keep a TreeMap sorted based on the values of another map the behavior will be undefined unless that second map remains unchanged. The strength of TreeMap is that you keep it sorted even after you add new entries. If you can't add new entries because you can't change the content of the second map, then what's the point of using a TreeMap?

But what is going to happen if you take the Films out of the Map and concurrently scores are added to a film which later alter the sorting?


It doesn't even matter if you do it concurrently. Once you alter the values of the map, the content of your TreeMap will be completely undefined if it uses a comparator based on values of another map.
 
Campbell Ritchie
Marshal
Posts: 79151
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:. . . Once you alter the values of the map, the content of your TreeMap will be completely undefined if it uses a comparator based on values of another map.

That is what I expected; it sounds a bad idea all round. Once that undefined behaviour, which I think I can construe as “incorrect ordering,” starts, the correct performance of such a program is doomed. whether single‑lthreaded or concurrent.
You can't even use Map#ofEntries() or Map#of() to create an unmodifiable Map because the List “V”s remain mutable.
 
Stephan van Hulst
Saloon Keeper
Posts: 15485
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

 
Carey Brown
Saloon Keeper
Posts: 10687
85
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Is there something I'm missing in this discussion. It seems like this would be a reasonable solution. The work is being done in basically 3 lines of code.
 
Stephan van Hulst
Saloon Keeper
Posts: 15485
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's absolutely a valid solution, but you're pretty much just using your map as a list of key-value pairs, with the only difference being that the list will be sorted while it's being filled, instead of afterwards.
 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hmm... lot of critics and suggestions, but as an exercise I find the assignment terrific.
The one thing I miss: it is for everyone clear what a rating like "Good" or "Mediocre" means. However, an average rating of, say, 3.32476 s completely meaningless. Therefore, the average should be itself one of the enums. How? Up to you.

And of course: Cambell is right that taking the average rating should be done with care. For instance: is it right that a film with "Good, Good" is rated higher than a film with "Good, NotWatched, Good"?
And if the average rating is a rating itself, as I proposed, would it be right that, if the ratings were: "Good, Bad" the double average is 0 and you might give it the average rating of "NotWatched"?

Lastly but one: if the ratings map gets updated, it is then simply a matter of creating a new instance of the FilmComparator, or you could give that class a method like 'setNewMap'.
Lastly: you can make the FilmComparator take care of missing films, if you so like. I have this in my FilmComparator class:

As I said: a great exercise!

@Carey: in your code you create a TreeMap:

Don't forget that that is only possible if your Film is either implementiong Comparable<Film> or you need to specify some Comparator!
 
Stephan van Hulst
Saloon Keeper
Posts: 15485
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Piet Souris wrote:Lastly but one: if the ratings map gets updated, it is then simply a matter of creating a new instance of the FilmComparator, or you could give that class a method like 'setNewMap'.


You will still not be able to use it in a TreeMap, because it will break the invariants that TreeMap has regarding its internal red-black tree.
 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Can you elaborate on this? I'm not sure what you mean.
 
Stephan van Hulst
Saloon Keeper
Posts: 15485
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here's a red-black tree:



Imagine that the integer values of the nodes are the keys of the map. When you ask TreeMap to retrieve the entry for key '7', it looks if the key is less than or greater than the key of the root node. Since it's less, it then moves to the left child of that node and compares the keys again. '7' is greater than '2', so it moves to the right child of that node and compares the keys again. It then finds that that node has the same key, so it returns that node.

Changing the way that keys compare to each other does not change the current structure of the tree. If the Comparator you've passed in suddenly changes the order of its keys so that '7' is considered greater than '11', the search will try to find the entry to the right of the root node. It will report that the entry does not exist, even though you added it earlier.

This means that changing the way that keys compare to each other (because the average rating of a movie changed) possibly makes the map lose entries. Not only does it lose entries, but it may not longer add new entries correctly, because the tree is not in a valid state. It's complete behavior becomes undefined.

Allowing a Comparator to change the way it orders elements is the same to a TreeMap as allowing a key to return different hash codes is to a HashMap.
 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the clear explanation.

But I made the Map that is the basis of the Comparator immutable (apart from the Films themselves):

so that any derived sorted map or set will always use the same FilmComparator. Therefore, if you update that basic Map, you are bound to create new (sorted) sets or map, if you want to have the latest scores.

Well, that is as I understood the assignment.
 
Campbell Ritchie
Marshal
Posts: 79151
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You can cure the prolem like that, taking a copy of the Map, but Stephan is right that we have very iffy design here. It doesn't make the design any better that it can be cured like that.
 
Piet Souris
Bartender
Posts: 5465
212
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Agreed, but as I wrote before: a very nice assignment, dealing with quite some useful aspects.
 
Campbell Ritchie
Marshal
Posts: 79151
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Afraid I disagree, Piet; it isn't a good assignment. It was over‑specified, lots of implementation details being given in the question, and on closer examination some of those details turned out to be at best misleading.
 
Al Davis
Greenhorn
Posts: 29
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
SUCCESS!!

I've finally gotten everything to do what it needs to do.

My original posting related only to part 6 of an 8 part problem (which I haven't finished yet), but part 6 is definitely the "core" of the exercise.  I've posted all the code for the class below - there are some methods in it which we haven't really discussed here which were required by earlier parts of the exercise.  I don't think my code is beautiful and almost certainly it is not elegant, but it does demonstrate that a bull in a china shop might eventually achieve a good end.  Based on the messages I've gotten from NetBeans, there seem to be plenty of opportunities to use functional expressions to save some typing, but I've made the decision not to use those until I have a more solid grounding on the "old style" code.  Lord knows I need it.

The discussions on this thread have been fascinating, enlightening and helpful.  Thanks to everyone.  I can't say I used anyone's code entirely, but I'm pretty sure I've stolen a piece here or there from almost everyone who posted.

If there's interest, I could write the MOOC organizers and ask for permission to upload the entire exercise.  They're revamping the course anyway over the next few months, so they might not mind.  Piet Souris, in particular, mentioned that he considered this an excellent exercise.  I know it sure as hell taught me a lot, but I'm old enough that my ego can handle the beating.  And it took a real beating...  Anyway, here's the code.  There are a lot of stupid/trivial comments, but I found it necessary to use them to keep my mind from exploding.  I've also included (again - sorry for the repetition) the instructions provided by the devious bastards that designed the course.  The instructions are after the code.



Instructions:
Create the class FilmComparator in the package reference.comparator. The class FilmComparator has to implement the interface Comparator<Film>, and it has to have the constructor public FilmComparator(Map<Film, List<Rating>> ratings). The class FilmComparator will be used later on to sort films according to their ratings.

The class FilmComparator has to allow for film sorting according to the average of the rating values they have received. The films with the greatest average should be placed first, and the ones with the smallest average should be the last.

Thanks again everyone.  I'm gonna have a glass of bourbon and go to bed.  More code in the morning!
 
Sheriff
Posts: 7125
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Want some comments on the code?  Here's one.

This code:
Could more succinctly be written
 
Knute Snortum
Sheriff
Posts: 7125
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Couldn't the second if else just be else?  And if not, what conditions are you missing?
 
Knute Snortum
Sheriff
Posts: 7125
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The third if has no statements in its body.  Something you're going to do later?
 
Carey Brown
Saloon Keeper
Posts: 10687
85
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Method could be replaced with


 
There's a way to do it better - find it. -Edison. A better tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic