Forums Register Login
Inner Classes with Comparable/Comparator
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



HandDisplay which doesnt matter until the first two sorts are done
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
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.
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.
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.
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


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
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

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?
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?
I think what Piet ment was "arbitrary". Example: why should diamonds precede clubs.
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.
Yes, Carey, I meant arbitrary indeed.
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?
Also, the link you provided to the full directions for this exercise leads to a page that says the document has been removed.
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."
And the problem you're having is...?
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?
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')
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
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?
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)?
This TUTORIAL shows how to implement a listener using Java 8 lambdas.

[Edit] Never mind. Seems that it covers Swing and not JFC.
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...
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.
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???
This being where the listView gets the deal list
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?
What you suggested first, but got a reply from the instructor telling me to use collections.sort
Okay, so use listView.getItems() to return the List<Cards> and I think you're golden.
so you're saying
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?

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.

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.
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?
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.

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?
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?
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

This thread has been viewed 1082 times.

All times above are in ranch (not your local) time.
The current ranch time is
Oct 16, 2018 03:05:03.