фильтровать и сортировать список, используя коллекции Google - PullRequest
27 голосов
/ 22 февраля 2010

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

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, но просто не увидев это. Я думаю, что должен быть краткий способ сделать это.

РЕДАКТИРОВАТЬ: набор вместо списка работает также.

Ответы [ 4 ]

33 голосов
/ 22 февраля 2010

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

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

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

12 голосов
/ 22 февраля 2010

Взгляните на Этот пример коллекций 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();

Хотя это, правда, возвращает набор.

0 голосов
/ 17 марта 2010

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

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

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

0 голосов
/ 22 февраля 2010

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

...