本文正在参加「Java主题月 – Java Debug笔记活动」,详情查看 活动链接
提问:筛选 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,我会做一些与谷歌非常相似的事情。
首先将下面的接口添加到你的代码中:
public interface IPredicate<T> { boolean apply(T type); }
复制代码当判断为某种类型的真时,实现者可以进行返回。例如:如果 T 是 User,并且AuthorizedUserPredicate <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 发布后):
自从我(Alan)首次发布此答案以来已经有好几年了,但我仍然不敢相信我正在为此答案收集这么多的点。无论如何,既然 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 Overfloww:stackoverflow.com/questions/1…






















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)
