Halo sesama pengembang Java,
Saya tahu subjeknya mungkin sedikit in advance
karena JDK8 belum dirilis (dan bukan untuk saat ini ..) tetapi saya membaca beberapa artikel tentang ekspresi Lambda dan khususnya bagian yang terkait dengan API koleksi baru yang dikenal sebagai Stream.
Berikut adalah contoh yang diberikan dalam artikel Majalah Java (ini adalah algoritma populasi berang-berang ..):
Set<Otter> otters = getOtters();
System.out.println(otters.stream()
.filter(o -> !o.isWild())
.map(o -> o.getKeeper())
.filter(k -> k.isFemale())
.into(new ArrayList<>())
.size());
Pertanyaan saya adalah apa yang terjadi jika di tengah iterasi internal Set, salah satu otter adalah null?
Saya berharap NullPointerException dilemparkan tetapi mungkin saya masih terjebak dalam paradigma pengembangan sebelumnya (non-fungsional), dapatkah seseorang mencerahkan saya tentang bagaimana hal ini harus ditangani?
Jika ini benar-benar memunculkan NullPointerException, menurut saya fiturnya cukup berbahaya dan harus digunakan hanya seperti di bawah ini:
- Pengembang untuk memastikan tidak ada nilai null (mungkin menggunakan .filter sebelumnya (o -> o! = Null))
- Pengembang untuk memastikan aplikasi tidak pernah menghasilkan null otter atau objek NullOtter khusus untuk ditangani.
Apa opsi terbaik, atau opsi lain?
Terima kasih!
sumber
filter(Objects::nonNull)
denganObjects
darijava.utils
Jawaban:
Pemikiran saat ini tampaknya untuk "mentolerir" nulls, yaitu untuk mengizinkan mereka secara umum, meskipun beberapa operasi kurang toleran dan mungkin berakhir dengan membuang NPE. Lihat pembahasan nulls di milis grup pakar Perpustakaan Lambda, khususnya pesan ini . Konsensus seputar opsi # 3 kemudian muncul (dengan keberatan penting dari Doug Lea). Jadi ya, kekhawatiran OP tentang pipa yang meledak dengan NPE adalah valid.
Bukan tanpa alasan Tony Hoare menyebut nulls sebagai "Kesalahan Miliaran Dolar." Berurusan dengan nol adalah rasa sakit yang nyata. Bahkan dengan koleksi klasik (tanpa mempertimbangkan lambda atau aliran) null bermasalah. Seperti yang disebutkan fge dalam komentar, beberapa koleksi mengizinkan nulls dan yang lainnya tidak. Dengan koleksi yang memungkinkan null, ini memperkenalkan ambiguitas ke dalam API. Misalnya, dengan Map.get () , pengembalian null menunjukkan bahwa kunci ada dan nilainya null, atau bahwa kunci tidak ada. Kita harus melakukan pekerjaan ekstra untuk membedakan kasus-kasus ini.
Biasanya null digunakan untuk menunjukkan tidak adanya nilai. Pendekatan untuk menangani ini yang diusulkan untuk Java SE 8 adalah dengan memperkenalkan
java.util.Optional
tipe baru , yang merangkum ada / tidaknya nilai, bersama dengan perilaku penyediaan nilai default, atau melempar pengecualian, atau memanggil fungsi, dll. Jika nilainya tidak ada.Optional
hanya digunakan oleh API baru, meskipun, semua yang lain di sistem masih harus menghadapi kemungkinan null.Saran saya adalah untuk menghindari referensi nol yang sebenarnya sejauh mungkin. Sulit untuk melihat dari contoh yang diberikan bagaimana mungkin ada Otter "null". Tetapi jika diperlukan, saran OP untuk menyaring nilai null, atau memetakannya ke objek sentinel ( Pola Objek Null ) adalah pendekatan yang bagus.
sumber
null
menyebalkan, itu sebabnya. Acc. menurut survei yang saya lihat (tidak dapat menemukannya), NPE adalah pengecualian nomor 1 di Jawa. SQL bukanlah bahasa pemrograman tingkat tinggi, tentu saja tidak berfungsi, yang membenci null, jadi tidak peduli.Meskipun jawabannya 100% benar, sedikit saran untuk meningkatkan
null
penanganan kasus dari daftar itu sendiri dengan Opsional :Bagian ini
Optional.ofNullable(listOfStuff).orElseGet(Collections::emptyList)
akan memungkinkan Anda untuk menangani dengan baik kasus ketikalistOfStuff
null dan mengembalikan emptyList daripada gagal dengan NullPointerException.sumber
Jawaban Stuart memberikan penjelasan yang bagus, tapi saya ingin memberikan contoh lain.
Saya mengalami masalah ini ketika mencoba untuk melakukan
reduce
di Stream yang berisi nilai null (sebenarnya ituLongStream.average()
, yang merupakan jenis pengurangan). Karena rata-rata () kembaliOptionalDouble
, saya berasumsi Stream dapat berisi null tetapi NullPointerException dilemparkan. Ini karena penjelasan Stuart tentang null v. Empty.Jadi, seperti yang disarankan OP, saya menambahkan filter seperti ini:
list.stream() .filter(o -> o != null) .reduce(..);
Atau seperti yang ditunjukkan di bawah ini, gunakan predikat yang disediakan oleh Java API:
Dari diskusi milis Stuart ditautkan: Brian Goetz tentang nulls di Streams
sumber
Jika Anda hanya ingin memfilter nilai null dari aliran, Anda dapat menggunakan metode referensi ke java.util.Objects.nonNull (Object) . Dari dokumentasinya:
Sebagai contoh:
List<String> list = Arrays.asList( null, "Foo", null, "Bar", null, null); list.stream() .filter( Objects::nonNull ) // <-- Filter out null values .forEach( System.out::println );
Ini akan mencetak:
sumber
Contoh bagaimana menghindari null misalnya menggunakan filter sebelum groupingBy
Filter instance null sebelum groupingBy.
Berikut ini contohnyaMyObjectlist.stream() .filter(p -> p.getSomeInstance() != null) .collect(Collectors.groupingBy(MyObject::getSomeInstance));
sumber