фильтровать и сортировать список с помощью коллекций Google
Вопрос
Предположим, у меня есть список (или набор):
List<String> testList = Lists.newArrayList("assocX","srcT","destA","srcX", "don't care Y", "garbage", "srcB");
Я хотел бы вернуть ImmutableList(Set), который сортирует/группирует термины в естественном порядке, где термины, начинающиеся с «src», являются первыми, «assoc» вторыми и «dest» последними.Если термин их не содержит, его следует удалить из полученного списка.
Поэтому результат здесь: «srcB», «srcT», «assocX», «destA».
Я думаю, что могу сделать это с помощью некоторой комбинации Iterables.filter или Predicates, но просто не вижу этого.Я думаю, что должен быть краткий способ сделать это.
РЕДАКТИРОВАТЬ:Набор вместо списка также работает.
Решение
Поскольку вас интересуют только эти три префикса, я бы предложил что-то вроде этого:
Predicate<String> filter = new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.startsWith("src") || input.startsWith("assoc") || input.startsWith("dest");
}
};
Function<String, Integer> assignWeights = new Function<String, Integer>() {
@Override
public Integer apply(String from) {
if (from.startsWith("src")) {
return 0;
} else if (from.startsWith("assoc")) {
return 1;
} else if (from.startsWith("dest")) {
return 2;
} else {
/* Shouldn't be possible but have to do something */
throw new IllegalArgrumentException(from + " is not a valid argument");
}
}
};
ImmutableList<String> sortedFiltered = ImmutableList.copyOf(
Ordering.natural().onResultOf(assignWeights).sortedCopy(
Iterables.filter(testList, filter)
)
);
Это решение определенно не будет хорошо масштабироваться, если вы начнете добавлять больше префиксов для фильтрации или сортировки, поскольку вам придется постоянно обновлять как фильтр, так и вес каждого префикса.
Другие советы
Посмотри на Этот пример коллекций Google.
Function<Fruit, String> getNameFunction = new Function<Fruit, String>() {
public String apply(Fruit from) {
return from.getName();
}
};
Ordering<Fruit> nameOrdering = Ordering.natural().onResultOf(getNameFunction);
ImmutableSortedSet<Fruit> sortedFruits = ImmutableSortedSet.orderedBy(
nameOrdering).addAll(fruits).build();
Хотя это, по общему признанию, возвращает Set.
Я думаю, вам придется сначала использовать предикат для исключения ненужных элементов, а затем реализовать Компаратор и отсортируйте свой список.
Обычно такое сопоставление четко различных данных является плохим решением.В вашем случае, когда вы говорите «assocX», «assoc» имеет отдельное значение от «X», но вы объединяете их вместе.
Поэтому я бы предложил создать класс с двумя полями.Затем вы можете создать порядок в первом поле, другой во втором и объединить их (например,Заказ#соединение()).С помощью метода toString(), который делает объединить эти поля в строку.В качестве бонуса это может значительно сократить использование памяти за счет совместного использования.
Итак, вы сортируете список таких объектов и, если хотите их распечатать, просто вызываете для них toString().