2010-02-22 2 views
27

Предположим, что у меня есть список (или Set):фильтровать и сортировать список с помощью коллекции 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, но просто не увидев ее. По-моему, должен быть лаконичный способ сделать это.

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

ответ

32

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

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

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

+11

В других случаях лучше «выбросить новое IllegalArgumentException()», чем «return 3'. –

0

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

12

Посмотрите на This Google Collections example.

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

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

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

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

Смежные вопросы