Daftar subdirektori menggunakan flatMap
Kita telah melihat sebelumnya bagaimana membuat daftar file dalam direktori tertentu. Mari kita lihat cara melintasi subdirektori langsung dari direktori yang ditentukan (kedalamannya 1), pertama-tama terapkan versi sederhana, lalu gunakan metode flatMap() yang lebih nyaman untuk mengimplementasikannya.
Pertama-tama kita menggunakan perulangan for tradisional untuk melintasi direktori tertentu. Jika ada file di subdirektori, tambahkan file tersebut ke daftar; jika tidak, tambahkan subdirektori ke daftar. Terakhir, cetak jumlah total semua file. Kode di bawah - ini untuk mode keras.
Copy kode kodenya sebagai berikut:
daftar kekosongan statis publikTheHardWay() {
Daftar<File> file = Daftar Array baru<>();
File[] filesInCurrentDir = File baru(".").listFiles();
untuk(Berkas berkas : filesInCurrentDir) {
File[] filesInSubDir = file.listFiles();
jika(fileInSubDir != null) {
files.addAll(Arrays.asList(filesInSubDir));
} kalau tidak {
file.tambahkan(file);
}
}
System.out.println("Hitungan: " + file.ukuran())
}
Pertama-tama kita mendapatkan daftar file di direktori saat ini dan kemudian melintasinya. Untuk setiap file, jika memiliki sub-file, tambahkan sub-file tersebut ke dalam daftar. Tidak ada masalah dengan ini, tetapi ada beberapa masalah umum: mutabilitas, paranoia tipe dasar, imperatif, verbositas kode, dll. Sebuah metode kecil bernama flatMap() dapat memecahkan masalah ini.
Seperti namanya, metode ini menjadi rata setelah dipetakan. Ini memetakan elemen dalam koleksi seperti peta(). Namun berbeda dengan metode map(), ekspresi lambda dalam metode map() hanya mengembalikan sebuah elemen, dan yang dikembalikan di sini adalah objek Stream. Jadi metode ini meratakan beberapa aliran dan memetakan setiap elemen di dalamnya menjadi aliran yang rata.
Kita dapat menggunakan flatMap() untuk melakukan berbagai operasi, namun masalah yang ada menggambarkan nilainya. Setiap subdirektori memiliki daftar atau aliran file, dan kami ingin mendapatkan daftar file di semua subdirektori di bawah direktori saat ini.
Beberapa direktori mungkin kosong atau tidak memiliki elemen turunan. Dalam hal ini, kami menggabungkan direktori atau file kosong ke dalam objek aliran. Jika kita ingin mengabaikan file, metode flatMap() di JDK juga dapat menangani file kosong dengan sangat baik; metode ini akan menggabungkan referensi null ke dalam aliran sebagai koleksi kosong; Mari kita lihat penggunaan metode flatMap().
Copy kode kodenya sebagai berikut:
public static void cara yang lebih baik() {
Daftar<File> file =
Stream.of(File baru(".").listFiles())
.flatMap(file -> file.listFiles() == null ?
Aliran.dari(file): Aliran.dari(file.listFiles()))
.collect(toList());
System.out.println("Hitungan: " + ukuranfile());
}
Pertama-tama kita mendapatkan aliran sub-file dari direktori saat ini, dan kemudian memanggil metode flatMap()-nya. Kemudian berikan ekspresi lambda ke metode ini, yang akan mengembalikan aliran subfile dari file yang ditentukan. Metode flatMap() mengembalikan kumpulan file di semua subdirektori dari direktori saat ini. Kami menggunakan metode collector() dan metode toList()( di Collectors untuk mengumpulkannya ke dalam daftar.
Ekspresi lambda yang kita teruskan ke flatMap() mengembalikan subfile dari sebuah file. Jika tidak, aliran file dikembalikan. Metode flatMap() secara elegan memetakan aliran ini ke dalam kumpulan aliran, lalu meratakan koleksi tersebut dan akhirnya menggabungkannya menjadi satu aliran.
Metode flatMap() mengurangi banyak pekerjaan pengembangan - metode ini menggabungkan dua operasi berturut-turut, sering disebut tupel - dalam satu operasi elegan.
Kita sudah mengetahui cara menggunakan metode flatMap() untuk membuat daftar semua file dalam subdirektori langsung. Mari kita pantau operasi modifikasi file.
Pantau modifikasi file
Kita sudah mengetahui cara menemukan file dan direktori, tetapi jika kita ingin menerima pesan cepat saat file dibuat, diubah, atau dihapus, ini juga sangat sederhana. Mekanisme seperti ini sangat berguna untuk memantau perubahan pada file khusus seperti file konfigurasi dan sumber daya sistem. Mari kita jelajahi alat yang diperkenalkan di Java 7, WatchService, yang dapat digunakan untuk memantau modifikasi file. Banyak fitur yang kita lihat di bawah berasal dari JDK 7, namun peningkatan terbesar di sini adalah kenyamanan yang dibawa oleh iterator internal.
Mari kita tuliskan contoh pemantauan modifikasi file di direktori saat ini. Kelas Path di JDK berhubungan dengan sebuah instance di sistem file, yang merupakan pabrik untuk layanan pengamat. Kita dapat mendaftarkan peristiwa notifikasi untuk layanan ini, seperti ini:
Copy kode kodenya sebagai berikut:
jalur akhir jalur = Jalur.get(".");
Layanan Jam Tangan terakhir jamLayanan =
jalur.getFileSystem()
.newWatchService();
path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
System.out.println("Laporkan perubahan file apa pun dalam 1 menit berikutnya...");
Kami mendaftarkan WatchService untuk mengamati modifikasi pada direktori saat ini. Anda dapat melakukan polling WatchService ini untuk mendapatkan operasi modifikasi file di direktori, dan ini akan mengembalikan perubahan ini kepada kami melalui WatchKey. Setelah kita mendapatkan kuncinya, kita dapat mengulang semua kejadiannya untuk mendapatkan detail pembaruan file. Karena beberapa file dapat diubah pada saat yang sama, operasi polling dapat menghasilkan beberapa kejadian. Mari kita lihat kode polling dan traversal.
Copy kode kodenya sebagai berikut:
WatchKey final watchKey = watchService.poll(1, TimeUnit.MINUTES);
jika(watchKey != null) {
tontonKey.pollEvents()
.sungai kecil()
.forEach(acara ->
Sistem.keluar.println(acara.konteks()));
}
Seperti yang Anda lihat di sini, fitur Java 7 dan Java 8 muncul secara bersamaan. Kami mengonversi koleksi yang dikembalikan oleh pollEvents() menjadi Java 8 Stream, lalu menggunakan iterator internalnya untuk mencetak informasi pembaruan mendetail untuk setiap file.
Mari kita jalankan kode ini, lalu ubah file sample.txt di direktori saat ini untuk melihat apakah program dapat mendeteksi pembaruan ini.
Copy kode kodenya sebagai berikut:
Laporkan file apa pun yang diubah dalam 1 menit berikutnya...
sampel.txt
Ketika kita memodifikasi file ini, program akan meminta bahwa file tersebut telah dimodifikasi. Kita dapat menggunakan fitur ini untuk memantau pembaruan pada file yang berbeda dan kemudian melakukan tugas terkait. Tentu saja, kami juga hanya dapat mendaftarkan operasi pembuatan atau penghapusan file.
Meringkaskan
Dengan ekspresi lambda dan referensi metode, tugas umum seperti manipulasi string dan file, serta membuat pembanding khusus menjadi lebih mudah dan ringkas. Kelas batin anonim menjadi elegan, dan variabilitas menghilang seperti kabut pagi setelah matahari terbit. Keuntungan lain dari coding dengan gaya baru ini adalah Anda dapat menggunakan fasilitas baru JDK untuk menjelajahi direktori besar secara efisien.
Sekarang Anda tahu cara membuat ekspresi lambda dan meneruskannya ke suatu metode. Pada bab berikutnya, kami akan memperkenalkan cara menggunakan antarmuka fungsional dan ekspresi lambda untuk merancang perangkat lunak.