4

I am fairly new to Java and now I have to create some Comparator classes.

On this Stackoverflow page I have found some really useful information about using lambda expressions. How to compare objects by multiple fields

Which made me thing about creating a Compartor class like this:

public class WidthComparator implements Comparator{
    @Override
    public int compare(Object t, Object t1) {
        Foto foto1 = (Foto)t;
        Foto foto2 = (Foto)t1;

        return Comparator.comparing(Foto::getWidth)
               .thenComparing(Foto::getHeight)
               .thenComparingInt(Foto::getName);
        }
    }    
}

so when I have a collection called fotosCollection, I would like to be able to do this:

fotosCollection.sort(new HoogteComparator());

This obviously does not work, but how could I get this to work?

Ps. I have to use a Comparator class.

Community
  • 1
  • 1
Johan Vergeer
  • 5,208
  • 10
  • 48
  • 105

3 Answers3

5

Comparator.comapring returns a Comparator - you can just use it directly:

// Define a "constant" comparator
private static final Comparator<Foo> HOOGTE_COMPARATOR = 
    Comparator.comparing(Foto::getWidth)
              .thenComparing(Foto::getHeight)
              .thenComparingInt(Foto::getName);

// Use it elsewhere in your code
fotosCollection.sort(HOOGTE_COMPARATOR);
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • I know this would be the right answer if I did not have to use a Comparator subclass. But for this assignment, I have to. – Johan Vergeer Feb 11 '17 at 12:41
  • 3
    @JohanVergeer but this **is** a Comparator. The fact that you use a factory method to generate it instead of writing boiler-plate code by yourself does not change this. – Mureinik Feb 11 '17 at 12:42
2

If you really don't want the comparator type to be anonymous for some reason, you can do:

public class WidthComparator implements Comparator<Foto>{
    private final static Comparator<Foto> FOTO_COMPARATOR = Comparator.comparing(Foto::getWidth)
        .thenComparing(Foto::getHeight)
        .thenComparingInt(Foto::getName);

    @Override
    public int compare(Foto foto1, Foto foto2) {    
        return FOTO_COMPARATOR.compare(foto1, foto2);        
    }    
}

I also would consider avoiding the use of the rawtype and implement Comparator<Foto> instead, as I did above.

Calculator
  • 2,769
  • 1
  • 13
  • 18
  • This works just as expected. I have to do this for a school assignment, so I have to use a Comparator class implementation. How could I implement `Comparator`? – Johan Vergeer Feb 11 '17 at 12:33
  • This doesn’t make any sense. The expression `Comparator.comparing(Foto::getWidth) .thenComparing(Foto::getHeight) .thenComparingInt(Foto::getName)` already creates a `Comparator` doing the actual work. The class `WidthComparator` is obsolete, all id does, is creating a new comparator for every comparison. – Holger Feb 13 '17 at 14:43
  • @Holger Indeed, the comparator should go into a constant. As I wrote, the concrete type of the comparator `Comparator.comparing(Foto::getWidth) .thenComparing(Foto::getHeight) .thenComparingInt(Foto::getName)` is anonymous. Especially if this is for an assignment, it could be a requirement that OP has to implement a named class implementing the comparator interface - in this case as an adapter to an anonymous comparator. – Calculator Feb 13 '17 at 15:01
  • If the intention of the assignment really is to have a manually implemented comparator, it’s unlikely that dodging the requirement by using the factory methods and wrapping the result into a façade gets much appreciation. – Holger Feb 13 '17 at 15:39
1

You can try this old-style approach:

public class WidthComparator implements Comparator{
    @Override
    public int compare(Object t, Object t1) {
        Foto foto1 = (Foto)t;
        Foto foto2 = (Foto)t1;

        // width asc order
        if(foto1.getWidth() != foto2.getWidth())
            return foto1.getWidth() - foto2.getWidth();

        // height asc order
        if(foto1.getHeight() != foto2.getHeight())
            return foto1.getHeight() - foto2.getHeight();

        // name asc order
        return foto1.getName().compareTo(foto2.getName());            
    }    
}
algojava
  • 743
  • 4
  • 9