Если вы хотите, чтобы ваш метод принимал как можно больше разных типов коллекций, и вы хотите быть уверены, что результат будет того же типа реализации, что и вы, вы можете использовать метод void
, который напрямуюизменяет предоставленную коллекцию.Например:
import com.google.common.base.Predicate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class Testy {
private static <T> void filter(Iterable<T> collection, Predicate<T> filter) {
Iterator<T> iterator = collection.iterator();
while (iterator.hasNext()) {
if (!filter.apply(iterator.next())) { // Condition goes here
iterator.remove();
}
}
}
public static void main(String... args) {
List<String> list = new ArrayList<String>();
list.addAll(Arrays.asList("A", "B", "C", "D"));
filter(list, new Predicate<String>() { // Anonymous filter (predicate)
@Override public boolean apply(String input) {
return input.equals("B");
}
});
System.out.println(list); // Prints ["B"]
}
}
Вспомогательный метод filter
принимает Iterable
, самый простой тип, необходимый для итерации по чему-либо.Примените фильтр к каждому элементу, и если предикат (фильтр) вернет false, удалите этот элемент из базовой коллекции с помощью Iterator.remove()
.
. Интерфейс Predicate<T>
здесь исходит от Google.Вы можете легко написать свой собственный, если вы не хотите импортировать его.Единственный обязательный метод - apply(T)
, который возвращает логическое значение.Либо так, либо просто напишите ваше условие непосредственно в цикле и избавьтесь от второго параметра.
Этот метод наиболее эффективен, если ваша исходная коллекция изменчива и вы не хотите сохранять промежуточные результаты.
Другой вариант - использовать Google Collections Collections2.filter(Collection<E>, Predicate<E>)
, который возвращает Collection<E>
, как и в вашем вопросе.Точно так же класс Iterables
сделает то же самое, но создаст ленивые итерации, где фильтры применяются только при выполнении итерации.