0

I currently have a java Entities: Cat and Kitten

Below is the Cat entity that contains the current comparator logic to order the Cat entities by which cat has the oldest Kitten

public class Cat implements Comparable<Cat>
{

    //other fields and methods

    @OneToMany(mappedBy = "cat",fetch = FetchType.EAGER)
    private List<Kitten> kittenList= new ArrayList<Kitten>();

     public DateTime getOldestBornValueForKittenInList(){

        return kittenList.stream().min(Comparator.comparing(Kitten::getBorn))
                .get().getBorn();
    }

    public int compareTo(Cat c) {

        //fist compare on the oldest Created DateTime Value
        int i = getOldestBornValueForKittenInList().compareTo(c.getOldestBornValueForKittenInList());
        if (i != 0){
            return i;
        }

    }

}

I no longer want my Cat Entity to implement the comparable interface. Can I call the comparator in my application instead?

I.e. if I wanted an ordered Map of cats and their list of kittens, with the cat with the oldest kitten being the first entry in the map:

Map<Cat, List<Kitten>> mapOfCatsAndKittens = new HashMap<Cat, List<Kitten>>();
Alexis C.
  • 91,686
  • 21
  • 171
  • 177
java123999
  • 6,974
  • 36
  • 77
  • 121
  • 1
    In general, having logic in an entity class is bad practice, have a service with the entity autowired to apply your logic – Roel Strolenberg May 31 '16 at 14:00
  • 1
    Why not `TreeMap`? It is designed to take a `comparator`. – Tirath May 31 '16 at 14:01
  • @RoelStrolenberg can you give example of the service that I could replace the entity logic with? – java123999 May 31 '16 at 14:04
  • @Tirath thanks, please give example of how I can add a comparator to a treemap? – java123999 May 31 '16 at 14:04
  • I never said add. Anyways, you can look at TreeMap here -https://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html. Check out the constructors. You can pass in your `comparator` implementation. – Tirath May 31 '16 at 14:08
  • Another side note: When you implement `Comparable` (i.e. the `compareTo` method), you should make sure that it is *consistent with equals* as described in the [`Comparable`](https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html) documentation. – Marco13 May 31 '16 at 14:28
  • @RoelStrolenberg not so sure about that... Have you heard about [anemic domain model anti-pattern](http://www.martinfowler.com/bliki/AnemicDomainModel.html)? – Jakub Bibro May 31 '16 at 16:37

1 Answers1

1

Note that your code contains several unnecessary duplications. In

public DateTime getOldestBornValueForKittenInList() {
    return kittenList.stream().min(Comparator.comparing(Kitten::getBorn)).get().getBorn();
}

you let the comparator fetch the property getBorn despite the fact that this is the only property you are interested in. So you can simplify the operation to

public DateTime getOldestBornValueForKittenInList() {
    return kittenList.stream().map(Kitten::getBorn).min(Comparator.naturalOrder()).get();
}

By mapping to the property first, you get a stream of DateTime elements which you can compare naturally, without having to re-fetch the property on each comparison. An the result is already the minimum DateTime.

Keep in mind that in either case, the operation fails if the list is empty.

But the Comparator.comparing factory still has its place. Right when you want to compare Cat objects by a property:

Comparator<Cat> oldestKitten=Comparator.comparing(Cat::getOldestBornValueForKittenInList);

You can use such a comparator to create a map, sorted by that property

Map<Cat, List<Kitten>> mapOfCatsAndKittens = new TreeMap<>(oldestKitten);

or to sort a list of Cats:

List<Cat> list= … ; // should be a mutable list implementation, e.g. ArrayList
// perhaps add (some more) Cats
list.sort(oldestKitten);
Holger
  • 285,553
  • 42
  • 434
  • 765
  • thanks, Can I also use multiple clauses in the comparator?, i.e. if I wanted to firstly check for the oldestBornValue of the kitten, then also check for another clause? Incase the first 2 are equal? – java123999 Jun 01 '16 at 12:37
  • `Comparator.comparing(Cat::firstProperty).thenComparing(Cat::nextProperty)` – Holger Jun 01 '16 at 12:41
  • Thanks, so the first key in this Treemap will be the Cat with the oldest kitten first, the 2nd key will be the Cat with 2nd oldest kitten and so on? – java123999 Jun 01 '16 at 12:45
  • If cat #1 has the oldest kitten and the second oldest kitten, the second value in the map will be the cat with the third oldest kitten. Is that ok? – Hank D Jun 01 '16 at 13:22