java.util.Collection
조건 자를 기반으로 기준 을 필터링하고 싶습니다 .
답변
Java 8 ( 2014 )은 한 줄의 코드로 스트림과 람다를 사용하여이 문제를 해결합니다.
List<Person> beerDrinkers = persons.stream()
.filter(p -> p.getAge() > 16).collect(Collectors.toList());
튜토리얼은 다음과 같습니다 .
Collection#removeIf
컬렉션을 제자리에 수정하는 데 사용 합니다. (주의 사항 :이 경우 술어는 술어를 만족시키는 오브젝트를 제거합니다) :
persons.removeIf(p -> p.getAge() <= 16);
lambdaj를 사용하면 루프 나 내부 클래스를 작성하지 않고도 컬렉션을 필터링 할 수 있습니다.
List<Person> beerDrinkers = select(persons, having(on(Person.class).getAge(),
greaterThan(16)));
더 읽기 쉬운 것을 상상할 수 있습니까?
면책 조항 : 나는 lambdaj에 기고자입니다
답변
Java 1.5 를 사용하고 있고 Google Collections를 추가 할 수 없다고 가정하면 Google 직원 과 매우 유사한 작업을 수행합니다. 이것은 Jon의 의견에 약간의 변형입니다.
먼저이 인터페이스를 코드베이스에 추가하십시오.
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라고 함)에서 술어가 예상 값을 반환하지 않을 때 기본값 옵션과 함께 select 메소드를 추가했으며 새 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 릴리스 이후) :
I (Alan)이이 답변을 처음 게시 한 지 몇 년이 지났지 만 여전히이 답변에 대한 SO 포인트를 수집하고 있다고 믿을 수 없습니다. 어쨌든 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
.
술어와 일치하는 모든 사용자를 단순히 수집하려면를 사용 Collectors
하여 원하는 콜렉션에서 스트림을 종료하십시오.
final UserService userService = ... // perhaps injected IoC
final List<UserModel> userOption = userCollection.stream().filter(u -> {
boolean isAuthorized = userService.isAuthorized(u);
return isAuthorized;
}).collect(Collectors.toList());
답변
Apache Commons의 CollectionUtils.filter (Collection, Predicate)를 사용하십시오 .
답변
“최상의”방법은 요청이 너무 넓습니다. “가장 짧습니까?” “가장 빠르다”? “읽기 쉬운”? 제자리에서 또는 다른 컬렉션으로 필터링 하시겠습니까?
가장 단순하지만 읽기 쉬운 방법은 반복하고 Iterator.remove () 메서드를 사용하는 것입니다.
Iterator<Foo> it = col.iterator();
while( it.hasNext() ) {
Foo foo = it.next();
if( !condition(foo) ) it.remove();
}
이제 더 읽기 쉽게하기 위해 유틸리티 메소드로 랩핑 할 수 있습니다. 그런 다음 IPredicate 인터페이스를 발명하고 해당 인터페이스의 익명 구현을 작성하고 다음과 같은 작업을 수행하십시오.
CollectionUtils.filterInPlace(col,
new IPredicate<Foo>(){
public boolean keepIt(Foo foo) {
return foo.isBar();
}
});
여기서 filterInPlace ()는 컬렉션을 반복하고 Predicate.keepIt ()을 호출하여 컬렉션에 유지할 인스턴스가 있는지 확인합니다.
나는이 작업을 위해 타사 라이브러리를 가져 오는 것에 대한 정당화를 실제로 보지 못합니다.
답변
제네릭을 지원하는 업데이트 된 컬렉션 프레임 워크에 대해서는 Google 컬렉션 을 고려하십시오 .
업데이트 : Google 컬렉션 라이브러리는 더 이상 사용되지 않습니다. 대신 최신 버전의 구아바 를 사용해야합니다 . 술어를 기반으로 필터링하는 메커니즘을 포함하여 콜렉션 프레임 워크에 대한 모든 확장이 여전히 있습니다.
답변
Java 8을 기다리십시오.
List<Person> olderThan30 =
//Create a Stream from the personList
personList.stream().
//filter the element to select only those with age >= 30
filter(p -> p.age >= 30).
//put those filtered elements into a new List.
collect(Collectors.toList());
답변
Java 8의 초기 릴리스 이후 다음과 같은 것을 시도해 볼 수 있습니다.
Collection<T> collection = ...;
Stream<T> stream = collection.stream().filter(...);
예를 들어, 정수 목록이 있고> 10보다 큰 숫자를 필터링 한 다음 해당 숫자를 콘솔에 인쇄하려면 다음과 같이 할 수 있습니다.
List<Integer> numbers = Arrays.asList(12, 74, 5, 8, 16);
numbers.stream().filter(n -> n > 10).forEach(System.out::println);