Javaコレクションをフィルタリングする最良の方法は何ですか?


回答:


698

Java 8(2014)は、1行のコードでストリームとラムダを使用してこの問題を解決します。

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は本当にセクシーですが、かなりのオーバーヘッド(平均2.6)を意味することに注意してください:code.google.com/p/lambdaj/wiki/PerformanceAnalysis
Doc Davluz、2012

7
Androidでは動作しないようです:groups.google.com/forum
Moritz

7
本当にこのLamdaJの例のように... .NET組み込みLambda関数に似ています。そして、人は16歳でどこで飲むことができますか?ローカリゼーション制約の追加を検討する必要があります。:P
MAbraham1 2013

3
removeIfの例は次のようになりますpersons.removeIf(p -> p.getAge() <= 16);
vim

223

Java 1.5を使用していて、Googleコレクションを追加できないと仮定すると、Googleの担当者が行ったのと非常によく似たことを行います。これはジョンのコメントのわずかなバリエーションです。

まず、このインターフェイスをコードベースに追加します。

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内で使用されるparamsの静的プロパティも追加しました。

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リリース後):

私(アラン)が最初にこの回答を投稿してから数年になりますが、私はこの回答の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();

optionalsのためのJDK 8 APIは、能力にありget()isPresent()orElse(defaultUser)orElseGet(userSupplier)orElseThrow(exceptionSupplier)だけでなく、このような他の「モナド」機能mapflatMapおよびを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());

Java 8ストリームの動作の例については、こちらをご覧ください。


27
ええ、でも私は繰り返し、車輪を再発明するのが嫌いです。必要なときに機能するユーティリティライブラリを見つけたいと思います。
ケビンウォン

2
これは、新しいコレクションが必要ない場合に最適な方法ではありません。フィルターイテレーターのメタファーを使用します。これは、新しいコレクションに入力することも、必要なだけのこともあります。
Josh、

@Nestor:Scalaの理解では、フィルタリングははるかに単純になります:val authorized = for (user <- users if user.isAuthorized) yield user
Alan

これにより、元のコレクションが変更されたり、新しいコレクションが作成されたりしますか?私はこのメソッドを使用してみて、私のコレクション(オリジナルとメソッドから返されたもの)の両方をログに記録しましたが、それらは同じです。@Alan
Rohan

1
@Rohan、これは元のコレクションを変更するためのものではありません。上記の結果コレクションは新しく構築され、述語が適用される場合にのみ、filterメソッドが結果コレクションに追加されることに注意してください。
アラン

92

3
これは問題ありませんが、ジェネリックではなく、コレクションを適切に変更します(適切ではありません)
Kevin Wong

2
CollectionUtilsには、元のコレクションを変更しない他のフィルターメソッドがあります。
skaffman

42
特に、適切なコレクションを変更しないメソッドはorg.apache.commons.collections.CollectionUtils#select(Collection、Predicate)
Eero

5
Commons Collections v4では、これはGenericsを使用するようになりました。
ジャスティンエメリー2014年

1
このメソッドは(少なくともcommons-collections-3.2.1の実装では)コレクションのオプションであるiterator.remove()メソッドに依存しているため、注意して使用する必要があります。そのため、たとえば配列をフィルタリングする代わりに、 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
Populus

これは元のコレクションも変更しますか?@ZeroOne
Rohan

はい、もちろんそうです、@ Rohan。信じられない場合はお試しください。;)
ZeroOne 2016年

ははは!でも元のコレクションは残したい。外部ライブラリを追加せずにこれを行う方法を提案できますか?@ZeroOne
Rohan

62

ジェネリックをサポートする更新されたコレクションフレームワークについては、Googleコレクションを検討してください。

更新:Googleコレクションライブラリは非推奨になりました。代わりにGuavaの最新リリースを使用してください。述語に基づくフィルタリングのメカニズムを含む、コレクションフレームワークに対する拡張機能はすべて同じです。


ええ、私はグーグルコレクションのlibについて知っていました。私が使用していたバージョンには、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);
Kevin Wong

8
上の直接使用フィルタにコレクションあなたが使用する必要がremoveIfコール:download.java.net/jdk8/docs/api/java/util/...
gavenkoa

6
@KevinWongの「冗長」は、私が考える言語全体をほぼ説明しています。少なくともそれらは一貫していますか?
ローグ

5
最後の部分でCollectors.toList()を使用しないのはなぜですか?
Nestor Hernandez Loli 2014年

3
ここではない404ん提供リンクgavenkoaあるpersonList.removeIf(p -> p.age < 30);冗長少ないが。また、sは非常に便利で高速ですがStreamCollectionsとStreamの間の移動が遅いため、s ではなくs を受け入れて返すAPIの実装を開始するとの話を聞きました。
キャプテンマン

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をリングに投げます。これはAndroidでも使用できます。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 2008

7

平易で率直なJavaについてはどうですか

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

シンプルで読みやすく、簡単です(Androidでも動作します!)Java 8を使用している場合は、簡単な1行で実行できます。

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

toList()は静的にインポートされることに注意してください



7

Eclipseコレクションを使用して、組み込みの 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コレクションの MutableListsをフィルタリングするいくつかの代替方法を示します。

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

受け取るselectWithメソッドで代わりにPredicates2ファクトリーを使用して、述語にオブジェクトを割り当てないバージョンを次に示しますPredicate2

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

否定的な条件でフィルタリングしたい場合があります。Eclipseコレクションにはと呼ばれる特別なメソッドがありrejectます。

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

このメソッドpartitionは、によって選択され、拒否された要素を含む2つのコレクションを返し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コレクションのコミッターです。


1
removeIfプリミティブのリストまたはセットでどのように実行しますか?
Vivek Rao

removeIfのAPIは、EC 9.1のプリミティブコレクションに追加されました。eclipse.org/collections/javadoc/9.1.0/org/eclipse/collections/...
ドナルド・ラーブ

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っぽい構文を実装するのに多くの作業が必要です。欠点は、フィルターがファーストクラスの関数ではないため、再利用できないことです。クロージャーをロールオン...
oxbow_lakes 2009

いい視点ね。ループ本体を再利用する1つの方法は、選択クエリをパラメーターとして受け取るメソッドにループをリファクタリングすることです。しかし、それは確かに実際のクロージャーほど便利で強力ではありません。
アクーン、2009


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 2011年

リポジトリを公開しました(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)プロパティのサポート。
  • あらゆる深さのコレクション内でのコレクションのサポート。
  • 内部クエリのサポート。
  • パラメータ化されたクエリのサポート。
  • 数百ミリ秒で100万件のレコードをフィルタリングできます。
  • フィルター(クエリ)は単純なjson形式で与えられ、Mangodbクエリのようです。次にいくつかの例を示します。
  • {"id":{"$ le": "10"}
    • ここで、オブジェクトIDプロパティは10以下です。
  • {"id":{"$ in":["0"、 "100"]}}
    • オブジェクト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'}]}}]}
    • 製品コードが10または20および40のSKU価格でSKUコードが「RedApple」であるすべての製品を選択します。

1
あなたが著者であることを放棄する必要があります(私はそうだと思います)。
アッシリア2012

はい、私はこのライブラリの作者です。
Kamran Ali Khan、

2

私が書いた、拡張反復処理可能クラスをサポートは、コレクションの内容をコピーせずに機能的なアルゴリズムを適用すること。

使用法:

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

フィルタ

Java 7

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

Java 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

私の答えはここにワンライナーとして使用して、ケビンウォンからその上に構築CollectionUtilsからとJava 8 のラムダ式。

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

これは、(アスペクトベースのライブラリを使用せずに)私が見たどの代替手段と同じくらい簡潔で読みやすいです

Spring CollectionUtilsは、Spring バージョン4.0.2.RELEASEから利用できます。JDK1.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.