Java Collection을 필터링하는 가장 좋은 방법은 무엇입니까?


답변:


699

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에 기고자입니다


34
멋지지만 정적 수입은 무슨 일이 일어나고 있는지 모호합니다. 참고로, select / having / on은 ch.lambdaj.Lambda에 대한 정식 수입품입니다. greatThan은 org.hamcrest.Matchers
MikePatel

11
LambdaJ는 매우 섹시하지만 code.google.com/p/lambdaj/wiki/PerformanceAnalysis와 같은 중요한 오버 헤드 (2.6 평균)를 의미합니다 .
Doc Davluz

7
분명히 안드로이드에서는 작동하지 않습니다 : groups.google.com/forum/#!msg/lambdaj/km7uFgvSd3k/grJhgl3ik5sJ
Moritz

7
.NET 내장 Lambda 함수와 유사한 LamdaJ의이 예제와 같습니다. 16 세 때 사람은 어디에서 마실 수 있습니까? 현지화 제약 조건 추가를 고려해야합니다. : P
MAbraham1

3
예를 들면 다음과 같습니다persons.removeIf(p -> p.getAge() <= 16);
vim

223

Java 1.5 를 사용하고 있고 Google Collections를 추가 할 수 없다고 가정하면 Google 직원 과 매우 유사한 작업을 수행합니다. 이것은 Jon의 의견에 약간의 변형입니다.

먼저이 인터페이스를 코드베이스에 추가하십시오.

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라고 함)에서 술어가 예상 값을 반환하지 않을 때 기본값 옵션과 함께 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, flatMapfilter.

술어와 일치하는 모든 사용자를 단순히 수집하려면를 사용 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());

Java 8 스트림 작동 방식에 대한 자세한 예는 여기 를 참조 하십시오 .


27
그래, 그러나 나는 바퀴를 다시 반복해서 재발 명하는 것을 싫어한다. 차라리 원할 때 수행하는 유틸리티 라이브러리를 찾고 싶습니다.
케빈

2
새로운 컬렉션을 원하지 않는 경우에는 이것이 최선의 방법은 아닙니다. 새로운 컬렉션에 입력되거나 필요한 모든 필터 반복자 은유를 사용하십시오.
Josh

@Nestor : 스칼라 이해에서 필터링은 훨씬 간단합니다.val authorized = for (user <- users if user.isAuthorized) yield user
Alan

원본 컬렉션을 수정하거나 새로운 컬렉션을 생성합니까? 이 방법을 사용해 보았고 두 컬렉션 (원본과 메소드에서 반환 된 모음)을 모두 기록했습니다. @Alan
Rohan

1
@Rohan은 원본 컬렉션을 변경하지 않습니다. 위의 결과 콜렉션은 새로 구성되며, 술어가 적용되는 경우에만 필터 메소드가 결과 콜렉션에 추가됩니다.
Alan

92

Apache Commons의 CollectionUtils.filter (Collection, Predicate)를 사용하십시오 .


3
이것은 괜찮지 만 일반적인 것이 아니며 컬렉션을 적절하게 수정합니다 (좋지 않음)
Kevin Wong

2
CollectionUtils에는 원래 콜렉션을 수정하지 않는 다른 필터 메소드가 있습니다.
skaffman

42
특히 컬렉션을 수정 하지 않는 방법 은 org.apache.commons.collections.CollectionUtils # select (Collection, Predicate)
Eero

5
Commons Collections v4에서는 이제 Generics를 사용합니다.
저스틴 에머리

1
이 메소드는 컬렉션에 대해 선택적인 iterator.remove () 메소드에 의존하므로 (적어도 commons-collections-3.2.1 구현에서는)주의해서 사용해야합니다. 따라서 배열을 필터링하는 대신에 UnsupportedOperationException을 가져옵니다.
user2417480

67

"최상의"방법은 요청이 너무 넓습니다. "가장 짧습니까?" "가장 빠르다"? "읽기 쉬운"? 제자리에서 또는 다른 컬렉션으로 필터링 하시겠습니까?

가장 단순하지만 읽기 쉬운 방법은 반복하고 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 ()을 호출하여 컬렉션에 유지할 인스턴스가 있는지 확인합니다.

나는이 작업을 위해 타사 라이브러리를 가져 오는 것에 대한 정당화를 실제로 보지 못합니다.


6
내 투표는 이것을 위해 진행됩니다 : 그것은 외부 라이브러리없이 작동합니다. 반복자를 인스턴스화하면 실제로 for-each 구문을 사용하는 것과 비교할 때 유용하거나 ConcurrentModificationException 또는 이와 유사한 항목없이 목록에서 항목을 제거 할 수 있다는 것을 결코 깨닫지 못했습니다. :)
ZeroOne

1
이것이 표준 Java lib를 복사하지 않고 사용하는 가장 좋은 방법이라고 생각합니다. 1.8 들어있을 것입니다 stream()기능을하지만 모두가 최신 장난감을 재생 가져옵니다 P
사시 나무속

원본 컬렉션도 수정됩니까? @ZeroOne
Rohan

물론 그렇습니다, @Rohan. 당신이 그것을 믿지 않으면 그것을 시도하십시오. ;)
ZeroOne

하하! 하지만 원본 컬렉션을 유지하고 싶습니다. 외부 라이브러리를 추가하지 않고이를 수행하는 방법을 제안 할 수 있습니까? @ZeroOne
Rohan

62

제네릭을 지원하는 업데이트 된 컬렉션 프레임 워크에 대해서는 Google 컬렉션 을 고려하십시오 .

업데이트 : Google 컬렉션 라이브러리는 더 이상 사용되지 않습니다. 대신 최신 버전의 구아바 를 사용해야합니다 . 술어를 기반으로 필터링하는 메커니즘을 포함하여 콜렉션 프레임 워크에 대한 모든 확장이 여전히 있습니다.


나중에 Google 컬렉션 라이브러리에 대해 알고있었습니다. 내가 사용하고있는 버전에는 Collections2가 없습니다. 이 질문에 특정 방법을 나열하는 새로운 답변을 추가했습니다.
케빈

7
Kevin, Iterables.filter () 및 Iterators.filter ()는 처음부터 존재했으며 일반적으로 필요한 모든 것입니다.
Kevin Bourrillion 2009

28

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());

13
어 ... 매우 장황하다. 왜 그들이 할 수 없었는가 : List <Person> result = personList.filter (p-> p.age> 30);
케빈

8
Collection에서 직접 필터를 사용하려면 removeIf 호출을 사용해야 합니다. download.java.net/jdk8/docs/api/java/util/…
gavenkoa

6
@KevinWong "verbose"는 제가 생각할 언어 전체를 설명합니다. 최소한 일관성이 있습니까?
Rogue

5
마지막 부분에서 Collectors.toList ()를 사용하지 않는 이유는 무엇입니까?
Nestor Hernandez Loli

3
여기 에 404를 제공하지 않는 링크 gavenkoa가 personList.removeIf(p -> p.age < 30);있습니다. 덜 장황합니다. 또한 s가 매우 유용하고 빠르지 만 s로 가거나 나가는 속도가 느리기 때문에 s Stream대신 s 를 수락하고 반환하는 api를 구현하기 시작한다는 이야기를 들었습니다 . CollectionStream
Captain Man

11

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);

11

내가 던질거야 RxJava을 에도 사용할 수있는 링에 안드로이드 . RxJava가 항상 최상의 옵션은 아니지만 콜렉션에 더 많은 변환을 추가하거나 필터링하는 동안 오류를 처리하려는 경우 유연성이 향상됩니다.

Observable.from(Arrays.asList(1, 2, 3, 4, 5))
    .filter(new Func1<Integer, Boolean>() {
        public Boolean call(Integer i) {
            return i % 2 != 0;
        }
    })
    .subscribe(new Action1<Integer>() {
        public void call(Integer i) {
            System.out.println(i);
        }
    });

산출:

1
3
5

RxJava의에 대한 자세한 세부 사항은 filter찾을 수 있습니다 여기에 .


7

설정:

public interface Predicate<T> {
  public boolean filter(T t);
}

void filterCollection(Collection<T> col, Predicate<T> predicate) {
  for (Iterator i = col.iterator(); i.hasNext();) {
    T obj = i.next();
    if (predicate.filter(obj)) {
      i.remove();
    }
  }
}

사용법 :

List<MyObject> myList = ...;
filterCollection(myList, new Predicate<MyObject>() {
  public boolean filter(MyObject obj) {
    return obj.shouldFilter();
  }
});

2
좋습니다. 그러나 컬렉션을 변경하는 대신 복사본을 얻으므로 Alan 구현을 선호합니다. 또한 Alan의 코드는 스레드 안전하지만 귀하의 코드는 안전하지 않습니다.
marcospereira

7

평범하고 단호한 자바는 어떻습니까?

 List<Customer> list ...;
 List<Customer> newList = new ArrayList<>();
 for (Customer c : list){
    if (c.getName().equals("dd")) newList.add(c);
 }

간단하고 읽기 쉽고 (Android에서 작동합니다!) 그러나 Java 8을 사용하는 경우 달콤한 한 줄로 할 수 있습니다.

List<Customer> newList = list.stream().filter(c -> c.getName().equals("dd")).collect(toList());

toList ()를 정적으로 가져옵니다.



7

Eclipse Collections를 사용하여 내장 JDK 목록 및 MutableList 를 필터링하는 방법을 살펴 보겠습니다 .

List<Integer> jdkList = Arrays.asList(1, 2, 3, 4, 5);
MutableList<Integer> ecList = Lists.mutable.with(1, 2, 3, 4, 5);

3보다 작은 숫자를 필터링하려면 다음과 같은 출력이 필요합니다.

List<Integer> selected = Lists.mutable.with(1, 2);
List<Integer> rejected = Lists.mutable.with(3, 4, 5);

다음은 Java 8 람다를 사용하여 필터링하는 방법 Predicate입니다.

Assert.assertEquals(selected, Iterate.select(jdkList, each -> each < 3));
Assert.assertEquals(rejected, Iterate.reject(jdkList, each -> each < 3));

Assert.assertEquals(selected, ecList.select(each -> each < 3));
Assert.assertEquals(rejected, ecList.reject(each -> each < 3));

익명 내부 클래스를로 사용하여 필터링하는 방법은 다음과 같습니다 Predicate.

Predicate<Integer> lessThan3 = new Predicate<Integer>()
{
    public boolean accept(Integer each)
    {
        return each < 3;
    }
};

Assert.assertEquals(selected, Iterate.select(jdkList, lessThan3));
Assert.assertEquals(selected, ecList.select(lessThan3));

다음은 Predicates 팩토리를 사용하여 JDK 목록 및 Eclipse 콜렉션 MutableList 를 필터링하는 몇 가지 대안 입니다.

Assert.assertEquals(selected, Iterate.select(jdkList, Predicates.lessThan(3)));
Assert.assertEquals(selected, ecList.select(Predicates.lessThan(3)));

다음은 Predicates2 팩토리를 대신 사용하는 selectWith메소드를 사용하여 술어에 오브젝트를 할당하지 않는 버전입니다 Predicate2.

Assert.assertEquals(
    selected, ecList.selectWith(Predicates2.<Integer>lessThan(), 3));

때때로 부정적인 조건을 필터링하려고합니다. Eclipse Collections에는 특별한 메소드가 reject있습니다.

Assert.assertEquals(rejected, Iterate.reject(jdkList, lessThan3));
Assert.assertEquals(rejected, ecList.reject(lessThan3));

이 메소드 partition는에 의해 선택되고 거부 된 요소를 포함하는 두 개의 콜렉션을 리턴합니다 Predicate.

PartitionIterable<Integer> jdkPartitioned = Iterate.partition(jdkList, lessThan3);
Assert.assertEquals(selected, jdkPartitioned.getSelected());
Assert.assertEquals(rejected, jdkPartitioned.getRejected());

PartitionList<Integer> ecPartitioned = gscList.partition(lessThan3);
Assert.assertEquals(selected, ecPartitioned.getSelected());
Assert.assertEquals(rejected, ecPartitioned.getRejected());

참고 : 저는 Eclipse Collections의 커미터입니다.


1
removeIf프리미티브에 대해 목록을 작성하거나 설정 하는 방법은 무엇입니까?
Vivek Rao

removeIf 용 API가 EC 9.1의 기본 컬렉션에 추가되었습니다. eclipse.org/collections/javadoc/9.1.0/org/eclipse/collections/…
Donald Raab

5

ForEach DSL을 사용하면

import static ch.akuhn.util.query.Query.select;
import static ch.akuhn.util.query.Query.$result;
import ch.akuhn.util.query.Select;

Collection<String> collection = ...

for (Select<String> each : select(collection)) {
    each.yield = each.value.length() > 3;
}

Collection<String> result = $result();

[The, quick, brown, fox, jumps, over, the lazy, dog] 모음이 주어지면 [quick, brown, jumps, over, lazy], 즉 3 문자보다 긴 모든 문자열이됩니다.

ForEach DSL에서 지원하는 모든 반복 스타일은 다음과 같습니다.

  • AllSatisfy
  • AnySatisfy
  • Collect
  • Counnt
  • CutPieces
  • Detect
  • GroupedBy
  • IndexOf
  • InjectInto
  • Reject
  • Select

자세한 내용은 https://www.iam.unibe.ch/scg/svn_repos/Sources/ForEach 를 참조 하십시오.


꽤 영리합니다! 멋진 Ruby-ish 구문을 구현하기위한 많은 작업! 필터가 일류 기능이 아니므로 재사용 할 수 없다는 단점이 있습니다. 폐쇄에 롤 ...
oxbow_lakes

좋은 지적. 루프 본문을 재사용하는 한 가지 방법은 루프를 선택 쿼리를 매개 변수로 사용하는 메서드로 리팩터링하는 것입니다. 그러나 그것은 실제 클로저만큼 편리하고 강력하지는 않습니다.
akuhn


5

Java 9 Collectors.filtering 가 사용 가능 하므로 :

public static <T, A, R>
    Collector<T, ?, R> filtering(Predicate<? super T> predicate,
                                 Collector<? super T, A, R> downstream)

따라서 필터링은 다음과 같아야합니다.

collection.stream().collect(Collectors.filtering(predicate, collector))

예:

List<Integer> oddNumbers = List.of(1, 19, 15, 10, -10).stream()
            .collect(Collectors.filtering(i -> i % 2 == 1, Collectors.toList()));

3

이것은 실제 클로저가 부족한 것과 함께 Java의 가장 큰 그립입니다. 솔직히, 위에서 언급 한 대부분의 방법은 읽기 쉽고 정말 효율적입니다. 그러나 .Net, Erlang 등으로 시간을 보낸 후 언어 수준에서 통합 된 목록 이해력은 모든 것을 훨씬 깨끗하게 만듭니다. 언어 수준에서 추가하지 않으면 Java는이 영역의 다른 많은 언어만큼 깨끗할 수 없습니다.

성능이 큰 관심사 인 경우 Google 컬렉션을 사용하는 것이 좋습니다 (또는 간단한 술어 유틸리티 작성). Lambdaj 구문은 일부 사람들에게 더 읽기 쉽지만 효율적이지 않습니다.

그리고 내가 쓴 라이브러리가 있습니다. 나는 그것의 효율성 (그렇습니다, 그 나쁜 것)에 관한 질문을 무시할 것입니다 ... 그렇습니다, 나는 그것의 명백한 반성을 기반으로 알고 있으며, 실제로 그것을 사용하지는 않지만 작동합니다 :

LinkedList<Person> list = ......
LinkedList<Person> filtered = 
           Query.from(list).where(Condition.ensure("age", Op.GTE, 21));

또는

LinkedList<Person> list = ....
LinkedList<Person> filtered = Query.from(list).where("x => x.age >= 21");

링크? 라이브러리가 비효율적이거나 사용 불가능하더라도 소스가 사용 가능한지 살펴 보는 것이 흥미로울 수 있습니다.
MatrixFrog

리포지토리를 공개했습니다 ( net-machine.com/indefero/p/jdclib/source/tree/master ). 표현식 패키지에 관심이 있습니다. 테스트 패키지에는 사용 예제가있는 테스터가 있습니다. 위에서 언급 한 문자열 쿼리 인터페이스 (실제 파서를 작성하는 느낌이 들지 않음)에서 실제로 많은 작업을 수행하지 않았으므로 테스터의 명시 적 쿼리 인터페이스가 좋습니다.
jdc0589

2

JFilter http://code.google.com/p/jfilter/ 는 요구 사항에 가장 적합합니다.

JFilter는 Java Bean의 콜렉션을 조회하기위한 단순하고 고성능의 오픈 소스 라이브러리입니다.

주요 특징들

  • 콜렉션 (java.util.Collection, java.util.Map 및 Array) 특성 지원
  • 모든 깊이의 컬렉션 내에서 컬렉션을 지원합니다.
  • 내부 쿼리 지원
  • 매개 변수화 된 쿼리 지원
  • 몇 100ms 내에 백만 개의 레코드를 필터링 할 수 있습니다.
  • 필터 (쿼리)는 간단한 json 형식으로 제공되며 Mangodb 쿼리와 같습니다. 다음은 몇 가지 예입니다.
  • { "id": { "$ le": "10"}
    • 여기서 object id 속성은 10보다 작습니다.
  • { "id": { "$ in": [ "0", "100"]}}
    • 여기서 object id 속성은 0 또는 100입니다.
  • { "lineItems": { "lineAmount": "1"}}
    • 여기서 매개 변수화 된 유형의 lineItems 콜렉션 특성은 lineAmount가 1과 같습니다.
  • { "$ and": [{ "id": "0"}, { "billingAddress": { "city": "DEL"}}]}
    • 여기서 id 속성은 0이고 billingAddress.city 속성은 DEL입니다.
  • { "lineItems": { "taxes": { "key": { "code": "GST"}, "value": { "$ gt": "1.01"}}}}
    • 여기서 parameteriszed 유형의 세금 맵 유형 특성이있는 매개 변수화 된 유형의 lineItems 콜렉션 특성의 코드는 1.01보다 큰 GST 값과 같습니다.
  • { '$ or': [{ 'code': '10'}, { 'skus': { '$ and': [{ 'price': { '$ in': [ '20', '40']} }, { 'code': 'RedApple'}]}}]}}
    • 20 및 40의 제품 코드가 10 또는 SKU 가격이고 Sku 코드가 "RedApple"인 모든 제품을 선택하십시오.

1
당신은 당신이 저자라고 주장하지 않아야합니다.
assylias

예, 저는이 도서관의 저자입니다.
Kamran Ali Khan

2

컬렉션 내용을 복사하지 않고 기능 알고리즘 적용을 지원 하는 확장 된 Iterable 클래스 를 작성 했습니다.

용법:

List<Integer> myList = new ArrayList<Integer>(){ 1, 2, 3, 4, 5 }

Iterable<Integer> filtered = Iterable.wrap(myList).select(new Predicate1<Integer>()
{
    public Boolean call(Integer n) throws FunctionalException
    {
        return n % 2 == 0;
    }
})

for( int n : filtered )
{
    System.out.println(n);
}

위의 코드는 실제로 실행됩니다

for( int n : myList )
{
    if( n % 2 == 0 ) 
    {
        System.out.println(n);
    }
}


2

여기에 정말 좋은 답변이 있습니다. 나는 가능한 한 단순하고 읽기 쉬운 씬을 유지하고 싶습니다.

public abstract class AbstractFilter<T> {

    /**
     * Method that returns whether an item is to be included or not.
     * @param item an item from the given collection.
     * @return true if this item is to be included in the collection, false in case it has to be removed.
     */
    protected abstract boolean excludeItem(T item);

    public void filter(Collection<T> collection) {
        if (CollectionUtils.isNotEmpty(collection)) {
            Iterator<T> iterator = collection.iterator();
            while (iterator.hasNext()) {
                if (excludeItem(iterator.next())) {
                    iterator.remove();
                }
            }
        }
    }
}

필터 당 적절한 excludeItem을 구현하십시오. 당신은 소장품에 대한 분류 기가있는 그대로 별도의 필터를 갖게 될 것입니다.
Lawrence

1

간단한 Java8 이전 솔루션 :

ArrayList<Item> filtered = new ArrayList<Item>(); 
for (Item item : items) if (condition(item)) filtered.add(item);

불행히도이 솔루션은 완전히 일반적인 것은 아니며 주어진 컬렉션의 유형이 아닌 목록을 출력합니다. 또한 라이브러리를 가져 오거나이 코드를 래핑하는 함수를 작성하는 것은 조건이 복잡하지 않으면 나에게 과도한 것처럼 보이지만 조건에 대한 함수를 작성할 수 있습니다.


1

https://code.google.com/p/joquery/

다양한 가능성을 지원합니다.

주어진 컬렉션,

Collection<Dto> testList = new ArrayList<>();

유형의

class Dto
{
    private int id;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getText()
    {
        return text;
    }
}

필터

자바 7

Filter<Dto> query = CQ.<Dto>filter(testList)
    .where()
    .property("id").eq().value(1);
Collection<Dto> filtered = query.list();

자바 8

Filter<Dto> query = CQ.<Dto>filter(testList)
    .where()
    .property(Dto::getId)
    .eq().value(1);
Collection<Dto> filtered = query.list();

또한,

Filter<Dto> query = CQ.<Dto>filter()
        .from(testList)
        .where()
        .property(Dto::getId).between().value(1).value(2)
        .and()
        .property(Dto::grtText).in().value(new string[]{"a","b"});

정렬 (Java 7에도 사용 가능)

Filter<Dto> query = CQ.<Dto>filter(testList)
        .orderBy()
        .property(Dto::getId)
        .property(Dto::getName)
    Collection<Dto> sorted = query.list();

그룹화 (Java 7에도 사용 가능)

GroupQuery<Integer,Dto> query = CQ.<Dto,Dto>query(testList)
        .group()
        .groupBy(Dto::getId)
    Collection<Grouping<Integer,Dto>> grouped = query.list();

조인 (Java 7에서도 사용 가능)

주어진,

class LeftDto
{
    private int id;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getText()
    {
        return text;
    }
}

class RightDto
{
    private int id;
    private int leftId;
    private String text;

    public int getId()
    {
        return id;
    }

    public int getLeftId()
        {
            return leftId;
        }

    public int getText()
    {
        return text;
    }
}

class JoinedDto
{
    private int leftId;
    private int rightId;
    private String text;

    public JoinedDto(int leftId,int rightId,String text)
    {
        this.leftId = leftId;
        this.rightId = rightId;
        this.text = text;
    }

    public int getLeftId()
    {
        return leftId;
    }

    public int getRightId()
        {
            return rightId;
        }

    public int getText()
    {
        return text;
    }
}

Collection<LeftDto> leftList = new ArrayList<>();

Collection<RightDto> rightList = new ArrayList<>();

다음과 같이 참여할 수 있습니다.

Collection<JoinedDto> results = CQ.<LeftDto, LeftDto>query().from(leftList)
                .<RightDto, JoinedDto>innerJoin(CQ.<RightDto, RightDto>query().from(rightList))
                .on(LeftFyo::getId, RightDto::getLeftId)
                .transformDirect(selection ->  new JoinedDto(selection.getLeft().getText()
                                                     , selection.getLeft().getId()
                                                     , selection.getRight().getId())
                                 )
                .list();

표현

Filter<Dto> query = CQ.<Dto>filter()
    .from(testList)
    .where()
    .exec(s -> s.getId() + 1).eq().value(2);

1

내 대답은 Kevin Wong의 CollectionUtils 부터 Java 8 람다 식을 사용하는 단일 라이너로 작성 합니다.

CollectionUtils.filter(list, p -> ((Person) p).getAge() > 16);

이것은 내가 본 다른 대안처럼 간결하고 읽을 수 있습니다 (화면 기반 라이브러리를 사용하지 않고)

Spring CollectionUtils 는 스프링 버전 4.0.2.RELEASE에서 사용 가능하며 JDK 1.8 및 언어 레벨 8 이상이 필요합니다.


1

사용 java 8특히 lambda expression, 당신은 단순히 예를 아래처럼 할 수있다 :

myProducts.stream().filter(prod -> prod.price>10).collect(Collectors.toList())

product내부 myProducts컬렉션 에 대해 이면 prod.price>10이 제품을 새로운 필터링 된 목록에 추가하십시오.


1

목록에 이미 존재하는 값에 따라 목록을 필터링해야했습니다. 예를 들어, 현재 값보다 작은 다음 값을 모두 제거하십시오. {2 5 3 4 7 5}-> {2 5 7}. 또는 예를 들어 모든 중복을 제거하려면 {3 5 4 2 3 5 6}-> {3 5 4 2 6}.

public class Filter {
    public static <T> void List(List<T> list, Chooser<T> chooser) {
        List<Integer> toBeRemoved = new ArrayList<>();
        leftloop:
        for (int right = 1; right < list.size(); ++right) {
            for (int left = 0; left < right; ++left) {
                if (toBeRemoved.contains(left)) {
                    continue;
                }
                Keep keep = chooser.choose(list.get(left), list.get(right));
                switch (keep) {
                    case LEFT:
                        toBeRemoved.add(right);
                        continue leftloop;
                    case RIGHT:
                        toBeRemoved.add(left);
                        break;
                    case NONE:
                        toBeRemoved.add(left);
                        toBeRemoved.add(right);
                        continue leftloop;
                }
            }
        }

        Collections.sort(toBeRemoved, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });

        for (int i : toBeRemoved) {
            if (i >= 0 && i < list.size()) {
                list.remove(i);
            }
        }
    }

    public static <T> void List(List<T> list, Keeper<T> keeper) {
        Iterator<T> iterator = list.iterator();
        while (iterator.hasNext()) {
            if (!keeper.keep(iterator.next())) {
                iterator.remove();
            }
        }
    }

    public interface Keeper<E> {
        boolean keep(E obj);
    }

    public interface Chooser<E> {
        Keep choose(E left, E right);
    }

    public enum Keep {
        LEFT, RIGHT, BOTH, NONE;
    }
}

이 같은 꿀벌이 사용됩니다.

List<String> names = new ArrayList<>();
names.add("Anders");
names.add("Stefan");
names.add("Anders");
Filter.List(names, new Filter.Chooser<String>() {
    @Override
    public Filter.Keep choose(String left, String right) {
        return left.equals(right) ? Filter.Keep.LEFT : Filter.Keep.BOTH;
    }
});

0

구아바와 함께 :

Collection<Integer> collection = Lists.newArrayList(1, 2, 3, 4, 5);

Iterators.removeIf(collection.iterator(), new Predicate<Integer>() {
    @Override
    public boolean apply(Integer i) {
        return i % 2 == 0;
    }
});

System.out.println(collection); // Prints 1, 3, 5

0

Java 8에서는이 필터 메소드를 직접 사용한 다음 수행 할 수 있습니다.

 List<String> lines = Arrays.asList("java", "pramod", "example");

 List<String> result = lines.stream()              
         .filter(line -> !"pramod".equals(line))     
         .collect(Collectors.toList());              

 result.forEach(System.out::println); 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.