web-dev-qa-db-ja.com

Java 8でcollect呼び出しを使用するには?

私たち全員が使用しなければならないこの退屈なコードがあるとしましょう:

ArrayList<Long> ids = new ArrayList<Long>();
for (MyObj obj : myList){
    ids.add(obj.getId());
}

Java 8、my IDEは、このコードをcollect callに置き換えることができると言っており、自動生成されます:

ArrayList<Long> ids = myList.stream().map(MyObj::getId).collect(Collectors.toList());

しかし、それは私にこのエラーを与えます:

steamのcollect(Java.util.stream.Collector)は以下に適用できません:(Java.util.stream.Collector、capture、Java.util.List>)

パラメーターをキャストしようとしましたが、未定義のAおよびRを提供し、IDEはそれ以上の提案を提供しません。

このシナリオでcollect callをどのように使用できるか興味があり、適切なガイドとなる情報が見つかりませんでした。誰もが光を当てることができますか?

22

問題は、 Collectors.toList が驚くことではないが、List<T>を返すことです。 ArrayListではありません。

List<Long> ids = remove.stream()
        .map(MyObj::getId)
        .collect(Collectors.toList());

interfaceへのプログラム。

ドキュメントから:

入力要素を新しいCollectorに蓄積するListを返します。 Listの型、可変性、直列化可能性、スレッドセーフ性についての保証はありません;返されたリストをさらに制御する必要がある場合は、toCollection(Supplier)を使用します。

私の強調-返されたListが特定のクラスであることは言うまでもなく、可変であると仮定することさえできません。 ArrayListが必要な場合:

ArrayList<Long> ids = remove.stream()
        .map(MyObj::getId)
        .collect(Collectors.toCollection(ArrayList::new));

また、Java 8 Stream AP​​Iでimport staticを使用するのが慣習であるため、以下を追加することにも注意してください。

import static Java.util.stream.Collectors.toCollection;

(スター付きのimport staticは嫌いです。名前空間を汚染して混乱を招くだけです。しかし、特にJava 8ユーティリティクラスでは、選択的なimport staticは冗長なコードを大幅に削減できます)

結果として:

ArrayList<Long> ids = remove.stream()
        .map(MyObj::getId)
        .collect(toCollection(ArrayList::new));
47

私は空の配列を作成し、ループを使用してそれを埋めるコレクターブロックをたくさん使用しているので、同じ行を再び広告しないように独自のユーティリティクラスが必要であると判断しました。

public class Collections {

    public static <T, O> List<T> collect(Set<O> items, Function<? super O, ? extends T> mapper) {

    return items.stream().map(mapper).collect(Collectors.toCollection(ArrayList::new));
}

}

そして、このように使用します

List<Product> prods = Collections.collect(basket.getOrderItems(), OrderItem::getProduct);

またはこのように

List<Long> prods = Collections.collect(basket.getOrderItems(), (item)->item.getProduct().getId());

読みやすいように見えるかもしれませんが、この種のシナリオではストリームが少し遅いようです こちらをご覧ください

2
azerafati