Предполагая, что вы используете Java 1.5 , и что вы не можете добавить Коллекции Google , я бы сделал что-то очень похожее на то, что сделали ребята Google. Это небольшое изменение в комментариях Джона.
Сначала добавьте этот интерфейс в свою кодовую базу.
public interface IPredicate { boolean apply(T type); }
Его разработчики могут ответить, когда определенный предикат является истинным для определенного типа. Например. Если T
были User
и AuthorizedUserPredicate
реализованы IPredicate
, тогда AuthorizedUserPredicate#apply
возвращает, разрешено ли переданное в User
.
Затем в каком-то классе утилиты вы могли бы сказать
public static Collection filter(Collection target, IPredicate predicate) {
Collection result = new ArrayList();
for (T element: target) {
if (predicate.apply(element)) {
result.add(element);
}
}
return result;
}
Итак, предполагая, что вы используете вышеупомянутое, может быть
Predicate isAuthorized = new Predicate() {
public boolean apply(User user) {
// binds a boolean method in User to a reference
return user.isAuthorized();
}
};
// allUsers is a Collection
Collection authorizedUsers = filter(allUsers, isAuthorized);
Если производительность на линейной проверке вызывает беспокойство, тогда я могу захотеть иметь объект домена который имеет целевую коллекцию. Объект домена, у которого есть целевая коллекция, будет иметь логику фильтрации для методов, которые инициализируют, добавляют и устанавливают целевую коллекцию.
UPDATE:
В классе утилиты (скажем, Predicate) , Я добавил метод select с опцией для значения по умолчанию, когда предикат не возвращает ожидаемое значение, а также статическое свойство для параметров, которые будут использоваться внутри нового IPredicate.
public class Predicate {
public static Object predicateParams;
public static Collection filter(Collection target, IPredicate predicate) {
Collection result = new ArrayList();
for (T element : target) {
if (predicate.apply(element)) {
result.add(element);
}
}
return result;
}
public static T select(Collection target, IPredicate predicate) {
T result = null;
for (T element : target) {
if (!predicate.apply(element))
continue;
result = element;
break;
}
return result;
}
public static T select(Collection target, IPredicate predicate, T defaultValue) {
T result = defaultValue;
for (T element : target) {
if (!predicate.apply(element))
continue;
result = element;
break;
}
return result;
}
}
следующий пример ищет отсутствующие объекты между коллекциями:
List missingObjects = (List) Predicate.filter(myCollectionOfA,
new IPredicate() {
public boolean apply(MyTypeA objectOfA) {
Predicate.predicateParams = objectOfA.getName();
return Predicate.select(myCollectionB, new IPredicate() {
public boolean apply(MyTypeB objectOfB) {
return objectOfB.getName().equals(Predicate.predicateParams.toString());
}
}) == null;
}
});
В следующем примере ищет экземпляр в коллекции и возвращает первый элемент коллекции как значение по умолчанию, когда экземпляр не найден:
MyType myObject = Predicate.select(collectionOfMyType, new IPredicate() {
public boolean apply(MyType objectOfMyType) {
return objectOfMyType.isDefault();
}}, collectionOfMyType.get(0));
UPDATE (после выпуска Java 8):
Прошло несколько лет с тех пор, как я (Алан) впервые опубликовал этот ответ, и я до сих пор не могу поверить, что собираю SO-очки для этого ответ. Во всяком случае, теперь, когда Java 8 представила закрытие языка, мой ответ теперь будет значительно другим и более простым. С Java 8 нет необходимости в отдельном статическом классе утилиты. Поэтому, если вы хотите найти 1-й элемент, который соответствует вашему предикату.
final UserService userService = ... // perhaps injected IoC
final Optional userOption = userCollection.stream().filter(u -> {
boolean isAuthorized = userService.isAuthorized(u);
return isAuthorized;
}).findFirst();
API JDK 8 для опциональных опций имеет возможность get()
, isPresent()
, orElse(defaultUser)
, orElseGet(userSupplier)
и orElseThrow(exceptionSupplier)
, а также другие «монадические» функции, такие как map
, flatMap
и filter
.
Если вы хотите просто собрать всех пользователей, которые соответствуют предикату, затем используйте Collectors
, чтобы завершить поток в нужной коллекции.
final UserService userService = ... // perhaps injected IoC
final List userOption = userCollection.stream().filter(u -> {
boolean isAuthorized = userService.isAuthorized(u);
return isAuthorized;
}).collect(Collectors.toList());
Подробнее см. здесь о том, как работают потоки Java 8.