Reputation: 69
I have tried to create a Comparator based on object fields that have non-null values using Comparator.compare
and then chain it with Comparator.thenCompare
. I have a HashMap that stores a field as a key and getter method reference as a value.
Here is my enum of fields :
public enum BikeProperty {
BRAND,
MAX_SPEED,
WEIGHT,
SIZE_OF_WHEEL,
NUMBER_OF_GEARS,
IS_LIGHT_AVAILABLE,
BATTERY_CAPACITY,
COLOR,
PRICE
}
Each of this fields related to some field in Bike
object.
Next stop is my HashMap that looks like this:
Map<BikeProperty, Function<Bike, Comparable<?>>> fieldToFieldExtractor = new HashMap<>();
fieldToFieldExtractor.put(BikeProperty.MAX_SPEED, Bike::getMaxSpeed);
fieldToFieldExtractor.put(BikeProperty.WEIGHT, Bike::getWeight);
fieldToFieldExtractor.put(BikeProperty.SIZE_OF_WHEEL, Bike::getSizeOfWheels);
fieldToFieldExtractor.put(BikeProperty.NUMBER_OF_GEARS, Bike::getNumberOfGears);
fieldToFieldExtractor.put(BikeProperty.IS_LIGHT_AVAILABLE, Bike::isLightsAvailable);
fieldToFieldExtractor.put(BikeProperty.BATTERY_CAPACITY, Bike::getBatteryCapacity);
fieldToFieldExtractor.put(BikeProperty.COLOR, Bike::getColor);
fieldToFieldExtractor.put(BikeProperty.PRICE, Bike::getPrice);
And finally my method:
public Comparator<Bike> provideComparatorByFields(Set<BikeProperty> fields) {
Comparator<Bike> comparator = Comparator.comparing(Bike::getBrand);
fields
.forEach(s -> comparator.thenComparing(fieldToFieldExtractor.get(s)));
return comparator;
}
My idea is to pass to method already filtered Set<BikePropery>
, iterate through this and chain comparator methods.
For example, for given set Set.of(BikeProperty.PRICE,BikeProperty.IS_LIGHT_AVAILABLE)
, generate following comparator : Comparator.compare(Bike::getBrand).thenCompare(Bike::getPrice).thenCompare(Bike::isLightAvailable)
Problem :
Created comparator have only one default comparing of Bike::getBrand()
. Therefore, I had a question, is it possible to do so at all, and if possible, bring some advice. Thank you!
Update
When I`m creating comparator (for example) from my main method, it looks like this :
But when I`m creating it in my method by forEach loop it looks like this:
So it does not append any thenComparing() keyExtractor to comparator
Upvotes: 1
Views: 422
Reputation: 3753
You are not storing the changes. thenCompare
doesn't modify the original comparator, but returns a new one.
for (var s : fields) {
comparator = comparator.thenComparing(fieldToFieldExtractor.get(s)));
}
Upvotes: 1