There are a few things I would strongly advise to do differently:
Package names should follow the reverse host name scheme: com.coderanch.cardsMake classes final unless designed for inheritance.Makes fields final unless designed for mutability.Don't provide setters unless designed for mutability.Write documentation. This is not example code, it's actually what's going to be used in a project.Implement your methods by throwing UnsupportedOperationException, and write tests before you replace the implementation.Validate your parameters.Don't use string concatenation. Inside loops, use StringBuilder, and outside loops, use String.format().Adhere to YAGNI: Why does Deck have a constant NUMBER_OF_CARDS without a clear use case for it?Deck is a pretty useless wrapper around a list of cards. Whatever class is using a deck of cards can just maintain a collection itself. Advantage is that they can decide the appropriate collection for themselves.Start method names with lowercase letter: shuffle().shuffledDeck() returns an empty list.Why is shuffledDeck() an instance method?Be consistent in accessing your fields. Use either the field directly, or call the getter, but don't mix it up. See my preferences below.
Some personal preferences:
Nest Rank and Suit inside Card. They are strongly related to Card, and don't mean much outside of the context of a Card.Don't prefix simple properties with get-. I find rank() and suit() less verbose, and I reserve getFoo() to express that returning a Foo involves more calculation than just returning a field.Instead of using the getters from within the class, just use the fields directly. Less verbose and saves you a stack frame (not that it really matters).I like to try and give equatable value types a natural order, if possible. The natural order of cards may not be applicable to all card games, but for most you will at least have a common way to sort a hand.Inside the equals() method, I like to explicitly refer to this, and name the other instance 'other'. That way, you get code like this.rank == other.rank.
Pete Letkeman wrote:I find sometimes is nice to have as much logic as I can in private methods provided it will not be shared with other members.
This would allow private methods to be totally rewritten without changing the public method too much.
I agree using private methods is good when you need to cut up your methods in smaller pieces, but just writing a private method as an alias for a one-liner is pretty pointless.
However you may need to know about Lambdas to full advantage of them.
Functional code is great for beginners to get into as soon as possible. There are good reasons to use collections over streams, but to avoid lambda expressions is not one of them.
I suggest that you spend some time defining your classes and stubbing methods as you go. This will give you a better idea of what is needed and how it is used.
Agreed, but stub them by throwing UnsupportedOperationException