Win a copy of OCP Java SE 8 Programmer II Exam Study Guide this week in the OCP forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Inner Classes with Comparable/Comparator  RSS feed

 
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So, I am just getting a massive headache trying to figure this out..sad part is the first part should be pretty simple. I have been looking up examples of comparator, and comparable but I dont get it. I know comparable only has one object while a comparator uses two. Each have their own method to compare, oh and comparable returns -1, 0, or 1 I believe. Sadly right now im just trying to sort cards in lowest to highest. Here are the full Directions

Here are all the class
Card


Deck:


MainApplication


HandDisplay which doesnt matter until the first two sorts are done
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
based on examples this is what I have for the card class...just to sort the card. Though im not sure if this is right either I want cards in lowest to highest within rank....anyway
 
Saloon Keeper
Posts: 4056
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A compareTo() method returns a positive number, a negative number, or zero. It is not limited to -1, 0, +1, though those could be used. Here's a very simple method that compares the rank of two cards, ignoring suit. You could do a similar thing to sort by suit. To sort by both suit and rank you'd have to decide if you want to sort by suit then rank, or rank then suite.
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well for the first one I believe we want to sort suit first then rank, and in the second sort its sorted by rank then suite. How could you sort by two thing though? if suite was something like

Like your example with rank anything after that return is not going to be reached in the method?
Also what does subtracting them do? ive tried researching, but I get the same results everytime.
 
Carey Brown
Saloon Keeper
Posts: 4056
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
To sort by two things you have to set up a temporary value to hold the potential result.
Only if the suits are the same do you compare the rank. So you either return the temporary results or the results of comparing the ranks.

The subtraction is a simple way to get a positive/negative/zero value.
A = 3
B = 7
A-B = -4 :: a negative number means that A is less than B

A = 5
B = 5
A-B = 0 :: meaning A and B are equal

A = 9
B = 2
A-B = 7 :: a positive number indicates that A is greater than B

Note that the subtraction trick should be used with caution because if you are dealing with very large numbers you could get an overflow which would be a bug. Your numbers, however, are very small.
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So from that I need to see if the returned value is going to be 0, and if it is then I want to sort by rank.
So just off the top of my head it would be something like

 
Carey Brown
Saloon Keeper
Posts: 4056
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yep.
 
Rancher
Posts: 2862
32
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

want to sort suit first  then rank


You would do two comparisons:
first compare the suit -
if different, return the difference in the suit
if the same: return the difference in the rank
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So from what I looked at comparable uses the variables, and comparators seem to use the getters. So it would make sense to use the getters, and just reverse what I did in the first sort. Maybe so for my comparator to sort by rank then suit I have

 
Rancher
Posts: 2451
80
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is a fine Comparator, indeed, although the sorting on the suit is a bit random of course. Any idea how you could incorporate a trump suit in the Comparator?
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What do you mean random? I'm sorry im still trying to get my head around comparable, and comparator. So for the comparator it should sort rank within suit, which I figured would be the reverse of my first sort of sorting suit within rank. So is the suit part in the comparable not right? or not finished?
 
Carey Brown
Saloon Keeper
Posts: 4056
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think what Piet ment was "arbitrary". Example: why should diamonds precede clubs.
 
Piet Souris
Rancher
Posts: 2451
80
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nothing wrong with this Comparator. The suit is determined by the card number (see the constructor of the Card class). So, card 51 compares positive to card 12. That's why I called it a bit random, but it certainly works.
 
Piet Souris
Rancher
Posts: 2451
80
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, Carey, I meant arbitrary indeed.
 
Sheriff
Posts: 11745
191
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would echo the question about comparing suits. Logically, how is a club less than or greater than heart? Do you want to able to group cards by suit and have those groupings be ordered in a certain way?
 
Junilu Lacar
Sheriff
Posts: 11745
191
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, the link you provided to the full directions for this exercise leads to a page that says the document has been removed.
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So, I mixed up the sorts according to the instructor. I believe they should now be



Lets try the Directions again. I have completed the deal button, so now I am on
the fish sort button

"Sort the code in a way that would be useful playing Go Fish. I.e. with all of the cards
grouped together. Implement the action handler as a lambda expression in the UI. The
code in the lambda expression should depend on the Card class for the actual sorting (i.e.
the natural order). It must not call any other method in the UI class."
 
Sheriff
Posts: 4742
131
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And the problem you're having is...?
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Figuring this out. The card class is has the natural sort order because is implements the comparable. So, since I want to sort by group meaning having all the 2's together, the 3's together, and so on I would really be using the CompareTo method in the card class. So my lambda would be something like... I dont know (Card) -> Card.CompareTo? Can you call a compareTo or compare method?
 
Piet Souris
Rancher
Posts: 2451
80
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What about a Comparator that sorts on the frequency of the ranks in a Hand? You could then start asking for cards of the rank that is closest to a 'kwartet' as we call it in Dutch.(or vice versa, to minimize the chance 'go fish')
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well as far as sorting the directions say "However, for this assignment, each piece is very specific as
to how I want you to implement things" So im not sure I have much wiggle room
 
Knute Snortum
Sheriff
Posts: 4742
131
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm assuming your UI class has something like this in it:
You want to know what goes in the place of the comment?  It depends on how you're implemented the Deal button.  I'm assuming you have a List of Cards that have been dealt.  You want to sort that List.  List has a sort method.  Does this help?
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So my deal button looks like





Since it needs to be a inner class. I was actually looking at collections.sort, Im not sure if its the same thing but like Collection.sort(list, Card.CompareTo.suit)?
 
Carey Brown
Saloon Keeper
Posts: 4056
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This TUTORIAL shows how to implement a listener using Java 8 lambdas.

[Edit] Never mind. Seems that it covers Swing and not JFC.
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have tried this which gives me an error because sort is not applicable for those arguments.

Also tried this but gives me an error because my rank sorter comparator is a inner class not method...
 
Carey Brown
Saloon Keeper
Posts: 4056
48
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A ListView is not a Collection. You may have to copy the ListView data to a List, sort the List, and then copy it back.
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What about this? I looked at where the ListView is getting its content from the deal method in Deck which the deal method returns an array list


So I came up with the following instead. So its going to sort the array list returning method with my comparator???
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This being where the listView gets the deal list
 
Knute Snortum
Sheriff
Posts: 4742
131
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
listView.getItems() returns an ObservableList which implements the List interface, so it has a sort() method, which takes a Comparator<? super E> as its argument.  Sound familiar?
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What you suggested first, but got a reply from the instructor telling me to use collections.sort
 
Knute Snortum
Sheriff
Posts: 4742
131
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Okay, so use listView.getItems() to return the List<Cards> and I think you're golden.
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
so you're saying
 
Piet Souris
Rancher
Posts: 2451
80
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can't speak fo Knute, but I'd say yes. A few posts ago you wrote:

Cody Biggs wrote:So my deal button looks like


With all the code snippets I lost track of the class to which this method belongs. but given the deal method the listView now only contains a hand. Is that what it should be?
 
Junilu Lacar
Sheriff
Posts: 11745
191
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Cody Biggs wrote:What about this?


So I came up with the following instead. So its going to sort the array list returning method with my comparator???


Lots of good discussion so far but I'll comment specifically on this and some of the smells I'm getting from it:

1. It's getting closer to being more object-oriented. The idea of an object having behavior is getting clearer with Deck.deal(), which is good.
2. High-level ideas are still getting mixed in with low-level implementation details. It also violates the Single Level of Abstraction Principle. This keeps the code more procedural rather than object-oriented.
3. Declaring Deck.deal() to return an ArrayList<Card> falls short of the Dependency Inversion Principle (DIP) which would have you "depend on abstractions, not concretions".
4. There's also a violation of a rule related to Inversion of Control that says "If you create it, don't use it. If you use it, don't create it." Following this rule allows you to loosen up coupling of your program code and leads to being able to do dependency injection more easily.

Test-Driven Development could have helped you avoid these problems. I would have written tests to first explore possible API formulations and behaviors of Deck.deal():

These kind of tests are really more Behavior Driven (BDD) rather than TDD but anyway, the point is that you're trying to define the behaviors of the class(es) involved at the API level first, before you've even considered how these behaviors would be implemented. By focusing on the abstract ideas first, you create a framework around which you can build the implementation.

(continued...)
 
Junilu Lacar
Sheriff
Posts: 11745
191
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's where you violate the SLAP:

Line 5 contains a high-level idea of deck.size() compared to a high-level idea of handSize. The conditional expression, however, is a formula that uses the < operator, and this makes it a low-level implementation detail. The next line where you call the Deck.shuffle() is also a high-level idea. In this case, you would try to extract the formula out so you're dealing only with high-level ideas, like so:

Now the high-level ideas are expressed very clearly and they are not muddied by implementation details. This may seem extreme but the more you can do this in your code, the more readable it becomes and that makes it a lot easier to work with.
 
Junilu Lacar
Sheriff
Posts: 11745
191
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
With some more extractions, the deal() method becomes something like this:

See how uncomplicated this code is? When you read it, doesn't it make sense right away? This might even lead you to ask the question, "Why am I having to do that initial check anyway? Shouldn't the shuffle() call be made in the nextCard() method instead?" The answer to that last question is "Yes!"  So, you refactor again:

See how small each method is now? Can you tell which ones are high-level and which ones are low-level?
 
Junilu Lacar
Sheriff
Posts: 11745
191
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As I said earlier, the tests are used to explore possible formulations of the Deck API. Now that I have made an initial exploration, I might question this decision:

There's a smell of a side-effect here and that can be a problem. This design creates coupling between the Deck and Hand classes. That is, Deck is now dependent on Hand. Is this appropriate? What if we reverse the dependency? What if we could eliminate it altogether?

We first try reversing the dependency:

With this formulation, I see that the Deck class can now be made totally unaware of the Hand class and that the Hand class can call the Deck.nextCard() method repeatedly until it is full. I think I like that design better. It makes more sense for a Hand to be aware of the existence of Deck than the other way around.  A Deck would always be able to give its topCard() and it really doesn't care where that top card is going. It could be going to a game of Solitaire for all it cares. Solitaire doesn't have any concept of a Hand.

On the other hand (pun intended), you could argue that a Hand naturally needs to know about the source of the Card objects that its getting, so creating a dependency from Hand to Deck makes more sense than from Deck to Hand.
 
Knute Snortum
Sheriff
Posts: 4742
131
Chrome Eclipse IDE Java Postgres Database VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Cody Biggs wrote:so you're saying


I'm not sure the "new" makes sense, but yes, that's what I was thinking.  Did it work?
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am waiting on the instructor to send the right folder of the card images that are suppose to be sorted...so as of right now Im not sure if any of the sort work which has got me freaked. However I had to use new because if not it complains that the rankSorter is not a method in the card class, which its not it is a inner class. So until I get the right images I might as well work on the next one which is ''

"Order the cards in such a way that they would be useful playing Spades; i.e. with the
cards sorted by rank within suit and the suits in the order provided by the nested class in
#2 above. You actually want to reverse this sort before displaying. Implement the action
handler as an anonymous class in the UI. The code in the anonymous class should
depend on the Card class for the actual sorting; i.e. the Comparator that you added above."

So for this one I know we have to use .reverse, and the inner class its talking about is the nested comparator. So what im understanding is the cards need to be sorted by the comparator, but reverse only takes a list if I can recall?
 
Cody Biggs
Ranch Hand
Posts: 288
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So I need to reverse the sort, which would be?



But also says the suits need to be "cards sorted by rank within suit and the suits in the order provided by the nested class in
#2 above" Which would be my static comparator class
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!