私たち全員が使用しなければならないこの退屈なコードがあるとしましょう:
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
をどのように使用できるか興味があり、適切なガイドとなる情報が見つかりませんでした。誰もが光を当てることができますか?
問題は、 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
APIで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));
私は空の配列を作成し、ループを使用してそれを埋めるコレクターブロックをたくさん使用しているので、同じ行を再び広告しないように独自のユーティリティクラスが必要であると判断しました。
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());
読みやすいように見えるかもしれませんが、この種のシナリオではストリームが少し遅いようです こちらをご覧ください