web-dev-qa-db-ja.com

グアバ:Lists.filter()関数がないのはなぜですか?

ある理由はありますか

Lists.transform()

でもない

Lists.filter()

リストを正しくフィルタリングするにはどうすればよいですか?使える

new ArrayList(Collection2.filter())

もちろん、しかし、この方法では、正しく理解した場合、注文が同じままであることは保証されません。

86
Fabian Zeindl

返されたリストビューで#get(index)などの危険な多数の低速メソッドを公開するため、実装されていません(パフォーマンスバグを招いています)。また、ListIteratorを実装するのも苦労します(それをカバーするために patch 年前に提出しましたが)。

インデックス付きメソッドは、フィルター処理されたリストビューでは効率的ではないため、フィルター処理されていないIterableを使用する方が良いでしょう。

57

Iterables.filterを使用できます。これにより、順序が確実に維持されます。

新しいリストを作成すると、copying要素(もちろん参照のみ)になるため、元のリストのライブビューにはならないことに注意してください。ビューを作成するのはかなり難しいでしょう-この状況を考慮してください:

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メンテナの1人がreal reasonでチップインするでしょう)

37
Jon Skeet

もちろんnew List(Collection2.filter())を使用することもできますが、この方法では順序が同じであることが保証されません。

これは真実ではありません。 Collections2.filter()は遅延評価された関数です-実際には、フィルターされたバージョンへのアクセスを開始するまでコレクションをフィルターしません。たとえば、フィルターされたバージョンを反復処理すると、フィルターされた要素が元のコレクションと同じ順序でイテレーターからポップアウトされます(明らかにフィルターされたものは除外されます)。

おそらく、前もってフィルタリングを実行してから、結果を何らかの形式の任意の順序付けされていないコレクションにダンプすると考えていたのかもしれません。

したがって、Collections2.filter()の出力を新しいリストへの入力として使用する場合、元の順序()が保持されます。

静的インポート(およびLists.newArrayList関数)、それはかなり簡潔になります:

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

Collections2.filterは、基礎となるコレクションに対して熱心に反復しません、Lists.newArrayListwill-フィルタリングされたコレクションのすべての要素を抽出し、それらを新しいArrayListにコピーします。

28
skaffman

ジョンが述べたように、Iterables.filter(..)またはCollections2.filter(..)を使用できます。ライブビューが必要ない場合は、ImmutableList.copyOf(Iterables.filter(..))またはLists.newArrayList( Iterables.filter(..))を使用できます。維持されます。

whyパートに本当に興味がある場合は、 https://github.com/google/guavaにアクセスできます。/issues/505 詳細については。

12
Premraj

他の人が言ったことを要約すると、リストをフィルタリングする汎用ラッパーを簡単に作成できます。

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