2014-09-08 2 views
2

Я хочу фильтровать, а затем сортировать, а затем ограничивать немодифицируемый список в Java и Guava. Есть ли разумный способ сделать это более эффективным, чем ниже?фильтровать, сортировать и ограничивать немодифицируемый список в Java

public static <T> List<T> execute(final List<T> list, final Predicate<? super T> filter, final Comparator<? super T> sort, final Integer limit) { 
    final List<T> newList = Lists.newArrayList(Iterables.filter(list, filter)); 
    Collections.sort(newList, sort); 

    if (limit > newList.size()) { 
     return newList; 
    } 
    return newList.subList(0, limit); 
} 

Спасибо!

+0

Да ... есть Java 8! Вы используете его или нет? – Dici

+0

Нет, я бы хотел, но я использую JDK v5. Но, пожалуйста, не стесняйтесь отвечать на вопрос JDK v8 ради полноты! –

+0

Что такое списки и классы Iterables? – Dici

ответ

4
if (limit != null) { 
    return newList.subList(0, limit); 
} 

Это будет дуть всякий раз, когда limit > newList.size().

Я думаю, только одно можно оптимизировать: вам не нужно сортировать всю коллекцию, если вы хотите только ее часть. Это a bit complicated, поэтому сначала вы должны измерить, если вам это действительно нужно.


Как указано в комментариях, на самом деле это просто, так как гуава уже делает это:

public static <T> List<T> execute(
     final List<T> list, 
     final Predicate<? super T> filter, 
     final Comparator<? super T> sort, 
     final Integer limit) { 
    final FluentIterable<T> filtered = FluentIterable.from(list).filter(filter); 
    return Ordering.from(sort).leastOf(filtered, limit); 
} 
+0

Спасибо, частичный интерес интересен! –

+0

@TweemaalZeven Возможно, вы относились к частичным интересным сортировкам? ;) – maaartinus

+0

Упс :) Я не могу его отредактировать. –

2

Ваши тесты довольно усложняют предмет ... Если вы хотите, чтобы пользователь мог вызвать этот метод без использования фильтра (например), просто перегрузите свой метод. null не должно быть юридическим значением для таких параметров.

+0

Это функция утилиты, а не метод класса. –

+0

Этот ответ по-прежнему работает с функциями утилиты.Вы можете перегрузить вашу функцию, например, 'execute (final List list, final Predicate filter)' или 'execute (final List list, final Comparator sort)' или 'execute (final List list, final Predicate фильтр, окончательный компаратор сортировать) ' – Volune

4
List<T> newList = FluentIterable.from(list) 
    .filter(predicate) 
    .limit(limit) 
    .toSortedList(comparator); 
// (This sorts last so is behaviorally different from the original example, but it 
// gives an idea of a somewhat more readable approach to this type of thing.) 

// Java 8's Stream, unlike Guava's FluentIterable, has a sort method which 
// makes this easier: 
List<T> newList = list.stream() 
    .filter(predicate) 
    .sort(comparator) 
    .limit(limit) 
    .collect(toList()); 

Просто используйте, что вместо вашего метода execute, и просто не позвонить filter, если у вас нет предиката для фильтрации и т. Д. Обратите внимание, как ясно, что делается, когда вы смотрите на этот код. Сравните это:

List<T> newList = execute(list, predicate, comparator, limit); 

или еще хуже:

List<T> newList = execute(list, null, comparator, null); 

Определение один метод, как это только запутывает код.

+1

Я считаю, что это неверно. Сначала вы должны фильтровать, затем сортировать и затем ограничивать. Здесь сортировка выполняется до ограничения. –

+0

@TweemaalZeven: Хорошо, к сожалению, вам придется немного изменить его. Суть в том, что выполнение этих шагов явно предпочтительнее. – ColinD

+0

Скажем, я должен фильтровать, сортировать, ... список в нескольких местах моего кода. Один раз мне нужно только фильтровать, в другой раз я должен фильтровать и сортировать, ... Предлагаете ли вы снова и снова проверять значение null в строке, вместо использования функции утилиты? –