mackesmilian
mackesmilian

Reputation: 123

Java - Comparator Class for same attributes from different object types

I have an odd question:

I have two classes, Book and Newspaper. They share the attribute price. I have to implement a PriceComparator which obviously compares price from Book and Newspaper. I'm not too experienced -especially in Java but my top off the head solution would be to make an interface which would get me the common values and I could do my comparison based on those but that is not possible for two reasons:

1) I can only have the classes Book, Newspaper, Main and PriceComparator and I'm not allowed to create another class/interface within the same .java file.

2) I have to use one list which contains both Book and Newspaper

My solution for this would be to maybe create a List<Object> and then compare the generic objects using casting to get their value via their getter, but this seems so clunky to me and I think there must be a better solution, though I can't think of one. I hope my question makes sense. Thanks!

Upvotes: 0

Views: 1047

Answers (2)

leo277
leo277

Reputation: 439

@Themelis answer is the more appropriate (and probably more efficient) solution IMO. But in case anyone is interested here is an alternative using reflection:

    Function<Object, Double> keyExtractor = o -> {
        try {
            Field field = o.getClass().getDeclaredField("fieldName");
            field.setAccessible(true);
            Double value = (Double) field.get(o);
            field.setAccessible(false);
            return value;
        } catch (Exception e) {
            return -1D;
        }
    };
    Comparator<Object> comparing = Comparator.comparing(keyExtractor, Double::compareTo);
    List<Object> objects = new ArrayList<>(List.of(new A(1), new B(3), new A(2), new B(0)));
    objects.sort(comparing);

Note: If you pass in an object of a class with no declared field fieldName of type double then NoSuchFieldException or ClassCastException will be thrown and -1 return for the comparison resulting in these objects to be at the beginning of the list after a sort.

Upvotes: 0

Themelis
Themelis

Reputation: 4255

If you're not allowed to create another class/interface within the same .java file then create your interface seperately. For example,

Priceable.java

public interface Priceable {
    double getPrice();
}

Book.java

public class Book implements Priceable{
    // ...
    int price;

    @Override
    public double getPrice() {
        return price;
    }
}

Newspaper.java

public class Newspaper implements Priceable{
    // ... other
    private double price;

    @Override
    public double getPrice() {
        return price;
    }
}

Now you can define a Comparator<Pricable> which compares the prices. For example,

Comparator<Priceable> products = (o1, o2) -> (int) (o2.getPrice() o1.getPrice());

Upvotes: 2

Related Questions