การแปลงรายการ
การแปลงคอลเลกชั่นให้เป็นคอลเลกชั่นใหม่นั้นง่ายดายเพียงแค่ทำซ้ำๆ สมมติว่าเราต้องการแปลงชื่อในรายการให้เป็นตัวพิมพ์ใหญ่ทั้งหมด มาดูวิธีการนำไปใช้บ้าง
สตริงใน Java นั้นไม่เปลี่ยนรูป ดังนั้นจึงไม่สามารถเปลี่ยนแปลงได้ เราสามารถสร้างสตริงใหม่เพื่อแทนที่องค์ประกอบดั้งเดิมในรายการได้ อย่างไรก็ตาม หากคุณทำเช่นนี้ รายการดั้งเดิมจะหายไป มีปัญหาอื่นเช่นกัน รายการดั้งเดิมอาจไม่เปลี่ยนรูป เช่น สร้างโดย Arrays.asList() ดังนั้นการแก้ไขรายการดั้งเดิมจะไม่ทำงาน ข้อเสียอีกประการหนึ่งคือการทำงานแบบขนานทำได้ยาก
การสร้างรายการตัวพิมพ์ใหญ่ทั้งหมดใหม่ถือเป็นตัวเลือกที่ดี
เมื่อดูเผินๆ อาจดูเหมือนคำแนะนำที่อ่อนแอ แต่ประสิทธิภาพเป็นปัญหาที่เราทุกคนสนใจ น่าประหลาดใจที่การเขียนโปรแกรมเชิงฟังก์ชันมักจะมีประสิทธิภาพมากกว่าการเขียนโปรแกรมเชิงความจำเป็น ดังที่เราอภิปรายในปัญหาด้านประสิทธิภาพ ในหน้า 153
เริ่มต้นด้วยการใช้ชุดนี้เพื่อสร้างชุดตัวพิมพ์ใหญ่ใหม่
คัดลอกรหัสรหัสดังต่อไปนี้:
รายการสุดท้าย <String> ตัวพิมพ์ใหญ่ = new ArrayList <String> ();
สำหรับ (ชื่อสตริง : เพื่อน) {
ตัวพิมพ์ใหญ่Names.add(name.toUpperCase());
-
ในโค้ดที่จำเป็น ขั้นแรกเราจะสร้างรายการว่าง จากนั้นกรอกชื่อตัวพิมพ์ใหญ่ โดยแทรกทีละรายการในขณะที่ข้ามรายการเดิม เพื่อปรับปรุงให้เป็นเวอร์ชันที่ใช้งานได้ ขั้นตอนแรกของเราคือพิจารณาแทนที่ for loop ด้วยตัววนซ้ำภายใน forEach ที่กล่าวถึงในการข้ามผ่านรายการในหน้า 19 ดังที่แสดงในตัวอย่างต่อไปนี้
คัดลอกรหัสรหัสดังต่อไปนี้:
รายการสุดท้าย <String> ตัวพิมพ์ใหญ่ = new ArrayList <String> ();
friends.forEach(ชื่อ -> ตัวพิมพ์ใหญ่Names.add(name.toUpperCase()));
System.out.println (ชื่อตัวพิมพ์ใหญ่);
เราใช้ตัววนซ้ำภายใน แต่เราต้องสร้างรายการใหม่และแทรกองค์ประกอบเข้าไปด้วย เราสามารถปรับปรุงเพิ่มเติมได้
การใช้นิพจน์แลมบ์ดา
มีวิธีการแมปในอินเทอร์เฟซ Stream ที่เพิ่งเปิดตัว ซึ่งสามารถช่วยให้เราหลีกเลี่ยงความแปรปรวนและทำให้โค้ดดูกระชับยิ่งขึ้น Steam เป็นเหมือนตัววนซ้ำคอลเลกชัน แต่ก็มีฟังก์ชันที่คล่องแคล่วเช่นกัน เมื่อใช้วิธีการของอินเทอร์เฟซนี้ เราสามารถรวมชุดการเรียกเพื่อให้โค้ดอ่านตามลำดับที่อธิบายปัญหา ทำให้สามารถอ่านได้ง่ายขึ้น
วิธีการแมปของ Steam สามารถใช้ในการแปลงลำดับอินพุตให้เป็นลำดับเอาต์พุตได้ ซึ่งเหมาะอย่างยิ่งกับสิ่งที่เราต้องการทำ
คัดลอกรหัสรหัสดังต่อไปนี้:
เพื่อน.สตรีม()
.map(ชื่อ -> name.toUpperCase())
.forEach(ชื่อ -> System.out.print(ชื่อ + " "));
System.out.println();
คอลเลกชันทั้งหมดใน JDK8 รองรับวิธีการสตรีมนี้ ซึ่งสรุปคอลเลกชันไว้ในอินสแตนซ์ Steam วิธีการ map เรียกนิพจน์แลมบ์ดาที่ระบุหรือบล็อคโค้ดสำหรับแต่ละองค์ประกอบในสตรีม วิธีการ map นั้นแตกต่างจากวิธี forEach มาก forEach เพียงเรียกใช้ฟังก์ชันที่ระบุในองค์ประกอบในคอลเลกชัน เมธอด map จะรวบรวมผลลัพธ์การทำงานของนิพจน์แลมบ์ดาและส่งกลับชุดผลลัพธ์ ในที่สุดเราก็พิมพ์องค์ประกอบทั้งหมดโดยใช้วิธี forEach
ชื่อในคอลเลกชันใหม่เป็นตัวพิมพ์ใหญ่ทั้งหมด:
คัดลอกรหัสรหัสดังต่อไปนี้:
ไบรอัน เนท นีล ราจู ซารา สก็อตต์
วิธีการแมปมีความเหมาะสมมากสำหรับการแปลงคอลเลกชั่นอินพุตให้เป็นคอลเลกชั่นเอาท์พุตใหม่ วิธีการนี้ช่วยให้แน่ใจว่าลำดับอินพุตและเอาต์พุตมีจำนวนองค์ประกอบเท่ากัน อย่างไรก็ตาม องค์ประกอบอินพุตและเอาต์พุตอาจมีประเภทต่างกันได้ ในตัวอย่างนี้ อินพุตและเอาต์พุตของเราเป็นทั้งคอลเลกชันของสตริง เราสามารถส่งโค้ดบางส่วนไปยังเมธอด map เพื่อให้ส่งคืน เช่น จำนวนอักขระที่มีอยู่ในชื่อ ในกรณีนี้ อินพุตยังคงเป็นลำดับของสตริง แต่เอาต์พุตจะเป็นลำดับตัวเลข ดังต่อไปนี้
คัดลอกรหัสรหัสดังต่อไปนี้:
เพื่อน.สตรีม()
.map(ชื่อ -> name.length())
.forEach(นับ -> System.out.print(นับ + " "));
ผลลัพธ์คือจำนวนตัวอักษรในแต่ละชื่อ:
คัดลอกรหัสรหัสดังต่อไปนี้:
5 4 4 4 4 5
นิพจน์แลมบ์ดาเวอร์ชันใหม่กว่าถูกใช้เพื่อหลีกเลี่ยงการดำเนินการแก้ไขที่ชัดเจน โค้ดดังกล่าวมีความกระชับมาก การเขียนในลักษณะนี้ไม่จำเป็นต้องเริ่มต้นคอลเลกชันว่างและตัวแปรขยะอีกต่อไป ตัวแปรนี้ถูกซ่อนอยู่ในการใช้งานพื้นฐาน
อ้างอิงวิธีการใช้งาน
นอกจากนี้เรายังสามารถใช้การอ้างอิงวิธีการเพื่อทำให้กระชับยิ่งขึ้นอีกเล็กน้อย ในกรณีที่จำเป็นต้องส่งผ่านการใช้งานอินเทอร์เฟซการทำงาน คอมไพลเลอร์ Java สามารถยอมรับนิพจน์แลมบ์ดาหรือการอ้างอิงเมธอด ด้วยคุณสมบัตินี้ คุณสามารถแทนที่ name -> name.toUpperCase() ด้วย String::toUpperCase ได้ดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
เพื่อน.สตรีม()
.map(String::toUpperCase)
.forEach(ชื่อ -> System.out.println(ชื่อ));
เมื่อพารามิเตอร์ถูกส่งผ่านไปยังวิธีการที่สร้างขึ้น - การใช้งานวิธีนามธรรมของอินเทอร์เฟซการทำงาน - Java จะเรียกวิธี toUpperCase ของพารามิเตอร์ String การอ้างอิงพารามิเตอร์นี้ถูกซ่อนอยู่ที่นี่ ในสถานการณ์ง่ายๆ ดังตัวอย่างข้างต้น เราสามารถใช้การอ้างอิงเมธอดเพื่อแทนที่นิพจน์แลมบ์ดาได้ สำหรับข้อมูลเพิ่มเติม ดูว่าเมื่อใดที่ควรใช้การอ้างอิงเมธอดในหน้า 26
คัดลอกรหัสรหัสดังต่อไปนี้:
เพื่อนคนหนึ่งถามว่า:
เมื่อใดที่คุณควรใช้การอ้างอิงวิธีการ?
เมื่อเขียนโปรแกรมใน Java เรามักจะใช้นิพจน์แลมบ์ดามากกว่าการอ้างอิงวิธีการ แต่ไม่ได้หมายความว่าการอ้างอิงวิธีการนั้นไม่สำคัญหรือไร้ประโยชน์ เมื่อนิพจน์แลมบ์ดาสั้นมาก นิพจน์เหล่านี้เป็นทางเลือกที่ดีในการเรียกเมธอดอินสแตนซ์หรือเมธอดสแตติกโดยตรง กล่าวอีกนัยหนึ่ง หากนิพจน์แลมบ์ดาส่งผ่านพารามิเตอร์ไปยังการเรียกเมธอดเท่านั้น เราควรใช้การอ้างอิงเมธอดแทน
การแสดงออกของแลมบ์ดาเช่นนี้คล้ายกับที่ Tom Smykowski พูดในภาพยนตร์เรื่อง "Working with a Bug" เล็กน้อย หน้าที่ของมันคือ "นำข้อกำหนดจากลูกค้าไปยังวิศวกรซอฟต์แวร์" ด้วยเหตุนี้ ฉันจึงเรียกรูปแบบวิธีการปรับโครงสร้างใหม่นี้ว่าอ้างอิงรูปแบบเวิร์ม
นอกจากจะกระชับแล้ว การใช้การอ้างอิงเมธอดยังสามารถสะท้อนความหมายและหน้าที่ของชื่อเมธอดได้ดียิ่งขึ้นอีกด้วย
เบื้องหลังการใช้การอ้างอิงเมธอด คอมไพเลอร์มีบทบาทสำคัญ วัตถุเป้าหมายและพารามิเตอร์ที่อ้างอิงโดยวิธีการนั้นจะได้มาจากพารามิเตอร์ที่ส่งผ่านในวิธีการที่สร้างขึ้น ซึ่งจะทำให้คุณสามารถใช้การอ้างอิงเมธอดเพื่อเขียนโค้ดที่กระชับมากกว่าการใช้นิพจน์แลมบ์ดา อย่างไรก็ตาม หากต้องแก้ไขพารามิเตอร์ก่อนที่จะส่งผ่านไปยังเมธอดหรือผลลัพธ์การเรียกถูกส่งคืน เราไม่สามารถใช้วิธีการเขียนที่สะดวกนี้ได้
ในตัวอย่างก่อนหน้านี้ การอ้างอิงวิธีการอ้างอิงถึงวิธีการอินสแตนซ์ การอ้างอิงวิธีการยังสามารถอ้างถึงวิธีการคงที่และวิธีการที่ยอมรับพารามิเตอร์ เราจะเห็นตัวอย่างนี้ในภายหลัง
นิพจน์ Lambda สามารถช่วยให้เราสำรวจคอลเลกชันและแปลงคอลเลกชันได้ ดังที่เราจะเห็นด้านล่าง นอกจากนี้ยังช่วยให้เราเลือกองค์ประกอบจากคอลเลกชันได้อย่างรวดเร็วอีกด้วย