Подтвердить что ты не робот

Фильтровать и сортировать список с помощью коллекций google

Предположим, у меня есть список (или Set):

List<String> testList = Lists.newArrayList("assocX","srcT","destA","srcX", "don't care Y", "garbage", "srcB");

Я хотел бы вернуть ImmutableList (Set), который сортирует/группирует термины в естественном порядке, где термины, начинающиеся с "src", являются первыми, "assoc" second и "dest" last. Если термин не содержит те, то он должен быть удален из результирующего списка.

Поэтому результатом здесь являются "srcB", "srcT", "assocX", "destA".

Я думаю, что могу сделать это с помощью некоторой комбинации Iterables.filter или Predicates, но просто не увижу этого. Должен быть лаконичный способ сделать это, я думаю.

EDIT: также работает набор вместо списка.

4b9b3361

Ответ 1

Пока эти три префиксы - единственное, что вам нужно, я бы предложил что-то вроде этого:

    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)
            )
    );

Это решение определенно не будет масштабироваться невероятно хорошо, если вы начнете добавлять больше префиксов для фильтрации или сортировки, так как вам придется постоянно обновлять фильтр и вес каждого префикса.

Ответ 2

Посмотрите Этот пример Google Collections.

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.

Ответ 3

Я думаю, что вы сначала должны использовать предикат для устранения элементов, которые вам не нужны, а реализация Comparator и сортировать список.

Ответ 4

Обычно это плохая конструкция для сопоставления четко определенных данных, подобных этому. В вашем случае, когда вы говорите "assocX", "assoc" имеет отдельный смысл от "X", но вы объедините их вместе.

Поэтому я бы предложил создать класс с двумя полями. Затем вы можете создать упорядочение в первом поле, другое на втором и объединить их (например, Ordering # compound()). С помощью метода toString(), который объединяет эти поля в строку. В качестве бонуса это может значительно сократить использование памяти путем совместного использования.

Итак, вы должны сортировать список таких объектов, и если вы хотите их распечатать, вы просто вызываете toString() на них.