[java] 구아바 : Lists.filter () 함수가없는 이유는 무엇입니까?

이유가 있습니까?

Lists.transform()

하지만

Lists.filter()

?

목록을 올바르게 필터링하려면 어떻게합니까? 나는 사용할 수있다

new ArrayList(Collection2.filter())

물론,하지만 이렇게하면 내가 올바르게 이해한다면 내 주문이 동일하게 유지된다는 보장은 없습니다.



답변

반환 된 목록보기에 #get (index)와 같은 위험한 많은 수의 느린 메서드가 노출되기 때문에 구현되지 않았습니다 (성능 버그 초대). 그리고 ListIterator는 구현하기에도 고통 스러울 것입니다 ( 패치를 제출했지만 몇 년 전에 ).

인덱싱 된 메서드는 필터링 된 목록보기에서 효율적일 수 없기 때문에 필터링 된 Iterable을 사용하지 않는 것이 좋습니다.


답변

당신이 사용할 수있는 Iterables.filter 은 확실히 순서를 유지할 것입니다 .

새 목록을 구성 하면 요소 (물론 참조 만)를 복사하게 되므로 원래 목록에 대한 라이브 뷰가되지 않습니다. 보기를 만드는 것은 매우 까다로울 수 있습니다. 다음 상황을 고려하십시오.

Predicate<StringBuilder> predicate =
    /* predicate returning whether the builder is empty */
List<StringBuilder> builders = Lists.newArrayList();
List<StringBuilder> view = Lists.filter(builders, predicate);

for (int i = 0; i < 10000; i++) {
    builders.add(new StringBuilder());
}
builders.get(8000).append("bar");

StringBuilder firstNonEmpty = view.get(0);

그것은 모든 원본 목록을 반복하여 모든 것에 필터를 적용해야합니다. 조건 자 일치가 뷰의 수명 동안 변경되지 않도록 요구할 수 있다고 생각하지만 완전히 만족 스럽지는 않습니다.

(이것은 추측 일뿐입니다. 아마도 Guava 관리자 중 한 명이 진짜 이유를 알아낼 것입니다. 🙂


답변

new List(Collection2.filter())물론 사용할 수 는 있지만 이렇게하면 내 주문이 동일하게 유지된다는 보장이 없습니다.

이것은 사실이 아닙니다. Collections2.filter()느리게 평가되는 함수입니다. 필터링 된 버전에 액세스하기 시작할 때까지 실제로 컬렉션을 필터링하지 않습니다. 예를 들어 필터링 된 버전을 반복하는 경우 필터링 된 요소는 원래 컬렉션과 동일한 순서로 반복자에서 튀어 나옵니다 (분명히 필터링 된 요소 제외).

아마도 당신은 그것이 필터링을 미리 수행 한 다음 결과를 임의의 임의의 정렬되지 않은 컬렉션으로 덤프한다고 생각하고 있었을 것입니다.

따라서의 출력을 Collections2.filter()새 목록에 대한 입력으로 사용하면 원래 주문 유지됩니다.

정적 가져 오기 (및 Lists.newArrayList함수)를 사용하면 상당히 간결 해집니다.

List filteredList = newArrayList(filter(originalList, predicate));

반면이 있습니다 Collections2.filter열망으로 반복 기본 콜렉션,하지 않을 Lists.newArrayList 것이다 는 필터링 콜렉션의 모든 요소를 추출하고 그들에게 새로운에 복사 – ArrayList.


답변

Jon이 언급했듯이 Iterables.filter(..)or 를 사용할 수 Collections2.filter(..)있으며 라이브 뷰가 필요하지 않은 경우 ImmutableList.copyOf(Iterables.filter(..))or 를 사용할 수 Lists.newArrayList( Iterables.filter(..))있으며 예 주문이 유지됩니다.
부분에

관심이 있다면 https://github.com/google/guava/issues/505 에서 자세한 내용을 확인할 수 있습니다 .


답변

다른 사람들이 말한 것을 요약하면 목록을 필터링하는 일반 래퍼를 쉽게 만들 수 있습니다.

public static <T> List<T> filter(Iterable<T> userLists, Predicate<T> predicate) {
    return Lists.newArrayList(Iterables.filter(userLists, predicate));
}


답변