JAVA 8 通過引入 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)));
你無法想象比這更容易理解的東西!
假設你使用的是 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 發布后):
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());