แสดงรายการไดเรกทอรีย่อยโดยใช้ flatMap
เราได้เห็นมาก่อนว่าจะแสดงรายการไฟล์ในไดเร็กทอรีที่ระบุได้อย่างไร มาดูวิธีสำรวจไดเรกทอรีย่อยโดยตรงของไดเรกทอรีที่ระบุ (ความลึกคือ 1) ขั้นแรกใช้เวอร์ชันธรรมดา จากนั้นใช้เมธอด flatMap() ที่สะดวกกว่าเพื่อนำไปใช้
ก่อนอื่นเราใช้ for loop แบบดั้งเดิมเพื่อสำรวจไดเร็กทอรีที่ระบุ หากมีไฟล์อยู่ในไดเร็กทอรีย่อย ให้เพิ่มไฟล์เหล่านั้นลงในรายการ มิฉะนั้น ให้เพิ่มไดเร็กทอรีย่อยลงในรายการ สุดท้าย ให้พิมพ์จำนวนไฟล์ทั้งหมดออกมา รหัสอยู่ด้านล่าง - รหัสนี้ใช้สำหรับโหมดฮาร์ด
คัดลอกรหัสรหัสดังต่อไปนี้:
โมฆะสาธารณะรายการ TheHardWay () {
รายการ <ไฟล์> ไฟล์ = ใหม่ ArrayList<>();
ไฟล์[] filesInCurrentDir = ไฟล์ใหม่(".").listFiles();
สำหรับ (ไฟล์ไฟล์ : filesInCurrentDir) {
ไฟล์[] filesInSubDir = file.listFiles();
ถ้า (filesInSubDir != null) {
files.addAll(Arrays.asList(filesInSubDir));
} อื่น {
files.add(ไฟล์);
-
-
System.out.println("จำนวน: " + files.size())
-
ก่อนอื่นเราจะได้รายชื่อไฟล์ในไดเร็กทอรีปัจจุบันแล้วจึงสำรวจดู สำหรับแต่ละไฟล์ หากมีไฟล์ย่อย ให้เพิ่มลงในรายการ ไม่มีปัญหาในเรื่องนี้ แต่มีปัญหาทั่วไปบางประการ เช่น ความไม่แน่นอน ความหวาดระแวงแบบพื้นฐาน ความจำเป็น การใช้โค้ดฟุ่มเฟือย ฯลฯ วิธีการเล็กๆ ที่เรียกว่า flatMap() สามารถแก้ปัญหาเหล่านี้ได้
ดังที่ชื่อกล่าวไว้ วิธีการนี้จะแบนลงหลังจากการแมป มันแมปองค์ประกอบในคอลเลกชันเช่นเดียวกับ map() แต่แตกต่างจากเมธอด map() ตรงที่นิพจน์แลมบ์ดาในเมธอด map() ส่งคืนองค์ประกอบเท่านั้น และสิ่งที่ส่งคืนที่นี่คืออ็อบเจ็กต์ Stream ดังนั้นวิธีนี้จะทำให้สตรีมหลาย ๆ แบนและแมปแต่ละองค์ประกอบภายในกับสตรีมที่แบน
เราสามารถใช้ flatMap() เพื่อดำเนินการต่างๆ ได้ แต่ปัญหาที่เกิดขึ้นแสดงให้เห็นถึงคุณค่าของมัน แต่ละไดเร็กทอรีย่อยมีรายการหรือสตรีมของไฟล์ และเราต้องการรับรายการไฟล์ในไดเร็กทอรีย่อยทั้งหมดภายใต้ไดเร็กทอรีปัจจุบัน
บางไดเร็กทอรีอาจว่างเปล่าหรือไม่มีองค์ประกอบย่อย ในกรณีนี้ เราจะรวมไดเร็กทอรีหรือไฟล์ว่างไว้ในออบเจ็กต์สตรีม หากเราต้องการละเว้นไฟล์ เมธอด flatMap() ใน JDK ก็สามารถจัดการไฟล์ว่างได้เป็นอย่างดี มันจะรวมการอ้างอิง null เข้ากับสตรีมเป็นคอลเลกชั่นว่าง มาดูการใช้เมธอด flatMap() กัน
คัดลอกรหัสรหัสดังต่อไปนี้:
โมฆะสาธารณะคงที่ดีกว่า Way () {
รายการ <ไฟล์> ไฟล์ =
Stream.of(ไฟล์ใหม่(".").listFiles())
.flatMap(ไฟล์ -> file.listFiles() == null ?
Stream.of(ไฟล์) : Stream.of(file.listFiles()))
.collect(toList());
System.out.println("นับ: " + files.size());
-
ก่อนอื่นเราได้รับสตรีมไฟล์ย่อยของไดเร็กทอรีปัจจุบัน จากนั้นจึงเรียกใช้เมธอด flatMap() จากนั้นส่งนิพจน์แลมบ์ดาไปยังวิธีนี้ ซึ่งจะส่งคืนสตรีมของไฟล์ย่อยของไฟล์ที่ระบุ flatMap() วิธีการส่งคืนชุดของไฟล์ในไดเร็กทอรีย่อยทั้งหมดของไดเร็กทอรีปัจจุบัน เราใช้เมธอด collect() และเมธอด toList()( ใน Collectors เพื่อรวบรวมไว้ในรายการ
นิพจน์แลมบ์ดาที่เราส่งไปยัง flatMap() ส่งคืนไฟล์ย่อยของไฟล์ ถ้าไม่เช่นนั้น สตรีมของไฟล์จะถูกส่งกลับ เมธอด flatMap() จะจับคู่สตรีมนี้เข้ากับคอลเลกชันของสตรีมอย่างสวยงาม จากนั้นจึงทำให้คอลเลกชันเรียบและรวมเป็นสตรีมเดียวในที่สุด
เมธอด flatMap() ช่วยลดงานการพัฒนาได้มาก โดยเป็นการรวมการดำเนินการสองครั้งติดต่อกัน ซึ่งมักเรียกว่า tuples ไว้ในการดำเนินการที่สวยงามเพียงครั้งเดียว
เรารู้วิธีใช้เมธอด flatMap() เพื่อแสดงรายการไฟล์ทั้งหมดในไดเร็กทอรีย่อยทันที มาติดตามการดำเนินการแก้ไขไฟล์กัน
ติดตามการแก้ไขไฟล์
เรารู้วิธีค้นหาไฟล์และไดเร็กทอรีอยู่แล้ว แต่หากเราต้องการได้รับข้อความแจ้งเตือนเมื่อมีการสร้าง แก้ไข หรือลบไฟล์ ก็ง่ายมากเช่นกัน กลไกดังกล่าวมีประโยชน์มากสำหรับการตรวจสอบการเปลี่ยนแปลงในไฟล์พิเศษ เช่น ไฟล์การกำหนดค่าและทรัพยากรระบบ มาสำรวจเครื่องมือนี้ที่นำมาใช้ใน Java 7, WatchService ซึ่งสามารถใช้เพื่อตรวจสอบการแก้ไขไฟล์ คุณสมบัติหลายอย่างที่เราเห็นด้านล่างมาจาก JDK 7 แต่การปรับปรุงที่ใหญ่ที่สุดที่นี่คือความสะดวกสบายที่มาจากตัววนซ้ำภายใน
ขั้นแรกเรามาเขียนตัวอย่างการตรวจสอบการแก้ไขไฟล์ในไดเร็กทอรีปัจจุบัน คลาส Path ใน JDK สอดคล้องกับอินสแตนซ์ในระบบไฟล์ ซึ่งเป็นโรงงานสำหรับบริการผู้สังเกตการณ์ เราสามารถลงทะเบียนกิจกรรมการแจ้งเตือนสำหรับบริการนี้ได้ เช่นนี้
คัดลอกรหัสรหัสดังต่อไปนี้:
เส้นทาง inal path = Paths.get(".");
WatchService สุดท้าย watchService =
เส้นทาง.getFileSystem()
.newWatchService();
path.register (บริการนาฬิกา, StandardWatchEventKinds.ENTRY_MODIFY);
System.out.println("รายงานไฟล์ที่มีการเปลี่ยนแปลงภายใน 1 นาทีถัดไป...");
เราลงทะเบียน WatchService เพื่อสังเกตการแก้ไขไดเร็กทอรีปัจจุบัน คุณสามารถสำรวจ WatchService นี้เพื่อรับการดำเนินการแก้ไขไฟล์ในไดเร็กทอรี และจะส่งคืนการเปลี่ยนแปลงเหล่านี้ให้เราผ่านทาง WatchKey เมื่อเรามีรหัสแล้ว เราก็สามารถวนซ้ำเหตุการณ์ทั้งหมดเพื่อรับรายละเอียดของการอัปเดตไฟล์ได้ เนื่องจากอาจมีการแก้ไขไฟล์หลายไฟล์พร้อมกัน การดำเนินการโพลจึงอาจส่งคืนหลายเหตุการณ์ มาดูรหัสการโพลและการสำรวจเส้นทางกัน
คัดลอกรหัสรหัสดังต่อไปนี้:
WatchKey สุดท้าย watchKey = watchService.poll (1, TimeUnit.MINUTES);
ถ้า (watchKey ! = null) {
watchKey.pollกิจกรรม()
.ลำธาร()
.forEach(เหตุการณ์ ->
System.out.println(event.context()));
-
ดังที่คุณเห็นที่นี่ คุณสมบัติของ Java 7 และ Java 8 ปรากฏพร้อมกัน เราแปลงคอลเลกชันที่ส่งคืนโดย pollEvents() ไปเป็นสตรีม Java 8 จากนั้นใช้ตัววนซ้ำภายในเพื่อพิมพ์ข้อมูลการอัพเดตโดยละเอียดสำหรับแต่ละไฟล์
มาเรียกใช้โค้ดนี้ จากนั้นแก้ไขไฟล์ example.txt ในไดเร็กทอรีปัจจุบันเพื่อดูว่าโปรแกรมสามารถตรวจพบการอัปเดตนี้ได้หรือไม่
คัดลอกรหัสรหัสดังต่อไปนี้:
แจ้งไฟล์ที่มีการเปลี่ยนแปลงภายใน 1 นาที...
ตัวอย่าง.txt
เมื่อเราแก้ไขไฟล์นี้ โปรแกรมจะแจ้งว่าไฟล์ถูกแก้ไข เราสามารถใช้คุณสมบัตินี้เพื่อตรวจสอบการอัปเดตไฟล์ต่าง ๆ จากนั้นทำงานที่เกี่ยวข้อง แน่นอนว่าเราสามารถลงทะเบียนได้เฉพาะการดำเนินการสร้างหรือลบไฟล์เท่านั้น
สรุป
ด้วยนิพจน์แลมบ์ดาและการอ้างอิงเมธอด งานทั่วไป เช่น การจัดการสตริงและไฟล์ และการสร้างตัวเปรียบเทียบแบบกำหนดเองจะง่ายและกระชับยิ่งขึ้น ชนชั้นภายในที่ไม่เปิดเผยตัวตนกลายเป็นความสง่างาม และความแปรปรวนหายไปเหมือนหมอกยามเช้าหลังพระอาทิตย์ขึ้น ข้อดีอีกประการหนึ่งของการเขียนโค้ดในรูปแบบใหม่นี้คือ คุณสามารถใช้เครื่องมือใหม่ของ JDK เพื่อสำรวจไดเร็กทอรีขนาดใหญ่ได้อย่างมีประสิทธิภาพ
ตอนนี้คุณรู้วิธีสร้างนิพจน์แลมบ์ดาและส่งต่อไปยังเมธอดแล้ว ในบทถัดไป เราจะแนะนำวิธีใช้อินเทอร์เฟซการทำงานและนิพจน์แลมบ์ดาในการออกแบบซอฟต์แวร์