ใช้อินเทอร์เฟซตัวเปรียบเทียบ
อินเทอร์เฟซตัวเปรียบเทียบสามารถเห็นได้ทุกที่ในไลบรารี JDK ตั้งแต่การค้นหา การเรียงลำดับ การดำเนินการย้อนกลับ และอื่นๆ ใน Java 8 มันจะกลายเป็นอินเทอร์เฟซที่ใช้งานได้ ข้อดีของสิ่งนี้คือเราสามารถใช้ไวยากรณ์การสตรีมเพื่อใช้งานตัวเปรียบเทียบ
ลองใช้ Comparator หลายวิธีเพื่อดูค่าของไวยากรณ์ใหม่ นิ้วของคุณจะขอบคุณ การไม่ต้องใช้คลาสภายในที่ไม่เปิดเผยตัวตนช่วยให้คุณประหยัดเวลาในการกดแป้นพิมพ์ได้มาก
การเรียงลำดับโดยใช้ตัวเปรียบเทียบ
ตัวอย่างต่อไปนี้จะใช้วิธีการเปรียบเทียบที่แตกต่างกันเพื่อจัดเรียงกลุ่มบุคคล เรามาสร้าง Person JavaBean กันก่อน
คัดลอกรหัสรหัสดังต่อไปนี้:
บุคคลในชั้นเรียนสาธารณะ {
ชื่อสตริงสุดท้ายส่วนตัว
อายุ int ส่วนตัวสุดท้าย
บุคคลสาธารณะ (theName สตริงสุดท้าย, int theAge สุดท้าย) {
ชื่อ = ชื่อ;
อายุ = อายุ;
-
สตริงสาธารณะ getName() { ชื่อที่ส่งคืน;
สาธารณะ int getAge() { อายุคืน;
public int ageDifference (บุคคลสุดท้าย อื่น ๆ) {
อายุที่กลับมา - อื่น ๆ อายุ;
-
สตริงสาธารณะ toString() {
return String.format("%s - %d", ชื่อ, อายุ);
-
-
เราสามารถใช้อินเทอร์เฟซ Comparator ผ่านคลาส Person ได้ แต่ด้วยวิธีนี้ เราสามารถใช้วิธีเปรียบเทียบได้เพียงวิธีเดียวเท่านั้น เราต้องการเปรียบเทียบคุณลักษณะต่างๆ เช่น ชื่อ อายุ หรือทั้งสองอย่างรวมกัน เพื่อดำเนินการเปรียบเทียบได้อย่างยืดหยุ่น เราสามารถใช้ Comparator เพื่อสร้างโค้ดที่เกี่ยวข้องเมื่อเราต้องการเปรียบเทียบ
ขั้นแรกเรามาสร้างรายชื่อบุคคล โดยแต่ละรายการมีชื่อและอายุที่แตกต่างกัน
คัดลอกรหัสรหัสดังต่อไปนี้:
รายการสุดท้าย <บุคคล> คน = Arrays.asList(
คนใหม่("จอห์น", 20),
คนใหม่("ซาร่า", 21),
คนใหม่("เจน", 21),
บุคคลใหม่ ("เกร็ก", 35));
เราสามารถจัดเรียงผู้คนจากน้อยไปหามากหรือจากมากไปน้อยตามชื่อหรืออายุของพวกเขา วิธีการทั่วไปคือการใช้คลาสภายในที่ไม่ระบุชื่อเพื่อใช้อินเทอร์เฟซตัวเปรียบเทียบ หากเขียนในลักษณะนี้ เฉพาะโค้ดที่เกี่ยวข้องมากกว่าเท่านั้นที่จะมีความหมาย และส่วนที่เหลือเป็นเพียงพิธีการเท่านั้น การใช้นิพจน์แลมบ์ดาสามารถเน้นไปที่แก่นแท้ของการเปรียบเทียบ
ขั้นแรกให้เรียงลำดับตามอายุจากอายุน้อยที่สุดไปหาอายุมากที่สุด
ตอนนี้เรามีออบเจ็กต์ List แล้ว เราสามารถใช้เมธอด sort() เพื่อเรียงลำดับได้ อย่างไรก็ตามวิธีนี้ก็มีปัญหาเช่นกัน นี่เป็นเมธอด void ซึ่งหมายความว่าเมื่อเราเรียกเมธอดนี้ รายการจะเปลี่ยนไป หากต้องการคงรายการเดิมไว้ เราต้องคัดลอกก่อนแล้วจึงเรียกใช้เมธอด sort() มันเป็นเพียงความพยายามมากเกินไป ในเวลานี้เราต้องหันไปขอความช่วยเหลือจากคลาส Stream
เราสามารถรับวัตถุ Stream จากรายการแล้วเรียกวิธีการ sorted() มันจะส่งคืนคอลเลกชันที่เรียงลำดับแทนที่จะแก้ไขคอลเลกชันดั้งเดิม เมื่อใช้วิธีการนี้ คุณสามารถกำหนดค่าพารามิเตอร์ของ Comparator ได้อย่างง่ายดาย
คัดลอกรหัสรหัสดังต่อไปนี้:
รายการ<บุคคล>จากน้อยไปหามาก=
คน.สตรีม()
.sorted((person1, person2) -> person1.ageDifference(person2))
.collect(toList());
printPeople("เรียงลำดับจากน้อยไปมากตามอายุ: ", จากน้อยไปมาก);
ก่อนอื่นเราจะแปลงรายการให้เป็นวัตถุ Stream ผ่าน stream() วิธีการ จากนั้นเรียกวิธีการ sorted() วิธีการนี้ยอมรับพารามิเตอร์ตัวเปรียบเทียบ เนื่องจาก Comparator เป็นอินเทอร์เฟซที่ใช้งานได้ เราจึงสามารถส่งผ่านนิพจน์แลมบ์ดาได้ ในที่สุดเราก็เรียกวิธีการรวบรวมและให้มันเก็บผลลัพธ์ไว้ในรายการ วิธีการรวบรวมคือตัวลดที่สามารถส่งออกอ็อบเจ็กต์ระหว่างกระบวนการวนซ้ำเป็นรูปแบบหรือประเภทเฉพาะ วิธีการ toList() เป็นวิธีการคงที่ของคลาส Collectors
วิธีการนามธรรม comparisonTo() ของ Comparator ได้รับพารามิเตอร์สองตัว ซึ่งเป็นอ็อบเจ็กต์ที่จะเปรียบเทียบ และส่งกลับผลลัพธ์เป็นประเภท int เพื่อให้เข้ากันได้กับสิ่งนี้ นิพจน์แลมบ์ดาของเรายังได้รับพารามิเตอร์สองตัว ซึ่งเป็นอ็อบเจ็กต์บุคคลสองตัว ซึ่งคอมไพลเลอร์จะอนุมานประเภทโดยอัตโนมัติ เราส่งคืนประเภท int เพื่อระบุว่าวัตถุที่เปรียบเทียบมีค่าเท่ากันหรือไม่
เนื่องจากเราต้องการเรียงลำดับตามอายุ เราจะเปรียบเทียบอายุของวัตถุทั้งสอง แล้วส่งกลับผลลัพธ์ของการเปรียบเทียบ หากมีขนาดเท่ากัน ให้คืนค่า 0 มิฉะนั้น ระบบจะส่งกลับจำนวนลบหากคนแรกอายุน้อยกว่า และจะส่งกลับจำนวนบวกหากคนแรกมีอายุมากกว่า
sorted() วิธีการจะสำรวจแต่ละองค์ประกอบของคอลเลกชันเป้าหมายและเรียกตัวเปรียบเทียบที่ระบุเพื่อกำหนดลำดับการจัดเรียงขององค์ประกอบ วิธีการดำเนินการของวิธีการ sorted() ค่อนข้างคล้ายกับวิธีการลด () ที่กล่าวถึงก่อนหน้านี้ วิธีลด () จะค่อยๆ ลดรายการลงเป็นผลลัพธ์ sorted() วิธีการเรียงลำดับตามผลการเปรียบเทียบ
เมื่อเราเรียงลำดับแล้ว เราต้องการพิมพ์ผลลัพธ์ ดังนั้นเราจึงเรียกเมธอด printPeople() มาใช้วิธีนี้กัน
คัดลอกรหัสรหัสดังต่อไปนี้:
โมฆะคงที่สาธารณะ printPeople(
ข้อความสตริงสุดท้าย รายการสุดท้าย<บุคคล> คน) {
System.out.println (ข้อความ);
people.forEach(System.out::println);
-
ในวิธีนี้ ขั้นแรกเราจะพิมพ์ข้อความ จากนั้นสำรวจรายการและพิมพ์แต่ละองค์ประกอบในนั้น
ลองใช้เมธอด sorted() เพื่อดูว่ามันจะเรียงลำดับบุคคลในรายการจากอายุน้อยที่สุดไปเก่าที่สุดได้อย่างไร
คัดลอกรหัสรหัสดังต่อไปนี้:
เรียงลำดับจากน้อยไปหามากตามอายุ:
จอห์น - 20
ซาร่า - 21
เจน - 21
เกร็ก - 35
ลองมาดูวิธีการ sorted() อีกครั้งเพื่อทำการปรับปรุง
คัดลอกรหัสรหัสดังต่อไปนี้:
.sorted((person1, person2) -> person1.ageDifference(person2))
ในนิพจน์แลมบ์ดาที่ส่งเข้ามา เราเพียงกำหนดเส้นทางพารามิเตอร์ทั้งสองนี้ - พารามิเตอร์แรกจะถูกใช้เป็นเป้าหมายการโทรของเมธอด ageDifference() และพารามิเตอร์ที่สองจะถูกใช้เป็นพารามิเตอร์ แต่เราไม่สามารถเขียนแบบนี้ได้ แต่ใช้โหมดพื้นที่สำนักงาน นั่นคือ ใช้การอ้างอิงเมธอด และปล่อยให้คอมไพเลอร์ Java กำหนดเส้นทาง
การกำหนดเส้นทางพารามิเตอร์ที่ใช้ที่นี่แตกต่างจากที่เราเห็นก่อนหน้านี้เล็กน้อย เราเห็นก่อนหน้านี้ว่าอาร์กิวเมนต์ถูกส่งผ่านเป็นเป้าหมายการโทรหรือเป็นพารามิเตอร์การโทร ตอนนี้ เรามีพารามิเตอร์สองตัว และเราต้องการแยกออกเป็นสองส่วน ส่วนหนึ่งเป็นเป้าหมายของการเรียกเมธอด และที่สองเป็นพารามิเตอร์ ไม่ต้องกังวล คอมไพเลอร์ Java จะบอกคุณว่า "ฉันจะจัดการเรื่องนี้เอง"
เราสามารถแทนที่นิพจน์แลมบ์ดาในเมธอด sorted() ก่อนหน้าด้วยวิธี ageDifference ที่สั้นและกระชับได้
คัดลอกรหัสรหัสดังต่อไปนี้:
คน.สตรีม()
.sorted(บุคคล::ความแตกต่างระหว่างอายุ)
โค้ดนี้กระชับมาก ต้องขอบคุณการอ้างอิงเมธอดที่คอมไพลเลอร์ Java มอบให้ คอมไพลเลอร์ได้รับพารามิเตอร์อินสแตนซ์สำหรับบุคคลสองคน และใช้ตัวแรกเป็นเป้าหมายของเมธอด ageDifference() และตัวที่สองเป็นพารามิเตอร์เมธอด เราปล่อยให้คอมไพเลอร์ทำงานนี้แทนการเขียนโค้ดโดยตรง เมื่อใช้วิธีการนี้ เราต้องตรวจสอบให้แน่ใจว่าพารามิเตอร์แรกเป็นเป้าหมายการเรียกของวิธีที่อ้างอิง และส่วนที่เหลือเป็นพารามิเตอร์อินพุตของวิธีการ
เครื่องเปรียบเทียบการใช้ซ้ำ
ง่ายต่อการเรียงลำดับบุคคลในรายการจากอายุน้อยที่สุดไปหาอายุมากที่สุด และยังง่ายต่อการเรียงลำดับจากอายุมากที่สุดไปหาอายุน้อยที่สุดอีกด้วย มาลองดูกัน
คัดลอกรหัสรหัสดังต่อไปนี้:
printPeople("เรียงลำดับตามอายุ: ",
คน.สตรีม()
.sorted((person1, person2) -> person2.ageDifference(person1))
.collect(toList()));
เราเรียกเมธอด sorted() และส่งผ่านนิพจน์แลมบ์ดา ซึ่งพอดีกับอินเทอร์เฟซตัวเปรียบเทียบ เช่นเดียวกับในตัวอย่างก่อนหน้านี้ ข้อแตกต่างเพียงอย่างเดียวคือการนำนิพจน์แลมบ์ดาไปใช้ - เราได้เปลี่ยนลำดับของบุคคลที่จะเปรียบเทียบ ควรจัดเรียงผลลัพธ์จากอายุมากที่สุดไปหาอายุน้อยที่สุด มาดูกันดีกว่า
คัดลอกรหัสรหัสดังต่อไปนี้:
เรียงลำดับตามอายุจากมากไปน้อย:
เกร็ก - 35
ซาร่า - 21
เจน - 21
จอห์น - 20
การเปลี่ยนตรรกะของการเปรียบเทียบไม่ต้องใช้ความพยายามมากนัก แต่เราไม่สามารถสร้างเวอร์ชันนี้ใหม่ให้เป็นการอ้างอิงวิธีการได้ เนื่องจากลำดับของพารามิเตอร์ไม่เป็นไปตามกฎของการกำหนดเส้นทางพารามิเตอร์สำหรับการอ้างอิงวิธีการ พารามิเตอร์แรกไม่ได้ใช้เป็นเป้าหมายการเรียกของวิธีการ แต่เป็นพารามิเตอร์วิธีการ มีวิธีแก้ไขปัญหานี้ซึ่งช่วยลดความซ้ำซ้อนของความพยายามด้วย เรามาดูวิธีการทำกัน
เราได้สร้างนิพจน์แลมบ์ดาขึ้นมาสองรายการก่อนหน้านี้ รายการหนึ่งคือการจัดเรียงตามอายุจากเล็กไปใหญ่ และอีกรายการหนึ่งคือการเรียงลำดับจากใหญ่ไปเล็ก การทำเช่นนี้จะนำไปสู่ความซ้ำซ้อนของโค้ดและการทำซ้ำ และละเมิดหลักการ DRY หากเราเพียงต้องการปรับลำดับการจัดเรียง JDK จัดเตรียมวิธีการย้อนกลับซึ่งมีตัวแก้ไขวิธีการพิเศษเป็นค่าเริ่มต้น เราจะพูดถึงมันในวิธีการเริ่มต้นในหน้า 77 อันดับแรกเราใช้วิธี Reversed() เพื่อลบความซ้ำซ้อน
คัดลอกรหัสรหัสดังต่อไปนี้:
ตัวเปรียบเทียบ<บุคคล> เปรียบเทียบจากน้อยไปมาก =
(บุคคล 1, บุคคล 2) -> person1.ageDifference (บุคคล 2);
ตัวเปรียบเทียบ<บุคคล> CompareDescending = comparisonAscending.reversed();
ขั้นแรกเราสร้างเครื่องมือเปรียบเทียบ เปรียบเทียบจากน้อยไปหามาก เพื่อจัดเรียงผู้คนตามอายุจากอายุน้อยที่สุดไปหาอายุมากที่สุด เพื่อที่จะกลับลำดับการเปรียบเทียบ แทนที่จะเขียนโค้ดนี้อีกครั้ง เราเพียงต้องเรียกเมธอด Reversed() ของ Comparator ตัวแรกเพื่อรับอ็อบเจ็กต์ Comparator ตัวที่สอง ภายใต้ประทุนของวิธีการ Reversed() จะสร้างตัวเปรียบเทียบเพื่อกลับลำดับของพารามิเตอร์ที่เปรียบเทียบ นี่แสดงว่าการกลับรายการเป็นวิธีการที่มีลำดับสูงกว่าเช่นกัน โดยจะสร้างและส่งกลับฟังก์ชันโดยไม่มีผลข้างเคียง เราใช้ตัวเปรียบเทียบทั้งสองนี้ในโค้ด
คัดลอกรหัสรหัสดังต่อไปนี้:
printPeople("เรียงลำดับจากน้อยไปมากตามอายุ: ",
คน.สตรีม()
.sorted(เปรียบเทียบจากน้อยไปหามาก)
.collect(toList())
-
printPeople("เรียงลำดับตามอายุ: ",
คน.สตรีม()
.sorted(เปรียบเทียบจากมากไปน้อย)
.collect(toList())
-
จากโค้ดจะเห็นได้ชัดเจนว่าคุณสมบัติใหม่เหล่านี้ของ Java8 ได้ลดความซ้ำซ้อนและความซับซ้อนของโค้ดลงอย่างมาก แต่ประโยชน์ที่ได้รับยังมีมากกว่านั้น มีความเป็นไปได้ไม่รู้จบรอให้คุณสำรวจใน JDK
เราสามารถจัดเรียงตามอายุได้แล้ว และยังจัดเรียงตามชื่อได้ง่ายอีกด้วย มาจัดเรียงคำศัพท์ตามชื่อกันดีกว่า ในทำนองเดียวกัน เราแค่ต้องเปลี่ยนตรรกะในนิพจน์แลมบ์ดาเท่านั้น
คัดลอกรหัสรหัสดังต่อไปนี้:
printPeople("เรียงลำดับจากน้อยไปมากตามชื่อ: ",
คน.สตรีม()
.sorted((person1, person2) ->
person1.getName().compareTo(person2.getName()))
.collect(toList()));
ผลลัพธ์ที่ได้จะถูกจัดเรียงตามลำดับพจนานุกรมตามชื่อ
คัดลอกรหัสรหัสดังต่อไปนี้:
เรียงลำดับจากน้อยไปหามากตามชื่อ:
เกร็ก - 35
เจน - 21
จอห์น - 20
ซาร่า - 21
จนถึงตอนนี้ เราได้จัดเรียงตามอายุหรือตามชื่อแล้ว เราสามารถทำให้ตรรกะของนิพจน์แลมบ์ดาฉลาดขึ้นได้ เช่น เราสามารถจัดเรียงตามอายุและชื่อพร้อมกันได้
เรามาเลือกคนที่อายุน้อยที่สุดในรายการกันดีกว่า ขั้นแรกเราสามารถจัดเรียงตามอายุจากน้อยไปหามาก จากนั้นเลือกอันแรกในผลลัพธ์ แต่นั่นไม่ได้ผลจริงๆ Stream มีวิธีการ min() เพื่อให้บรรลุเป้าหมายนี้ วิธีนี้ยังยอมรับตัวเปรียบเทียบ แต่จะส่งคืนวัตถุที่เล็กที่สุดในคอลเลกชัน มาใช้กันเถอะ
คัดลอกรหัสรหัสดังต่อไปนี้:
คน.สตรีม()
.min(บุคคล::ความแตกต่างระหว่างอายุ)
.ifPresent(อายุน้อยที่สุด -> System.out.println("อายุน้อยที่สุด: " + อายุน้อยที่สุด));
เมื่อเรียกเมธอด min() เราใช้การอ้างอิงเมธอด ageDifference เมธอด min() ส่งคืนวัตถุ Optinal เนื่องจากรายการอาจว่างเปล่าและอาจมีบุคคลที่อายุน้อยที่สุดมากกว่าหนึ่งคน จากนั้นเราจะหาบุคคลที่อายุน้อยที่สุดโดยใช้วิธี ifPrsend() ของ Optinal และพิมพ์ข้อมูลโดยละเอียดของเขา ลองมาดูที่ผลลัพธ์
คัดลอกรหัสรหัสดังต่อไปนี้:
อายุน้อยที่สุด: จอห์น - 20
การส่งออกอันที่เก่าที่สุดนั้นง่ายมากเช่นกัน เพียงส่งการอ้างอิงเมธอดนี้ไปยังเมธอด max()
คัดลอกรหัสรหัสดังต่อไปนี้:
คน.สตรีม()
.max(บุคคล::ความแตกต่างระหว่างอายุ)
.ifPresent(คนโต -> System.out.println("คนโต: " + คนโต));
มาดูชื่อและอายุของคนโตกันดีกว่า
คัดลอกรหัสรหัสดังต่อไปนี้:
คนโต: เกร็ก - 35
ด้วยนิพจน์แลมบ์ดาและการอ้างอิงเมธอด การใช้งานตัวเปรียบเทียบจะง่ายและสะดวกยิ่งขึ้น JDK ยังแนะนำวิธีการที่สะดวกสบายมากมายให้กับคลาส Compararor ซึ่งช่วยให้เราสามารถเปรียบเทียบได้ราบรื่นยิ่งขึ้น ดังที่เราจะดูด้านล่าง
การเปรียบเทียบหลายรายการและการเปรียบเทียบการสตรีม
มาดูวิธีการใหม่ที่สะดวกสบายจากอินเทอร์เฟซตัวเปรียบเทียบ และใช้เพื่อเปรียบเทียบคุณสมบัติหลายรายการ
ลองใช้ตัวอย่างจากส่วนก่อนหน้าต่อไป เรียงตามชื่อ นี่คือสิ่งที่เราเขียนไว้ด้านบน:
คัดลอกรหัสรหัสดังต่อไปนี้:
คน.สตรีม()
.sorted((person1, person2) ->
person1.getName().compareTo(person2.getName()));
เมื่อเปรียบเทียบกับวิธีการเขียนแบบชั้นในของศตวรรษที่ผ่านมา วิธีการเขียนนี้เรียบง่ายเกินไป อย่างไรก็ตาม มันสามารถทำให้ง่ายขึ้นได้ถ้าเราใช้ฟังก์ชันบางอย่างในคลาส Comparator การใช้ฟังก์ชันเหล่านี้สามารถช่วยให้เราแสดงวัตถุประสงค์ของเราได้อย่างราบรื่นมากขึ้น ตัวอย่างเช่น หากเราต้องการเรียงลำดับตามชื่อ เราสามารถเขียนได้ดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
ฟังก์ชั่นสุดท้าย <บุคคล, สตริง> byName = person -> person.getName();
คน.สตรีม()
.sorted(เปรียบเทียบ(byName));
ในโค้ดนี้เราได้นำเข้าวิธีการแบบคงที่ comparison() ของคลาส Comparator เมธอด comparison() ใช้นิพจน์แลมบ์ดาที่ส่งผ่านเพื่อสร้างออบเจ็กต์ Comparator กล่าวอีกนัยหนึ่ง ยังเป็นฟังก์ชันลำดับที่สูงกว่าที่ยอมรับฟังก์ชันเป็นพารามิเตอร์อินพุตและส่งกลับฟังก์ชันอื่น นอกจากจะทำให้ไวยากรณ์กระชับมากขึ้นแล้ว โค้ดดังกล่าวยังสามารถแสดงปัญหาที่แท้จริงที่เราต้องการแก้ไขได้ดีขึ้นอีกด้วย
ด้วยเหตุนี้ การเปรียบเทียบหลายๆ รายการจึงราบรื่นขึ้น ตัวอย่างเช่น รหัสต่อไปนี้เปรียบเทียบตามชื่อและอายุระบุทั้งหมด:
คัดลอกรหัสรหัสดังต่อไปนี้:
ฟังก์ชั่นสุดท้าย <บุคคล, จำนวนเต็ม> byAge = person -> person.getAge();
ฟังก์ชั่นสุดท้าย <บุคคล, สตริง> byTheirName = person -> person.getName();
printPeople("เรียงลำดับจากน้อยไปมากตามอายุและชื่อ: ",
คน.สตรีม()
.sorted(เปรียบเทียบ(byAge).thenComparing(byTheirName))
.collect(toList()));
ขั้นแรกเราสร้างนิพจน์แลมบ์ดาสองรายการ รายการหนึ่งส่งคืนอายุของบุคคลที่ระบุ และอีกรายการส่งคืนชื่อของเขา เมื่อเรียกใช้เมธอด sorted() เราจะรวมนิพจน์ทั้งสองนี้เข้าด้วยกันเพื่อให้สามารถเปรียบเทียบแอตทริบิวต์หลายรายการได้ เมธอด comparison() สร้างและส่งกลับ Comparator ตามอายุ จากนั้นเราจะเรียกเมธอด thenComparing() บน Comparator ที่ส่งคืน เพื่อสร้างตัวเปรียบเทียบแบบรวมที่เปรียบเทียบอายุและชื่อ ผลลัพธ์ด้านล่างคือผลลัพธ์ของการเรียงลำดับตามอายุก่อนแล้วจึงตามด้วยชื่อ
คัดลอกรหัสรหัสดังต่อไปนี้:
เรียงลำดับตามอายุและชื่อ:
จอห์น - 20
เจน - 21
ซาร่า - 21
เกร็ก - 35
อย่างที่คุณเห็น การใช้งาน Comparator สามารถรวมเข้าด้วยกันได้อย่างง่ายดายโดยใช้ lambda expression และคลาสเครื่องมือใหม่ที่ JDK มอบให้ มาแนะนำนักสะสมด้านล่างกันดีกว่า