Это работает для меня без класса Extractor
, а также без вызова map(e -> e)
в конвейере потока.На самом деле, потоковая передача списка экстракторов вообще не нужна, если вы используете правильные универсальные типы.
Относительно того, почему ваш код не работает, я не совсем уверен.Обобщения являются сложным и нестабильным аспектом Java ... Все, что я делал, это настраивал сигнатуру метода parseKeysAscending
, чтобы он соответствовал тому, что на самом деле ожидает Comparator.comparing
.
Вот метод parseKeysAscending
:
public static <T, S extends Comparable<? super S>> Comparator<T> parseKeysAscending(
List<Function<? super T, ? extends S>> keyExtractors) {
if (keyExtractors.isEmpty()) {
return (a, b) -> 0;
} else {
Function<? super T, ? extends S> firstSortKey = keyExtractors.get(0);
List<Function<? super T, ? extends S>> restOfSortKeys =
keyExtractors.subList(1, keyExtractors.size());
return Comparator.<T, S>comparing(firstSortKey)
.thenComparing(parseKeysAscending(restOfSortKeys));
}
}
А вот демонстрация с вызовом:
List<Function<? super Data, ? extends Comparable>> extractors = new ArrayList<>();
extractors.add(Data::getA);
extractors.add(Data::getB);
Comparator<Data> test = parseKeysAscending(extractors);
List<Data> data = new ArrayList<>(Arrays.asList(
new Data(1, "z"),
new Data(2, "b"),
new Data(1, "a")));
System.out.println(data); // [[1, 'z'], [2, 'b'], [1, 'a']]
data.sort(test);
System.out.println(data); // [[1, 'a'], [1, 'z'], [2, 'b']]
Единственный способ заставить код компилироваться без предупреждений - это объявить список функций.как List<Function<Data, Integer>>
.Но это работает только с геттерами, которые возвращают Integer
.Я предполагаю, что вы можете сравнить любой набор Comparable
с, т.е. приведенный выше код работает со следующим классом Data
:
public class Data {
private final Integer a;
private final String b;
private Data(int a, String b) {
this.a = a;
this.b = b;
}
public Integer getA() {
return a;
}
public String getB() {
return b;
}
@Override
public String toString() {
return "[" + a + ", '" + b + "']";
}
}
Вот демоверсия .
РЕДАКТИРОВАТЬ: Обратите внимание, что в Java 8 последняя строка метода parseKeysAscending
может быть:
return Comparator.comparing(firstSortKey)
.thenComparing(parseKeysAscending(restOfSortKeys));
В то время как для более новых версий Java вы должныпредоставить явные универсальные типы:
return Comparator.<T, S>comparing(firstSortKey)
.thenComparing(parseKeysAscending(restOfSortKeys));