Реализуем настраиваемые критерии сортировки - PullRequest
0 голосов
/ 03 сентября 2018

Мне нужно иметь возможность сортировать объект по нескольким условиям, и эти сортировки должны быть конфигурируемыми из файла 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...