Лучший способ фильтровать коллекции Java | Заметки об отладке Java

Java задняя часть

Эта статья участвует в "Месяце тем Java - Заметки по отладке Java", подробности см.Ссылка на мероприятие

Вопрос: Как лучше всего отфильтровать коллекцию Java?

я хочу пройтиPredicateфильтроватьjava.util.Collection.

Ответ 1 (от автора Lamdaj):

Java 8(2014) представленjava.util.streamпакет иLambdaРеализация выражения решает эту проблему одной строкой кода:

List<Person> beerDrinkers = persons.stream()
    .filter(p -> p.getAge() > 16).collect(Collectors.toList());

использоватьCollection.removeIfИзмените коллекцию, если условие выполнено. (Примечание: в этом примере объекты, удовлетворяющие условию, будут удалены):

persons.removeIf(p -> p.getAge() <= 16);

LambdajБиблиотека позволяет фильтровать коллекции без написания циклов или внутренних классов (LambdajПозволяет манипулировать коллекциями псевдофункционально и статически типизированным образом, частично снимая нагрузку с написания циклов (часто вложенных и плохо читаемых) при переборе коллекций):

List<Person> beerDrinkers = select(persons, having(on(Person.class).getAge(),
    greaterThan(16)));

Вы не можете себе представить ничего проще для понимания, чем это!

Ответ 2:

Предположим, вы используетеJava 1.5, и вы не можете использоватьCollections, я бы сделал что-то очень похожее на Google.

Сначала добавьте в код следующий интерфейс:

public interface IPredicate<T> { boolean apply(T type); }

Разработчик может вернуться, когда он будет признан истинным для определенного типа. Например: еслиTдаUserAuthorizedUserPredicate <User>выполнитьIPredicate <T>,ноAuthorizedUserPredicate.applyвозвращает входящийUserавторизован.

В некоторых общих классах инструментов вы можете написать:

public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
    Collection<T> result = new ArrayList<T>();
    for (T element: target) {
        if (predicate.apply(element)) {
            result.add(element);
        }
    }
    return result;
}

Итак, возможно, вы реализуете следующее:

Predicate<User> isAuthorized = new Predicate<User>() {
    public boolean apply(User user) {
        // binds a boolean method in User to a reference
        return user.isAuthorized();
    }
};
// allUsers is a Collection<User>
Collection<User> authorizedUsers = filter(allUsers, isAuthorized);

Если речь идет о производительности проверки линейности, мне может понадобиться объект домена с целевой коллекцией. Объект предметной области с целевой коллекцией будет иметь логику фильтрации для методов, которые инициализируют, добавляют и устанавливают целевую коллекцию.

обновить:

в классе инструментов (называетсяPredicateбар), я добавил метод выбора с опцией для значения по умолчанию, если предикат не возвращает ожидаемое значение, и опцию для новогоIPredicateСтатические свойства параметров, используемых в

public class Predicate {
    public static Object predicateParams;

    public static <T> Collection<T> filter(Collection<T> target, IPredicate<T> predicate) {
        Collection<T> result = new ArrayList<T>();
        for (T element : target) {
            if (predicate.apply(element)) {
                result.add(element);
            }
        }
        return result;
    }

    public static <T> T select(Collection<T> target, IPredicate<T> predicate) {
        T result = null;
        for (T element : target) {
            if (!predicate.apply(element))
                continue;
            result = element;
            break;
        }
        return result;
    }

    public static <T> T select(Collection<T> target, IPredicate<T> predicate, T defaultValue) {
        T result = defaultValue;
        for (T element : target) {
            if (!predicate.apply(element))
                continue;
            result = element;
            break;
        }
        return result;
    }
}

В следующем примере показано, как найти отсутствующие объекты между коллекциями:

List<MyTypeA> missingObjects = (List<MyTypeA>) Predicate.filter(myCollectionOfA,
    new IPredicate<MyTypeA>() {
        public boolean apply(MyTypeA objectOfA) {
            Predicate.predicateParams = objectOfA.getName();
            return Predicate.select(myCollectionB, new IPredicate<MyTypeB>() {
                public boolean apply(MyTypeB objectOfB) {
                    return objectOfB.getName().equals(Predicate.predicateParams.toString());
                }
            }) == null;
        }
    });

В следующем примере показано, как найти экземпляр в коллекции и вернуть первый элемент коллекции в качестве значения по умолчанию, если экземпляр не найден:

MyType myObject = Predicate.select(collectionOfMyType, new IPredicate<MyType>() {
public boolean apply(MyType objectOfMyType) {
    return objectOfMyType.isDefault();
}}, collectionOfMyType.get(0));

Обновление (после выпуска Java 8):

Прошли годы с тех пор, как я (Алан) впервые опубликовал этот ответ, и я до сих пор не могу поверить, что набрал так много баллов за этот ответ. Во всяком случае, посколькуJava 8С введением замыканий для языка мой ответ теперь будет намного другим и проще. то есть использоватьJava 8, без необходимости в уникальном статическом служебном классе. Итак, если вы хотите найти первый элемент, удовлетворяющий условию:

final UserService userService = ... // perhaps injected IoC
final Optional<UserModel> userOption = userCollection.stream().filter(u -> {
    boolean isAuthorized = userService.isAuthorized(u);
    return isAuthorized;
}).findFirst();

по желаниюJDK 8 APIимеютget(),isPresent(),orElse(defaultUser),orElseGet(userSupplier)иorElseThrow(exceptionSupplier)и другие одиночные методы, такие как:map, flatMapиfilter.

Если вы просто хотите отфильтровать всех пользователей, соответствующих условию, используйте сборщик, чтобы завершить поток в нужной коллекции:

final UserService userService = ... // perhaps injected IoC
final List<UserModel> userOption = userCollection.stream().filter(u -> {
    boolean isAuthorized = userService.isAuthorized(u);
    return isAuthorized;
}).collect(Collectors.toList());

существуетздесьможно увидеть больше оJava 8поток(Stream) пример того, как это работает.

Статья переведена с Stack Overflow:stackoverflow.com/questions/1…