이유가 있습니까?
Lists.transform()
하지만
Lists.filter()
?
목록을 올바르게 필터링하려면 어떻게합니까? 나는 사용할 수있다
new ArrayList(Collection2.filter())
물론,하지만 이렇게하면 내가 올바르게 이해한다면 내 주문이 동일하게 유지된다는 보장은 없습니다.
이유가 있습니까?
Lists.transform()
하지만
Lists.filter()
?
목록을 올바르게 필터링하려면 어떻게합니까? 나는 사용할 수있다
new ArrayList(Collection2.filter())
물론,하지만 이렇게하면 내가 올바르게 이해한다면 내 주문이 동일하게 유지된다는 보장은 없습니다.
List.newArrayList(Iterables.filter(...))
라고해야합니다 Lists.newArrayList(Iterables.filter(...))
.
답변:
반환 된 목록보기에 #get (index)와 같은 위험한 많은 수의 느린 메서드가 노출되기 때문에 구현되지 않았습니다 (성능 버그 초대). 그리고 ListIterator는 구현하기에도 고통 스러울 것입니다 ( 패치를 제출했지만 몇 년 전에 ).
인덱싱 된 메서드는 필터링 된 목록보기에서 효율적일 수 없기 때문에 필터링 된 Iterable을 사용하지 않는 것이 좋습니다.
filter
지속적으로 그의 여부 (의미 동작과 함께)보기를 의미 Iterables.filter
, Sets.filter
등 때문에 Iterables.filter
쉽게와 결합 copyOf
어떤에 ImmutableCollection
, 내가 찾을이 좋은 디자인 트레이드 오프 (같은 별도의 방법 및 이름으로 오는 대 filteredCopy
또는 이것 저것 , 간단한 유틸리티의 조합).
당신이 사용할 수있는 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 관리자 중 한 명이 진짜 이유를 알아낼 것입니다. :)
Collections2.filter.iterator
을 호출하기 만하면 Iterables.filter
결과는 동일합니다.
Iterables.filter
명확성을 위해 버전을 사용합니다 .
view.size()
나중에 코드에서 어딘가 가 필요하지 않는 한 :)
new List(Collection2.filter())
물론 사용할 수 는 있지만 이렇게하면 내 주문이 동일하게 유지된다는 보장이 없습니다.
이것은 사실이 아닙니다. Collections2.filter()
느리게 평가되는 함수입니다. 필터링 된 버전에 액세스하기 시작할 때까지 실제로 컬렉션을 필터링하지 않습니다. 예를 들어 필터링 된 버전을 반복하는 경우 필터링 된 요소는 원래 컬렉션과 동일한 순서로 반복자에서 튀어 나옵니다 (분명히 필터링 된 요소 제외).
아마도 당신은 그것이 필터링을 미리 수행 한 다음 결과를 임의의 임의의 정렬되지 않은 컬렉션으로 덤프한다고 생각하고 있었을 것입니다.
따라서의 출력을 Collections2.filter()
새 목록에 대한 입력으로 사용하면 원래 주문 이 유지됩니다.
정적 가져 오기 (및 Lists.newArrayList
함수)를 사용하면 상당히 간결 해집니다.
List filteredList = newArrayList(filter(originalList, predicate));
반면이 있습니다 Collections2.filter
열망으로 반복 기본 콜렉션,하지 않을 Lists.newArrayList
것이다 는 필터링 콜렉션의 모든 요소를 추출하고 그들에게 새로운에 복사 - ArrayList
.
List filteredList = newArrayList(filter(originalList, new Predicate<T>() { @Override public boolean apply(T input) { return (...); } }));
또는 ie. List filteredList = newArrayList(filter(originalList, Predicates.notNull()));
Jon이 언급했듯이 Iterables.filter(..)
or 를 사용할 수 Collections2.filter(..)
있으며 라이브 뷰가 필요하지 않은 경우 ImmutableList.copyOf(Iterables.filter(..))
or 를 사용할 수 Lists.newArrayList( Iterables.filter(..))
있으며 예 주문이 유지됩니다.
왜 부분에
관심이 있다면 https://github.com/google/guava/issues/505 에서 자세한 내용을 확인할 수 있습니다 .