Мне нужно иметь возможность сортировать объект по нескольким условиям, и эти сортировки должны быть конфигурируемыми из файла application.properties (так как в нем должна быть возможность указать применяемые сортировки и порядок).
Итак, в своем дизайне я создал компаратор для каждого из видов, а затем перечисление с поставщиком, таким как:
public enum CarSort {
ENGINE(CarEngineComparator::new), BRAND(CarBrandComparator::new);
private final Supplier<Comparator<Car>> constructor;
CarSort(Supplier<Comparator<Car>> constructor){
this.constructor = constructor;
}
Comparator<Car> newComparator() {
return constructor.get();
}
}
При таком дизайне я смог бы загрузить сортировки из файла свойств:
myapp.cars.sorts=BRAND,ENGINE
И сортируйте цепочки с чем-то вроде:
Stream<Comparator<Car>> comparators = sorts.stream().map(CarSort::newComparator);
return comparators
.reduce(Comparator::thenComparing)
.map(comparator -> filteredCars.sorted((comparator.reversed())))
.orElse(filteredCars)
.collect(Collectors.toList());
Проблема, с которой я столкнулся на данный момент, заключается в том, что одному из компараторов требуются два параметра, поэтому я не думаю, что это решение больше подходит, но в настоящий момент я не могу придумать каких-либо чистых альтернатив.
Знаете ли вы, можно ли будет адаптировать мою текущую конструкцию, чтобы она соответствовала этому требованию, или у вас есть альтернативное жизнеспособное решение?
Я собираюсь добавить больше деталей. Скажем, конкретный компаратор, который мне нужно добавить, сортирует автомобили, основываясь, например, на том, как далеко они находятся от клиента. Так что это может быть что-то вроде этого (детали на самом деле не важны, только тот факт, что для этого нужен дополнительный параметр):
public class CarDistanceComparator implements Comparator<Car> {
private Location origin;
CarDistanceComparator(Location origin) {
this.origin = origin;
}
@Override
public int compare(Car o1, Car o2) {
double distanceToFirstCar = DistanceService.calculateDistance(origin, o1.getLocation());
double distanceToSecondCar = DistanceService.calculateDistance(origin, o2.getLocation());
return Double.compare(distanceToFirstCar, distanceToSecondCar);
}
}
Итак, я хотел бы иметь возможность сортировки по BRAND, ENGINE, DISTANCE (как указано в файле конфигурации) для нескольких клиентов. Это означает, что мне нужно будет каждый раз передавать разные аргументы в DistanceComparator.