ครั้งแรกที่ฉันได้สัมผัสกับการแสดงออกของแลมบ์ดาอยู่ใน typeScript (superset ของ JavaScript) และมันคือการทำให้วิธีการของ TypeScript นอกวิธีนี้มากกว่าในวิธีนี้ หลังจากใช้มันฉันก็รู้ทันทีว่าแลมบ์ดาไม่ใช่ฟีเจอร์ใหม่ของ JDK8 หรือไม่? ดังนั้นฉันรู้สึกว่าฉันตรวจสอบข้อมูลที่เกี่ยวข้องและบันทึกไว้:
1. การกำหนดพารามิเตอร์พฤติกรรม
ในระยะสั้นการกำหนดพารามิเตอร์พฤติกรรมหมายความว่าร่างกายของฟังก์ชั่นมีเฉพาะรหัสทั่วไปที่เหมือนแม่แบบในขณะที่ตรรกะบางอย่างที่เปลี่ยนแปลงไปตามสถานการณ์ทางธุรกิจจะถูกส่งผ่านไปยังฟังก์ชั่นในรูปแบบของพารามิเตอร์ การใช้พารามิเตอร์พฤติกรรมสามารถทำให้โปรแกรมทั่วไปมากขึ้นเพื่อรับมือกับความต้องการของการเปลี่ยนแปลงบ่อยครั้ง
พิจารณาสถานการณ์ทางธุรกิจโดยสมมติว่าเราจำเป็นต้องกรอง Apple ผ่านโปรแกรมก่อนอื่นเราจะกำหนดเอนทิตีของ Apple:
แอปเปิ้ลระดับสาธารณะ {/** หมายเลข*/ส่วนตัว id ยาว;/** สี*/สีส่วนตัว;/** น้ำหนัก*/น้ำหนักลอยตัวส่วนตัว;/** แหล่งกำเนิด*/ต้นกำเนิดสตริงส่วนตัว; แอปเปิ้ลสาธารณะ () {} แอปเปิ้ลสาธารณะ (id ยาว, สีสี, น้ำหนักลอย, ต้นกำเนิด) {this.id = id;ความต้องการเบื้องต้นของผู้ใช้อาจเป็นเพียงการกรองแอปเปิ้ลสีเขียวผ่านโปรแกรมดังนั้นเราจึงสามารถนำไปใช้อย่างรวดเร็วผ่านโปรแกรม:
รายการคงที่สาธารณะ <Apple> FilterGreenapples (รายการ <ples> แอปเปิ้ล) {รายการ <apple> filterapples = arraylist ใหม่ <> (); สำหรับ (แอปเปิ้ลสุดท้าย: แอปเปิ้ล) {ถ้า (color.green.equals (Apple.getColor ()))รหัสนี้ง่ายและไม่มีอะไรที่ควรพูด แต่เมื่อผู้ใช้ต้องการเป็นสีเขียวดูเหมือนว่าการปรับเปลี่ยนรหัสนั้นง่ายมันไม่มีอะไรมากไปกว่าการเปลี่ยนสภาพสีเขียวของเงื่อนไขการตัดสินเป็นสีแดง แต่เราต้องพิจารณาปัญหาอื่น หากเงื่อนไขการเปลี่ยนแปลงเปลี่ยนไปบ่อยครั้งจะเสร็จสิ้น? หากเป็นเพียงการเปลี่ยนสีเราสามารถปล่อยให้ผู้ใช้ผ่านเงื่อนไขการตัดสินสีโดยตรงและพารามิเตอร์ของวิธีการตัดสินเปลี่ยน "ชุดที่จะตัดสินและสีที่จะกรอง" แต่ถ้าผู้ใช้ไม่เพียง แต่ตัดสินสี แต่ยังต้องการตัดสินน้ำหนักขนาด ฯลฯ ? คุณคิดว่าเราสามารถเพิ่มพารามิเตอร์ที่แตกต่างกันเพื่อให้การตัดสินเสร็จสมบูรณ์หรือไม่? แต่การส่งพารามิเตอร์แบบนี้เป็นเรื่องดีจริงๆเหรอ? หากมีเงื่อนไขการกรองมากขึ้นเรื่อย ๆ และโหมดการรวมกันมีความซับซ้อนมากขึ้นเราจำเป็นต้องพิจารณาสถานการณ์ทั้งหมดและมีกลยุทธ์การเผชิญปัญหาที่สอดคล้องกันสำหรับแต่ละสถานการณ์หรือไม่? ในเวลานี้เราสามารถกำหนดพารามิเตอร์พฤติกรรมแยกเงื่อนไขการกรองและส่งผ่านเป็นพารามิเตอร์ ในเวลานี้เราสามารถห่อหุ้มอินเทอร์เฟซการตัดสิน:
อินเทอร์เฟซสาธารณะ AppleFilter {/*** ตัวกรองบทคัดย่อ ** @param Apple* @return*/boolean Accept (Apple Apple);}/*** encapsulate filters ลงในอินเตอร์เฟส ** @param แอปเปิ้ล*@param ตัวกรอง* @return*/รายการคงที่ ArrayList <> (); สำหรับ (แอปเปิ้ลสุดท้าย: แอปเปิ้ล) {ถ้า (filter.accept (Apple)) {filterapples.add (Apple);}} return filterapples;}หลังจากสรุปพฤติกรรมข้างต้นเราสามารถตั้งค่าเงื่อนไขตัวกรองในการโทรเฉพาะและส่งผ่านเงื่อนไขเป็นพารามิเตอร์ลงในวิธีการ ในเวลานี้เราใช้วิธีการชั้นในที่ไม่ระบุชื่อ:
โมฆะคงที่สาธารณะหลัก (String [] args) {รายการ <pliS> แอปเปิ้ล = ใหม่ arraylist <> (); // ตัวกรองรายการแอปเปิ้ล <apple> filterapples = filterapplesByappleFilter (แอปเปิ้ลแอปเปิ้ลใหม่ (@OverridePublic Apple.getweight ()> 100;}});}การออกแบบนี้มักจะใช้ภายใน JDK เช่น java.util.comparator, java.util.concurrent.callable ฯลฯ เมื่อใช้อินเทอร์เฟซประเภทนี้เราสามารถใช้คลาสที่ไม่ระบุชื่อเพื่อระบุตรรกะการดำเนินการเฉพาะของฟังก์ชันในสถานที่โทรเฉพาะ อย่างไรก็ตามจากบล็อกรหัสข้างต้นแม้ว่ามันจะเกินจริงมาก แต่ก็ไม่กระชับเพียงพอ ใน Java8 เราสามารถทำให้มันง่ายขึ้นผ่านแลมบ์ดา:
// ตัวกรองรายการแอปเปิ้ล <apple> filterapples = filterapplesByappleFilter (แอปเปิ้ล, (แอปเปิ้ลแอปเปิ้ล) -> color.red.equals (Apple.getColor ()) && Apple.getweight ()> = 100); // () -> xxx ()
2. คำจำกัดความการแสดงออกของแลมบ์ดา
เราสามารถกำหนดนิพจน์แลมบ์ดาเป็นฟังก์ชั่นที่ไม่ระบุชื่อที่ย่อและผ่านได้ ก่อนอื่นเราต้องทำให้ชัดเจนว่าการแสดงออกของแลมบ์ดาเป็นฟังก์ชั่นเป็นหลัก แม้ว่ามันจะไม่ได้อยู่ในคลาสที่เฉพาะเจาะจง แต่ก็มีรายการพารามิเตอร์ร่างกายฟังก์ชั่นประเภทการส่งคืนและความสามารถในการโยนข้อยกเว้น ประการที่สองมันไม่ระบุชื่อและนิพจน์แลมบ์ดาไม่มีชื่อฟังก์ชั่นเฉพาะ การแสดงออกของแลมบ์ดาสามารถส่งผ่านเหมือนพารามิเตอร์ดังนั้นจึงทำให้การเขียนโค้ดง่ายขึ้นอย่างมาก คำจำกัดความรูปแบบมีดังนี้:
รูปแบบ 1: รายการพารามิเตอร์ -> นิพจน์
รูปแบบ 2: รายการพารามิเตอร์ -> {expression collection}
ควรสังเกตว่านิพจน์แลมบ์ดาหมายถึงคำหลักส่งคืนดังนั้นในนิพจน์เดียวเราไม่จำเป็นต้องเขียนคำหลักส่งคืนอย่างชัดเจน แต่เมื่อนิพจน์เป็นชุดของคำสั่งเราต้องเพิ่มการส่งคืนและแนบหลายการแสดงออกด้วยการจัดฟัน มาดูตัวอย่างด้านล่าง:
// ส่งคืนความยาวของสตริงที่กำหนดคำสั่ง return โดยปริยาย (String s) -> s.length () // มักจะส่งคืนวิธีการที่ไม่ได้รับการจัดสรร () () - -> 42 // มีการแสดงออกหลายบรรทัดซึ่งอยู่ในวงเล็บปีกกา (int x, int y) -> {int z = x * y;3. ใช้นิพจน์แลมบ์ดาตามอินเตอร์เฟสการทำงาน
การใช้นิพจน์แลมบ์ดาต้องการความช่วยเหลือของอินเทอร์เฟซการทำงานซึ่งหมายความว่าเฉพาะเมื่ออินเทอร์เฟซการทำงานปรากฏขึ้นเราสามารถทำให้พวกเขาง่ายขึ้นด้วยนิพจน์แลมบ์ดา
อินเตอร์เฟสการทำงานที่กำหนดเอง:
อินเทอร์เฟซที่ใช้งานได้ถูกกำหนดเป็นอินเทอร์เฟซที่มีวิธีนามธรรมเพียงวิธีเดียว การปรับปรุงคำจำกัดความอินเตอร์เฟสของ Java8 คือการแนะนำวิธีการเริ่มต้นเพื่อให้เราสามารถให้การใช้งานเริ่มต้นของวิธีการในอินเทอร์เฟซ อย่างไรก็ตามไม่ว่าจะมีวิธีการเริ่มต้นกี่วิธีตราบใดที่มีวิธีการที่เป็นนามธรรมเพียงวิธีเดียวเท่านั้นมันเป็นอินเทอร์เฟซที่ใช้งานได้ดังนี้ (อ้างอิงจาก Applefilter ด้านบน):
/*** อินเทอร์เฟซตัวกรอง Apple*/ @functionalInterfacepublic Interface AppleFilter {/*** เงื่อนไขตัวกรองบทคัดย่อ ** @param Apple* @return*/boolean Accept (Apple Apple);};AppleFilter มีวิธีการที่เป็นนามธรรมเท่านั้น (Apple Apple) ตามคำจำกัดความมันถือได้ว่าเป็นอินเทอร์เฟซที่ใช้งานได้ เมื่อกำหนดเราจะเพิ่มคำอธิบายประกอบ @FunctionAlInterface ลงในอินเตอร์เฟสเพื่อทำเครื่องหมายอินเตอร์เฟสเป็นอินเตอร์เฟสที่ใช้งานได้ อย่างไรก็ตามอินเทอร์เฟซนี้เป็นทางเลือก หลังจากเพิ่มอินเทอร์เฟซนี้คอมไพเลอร์จะ จำกัด อินเทอร์เฟซให้มีวิธีนามธรรมเท่านั้นมิฉะนั้นจะมีการรายงานข้อผิดพลาดดังนั้นจึงขอแนะนำให้เพิ่มคำอธิบายประกอบนี้ลงในส่วนต่อประสานการทำงาน
JDK มาพร้อมกับอินเทอร์เฟซที่ใช้งานได้:
JDK เป็นนิพจน์แลมบ์ดาที่มีส่วนต่อประสานการทำงานที่หลากหลาย ด้านล่างนี้เป็นตัวอย่างของการใช้งานของ Predicate <T>, ผู้บริโภค <T>, ฟังก์ชั่น <t, r> ตามลำดับ
ภาคแสดง:
@functionalInterfacepublic อินเตอร์เฟส Predicate <t> {/*** ประเมินการคาดการณ์นี้ในอาร์กิวเมนต์ที่กำหนด ** @param t อาร์กิวเมนต์อินพุต* @return {@code true} หากอาร์กิวเมนต์อินพุตตรงกับการคาดการณ์ฟังก์ชั่นของเพรดิเคตคล้ายกับ Applefilter ด้านบน มันใช้เงื่อนไขที่เราตั้งค่าภายนอกเพื่อตรวจสอบพารามิเตอร์ที่เข้ามาและส่งคืนบูลีนผลการตรวจสอบ การใช้งานต่อไปนี้เพื่อกรององค์ประกอบของรายการคอลเลกชัน:
/**** @param List* @param Predicate* @param <t>* @return*/public <t> รายการ <t> ตัวกรอง (รายการ <t> รายการ, predicate <t> predicate) {รายการ <t> newlist = new ArrayList <t> ();ใช้:
demo.filter (รายการ, (string str) -> null! = str &&! str.isempty ());
ผู้บริโภค
@functionalInterfacepublic Interface Consumer <t> {/*** ดำเนินการนี้ในอาร์กิวเมนต์ที่กำหนด ** @param t อาร์กิวเมนต์อินพุต*/void accept (t t);}ผู้บริโภคให้ฟังก์ชั่นนามธรรมที่ยอมรับได้ซึ่งได้รับพารามิเตอร์ แต่ไม่คืนค่า ต่อไปนี้ใช้ผู้บริโภคเพื่อสำรวจคอลเลกชัน
/*** Traversal ของคอลเลกชันและดำเนินการพฤติกรรมที่กำหนดเอง ** @param List* @param Consumer* @param <t>*/public <t> ตัวกรองโมฆะ (รายการ <t> รายการ, ผู้บริโภค <T> ผู้บริโภค) {สำหรับ (สุดท้าย t: รายการ)การใช้อินเทอร์เฟซที่ใช้งานได้ข้างต้นวนซ้ำผ่านคอลเลกชันสตริงและพิมพ์สตริงที่ไม่ว่างเปล่า:
demo.filter (รายการ, (string str) -> {ถ้า (stringutils.isnotblank (str)) {system.out.println (str);}});การทำงาน
@functionalInterfacepublic ฟังก์ชันฟังก์ชัน <t, r> {/*** ใช้ฟังก์ชั่นนี้กับอาร์กิวเมนต์ที่กำหนด ** @param t อาร์กิวเมนต์ฟังก์ชัน*@return ฟังก์ชันผลลัพธ์*/r ใช้ (t t);}ฟังก์ชั่นดำเนินการแปลง อินพุตคือข้อมูลประเภท T และส่งคืนข้อมูลประเภท R ฟังก์ชั่นการใช้งานต่อไปนี้เพื่อแปลงชุด:
public <t, r> list <r> ตัวกรอง (รายการ <t> รายการ, ฟังก์ชั่น <t, r> ฟังก์ชั่น) {รายการ <r> newlist = new ArrayList <r> (); สำหรับ (สุดท้าย t t: รายการ) {newlist.add (function.apply (t));} ส่งคืน newlist;}อื่น:
demo.filter (รายการ, (string str) -> integer.parseint (str));
อินเทอร์เฟซที่ใช้งานได้ข้างต้นยังให้การใช้งานเริ่มต้นของการดำเนินการเชิงตรรกะ พูดคุยกันในภายหลังเมื่อแนะนำวิธีการเริ่มต้นของอินเตอร์เฟส Java8 ~
บางสิ่งให้ความสนใจในระหว่างการใช้งาน:
พิมพ์การอนุมาน:
ในระหว่างกระบวนการเข้ารหัสบางครั้งเราอาจสงสัยว่าอินเทอร์เฟซที่ใช้งานได้รหัสการโทรของเราจะตรงกัน ในความเป็นจริงคอมไพเลอร์จะทำการตัดสินที่ถูกต้องตามพารามิเตอร์ประเภทการส่งคืนประเภทข้อยกเว้น (ถ้ามี) ฯลฯ
เมื่อโทรด้วยวิธีที่เฉพาะเจาะจงประเภทของพารามิเตอร์สามารถละเว้นได้ในบางครั้งดังนั้นจึงทำให้รหัสง่ายขึ้น:
// ตัวกรองรายการแอปเปิ้ล <apple> filterapples = filterapplesByappleFilter (แอปเปิ้ล, (แอปเปิ้ลแอปเปิ้ล) -> color.red.equals (Apple.getColor ()) && Apple.getweight ()> = 100); // ในบางกรณี color.red.equals (apple.getColor ()) && apple.getweight ()> = 100);
ตัวแปรท้องถิ่น
ตัวอย่างทั้งหมดด้านบนนิพจน์แลมบ์ดาของเราใช้พารามิเตอร์ร่างกายของพวกเขาเรายังสามารถใช้ตัวแปรท้องถิ่นในแลมบ์ดาดังต่อไปนี้
int weight = 100; list <apple> filterapples = filterapplesByappleFilter (แอปเปิ้ล, Apple -> color.red.equals (Apple.getColor ()) && apple.getweight ()> = น้ำหนัก);:
ในตัวอย่างนี้เราใช้น้ำหนักตัวแปรท้องถิ่นในแลมบ์ดา อย่างไรก็ตามการใช้ตัวแปรท้องถิ่นในแลมบ์ดาจะต้องมีการประกาศตัวแปรอย่างชัดเจนว่าเป็นขั้นสุดท้ายหรือในความเป็นจริงสุดท้าย นี่เป็นส่วนใหญ่เป็นเพราะตัวแปรท้องถิ่นถูกเก็บไว้ในสแต็กและนิพจน์แลมบ์ดาทำงานในเธรดอื่น เมื่อมุมมองเธรดเข้าถึงตัวแปรโลคัลตัวแปรมีความเป็นไปได้ที่จะเปลี่ยนหรือรีไซเคิลดังนั้นจะไม่มีปัญหาด้านความปลอดภัยของเธรดหลังจากการดัดแปลงด้วยขั้นสุดท้าย
iv. วิธีการอ้างอิง
การใช้การอ้างอิงวิธีการสามารถทำให้รหัสง่ายขึ้น บางครั้งการทำให้เข้าใจง่ายนี้ทำให้รหัสดูง่ายขึ้น ลองมาดูตัวอย่าง:
/* ... ละเว้นการดำเนินการเริ่มต้นของแอปเปิ้ล* /// ใช้แอปเปิ้ลนิพจน์แลมบ์ดา ((แอปเปิ้ล A, แอปเปิ้ล b) -> float.compare (a.getweight (), b.getweight ())); // ใช้วิธีการอ้างอิงแอปเปิ้ล
การอ้างอิงวิธีการเชื่อมต่อการเป็นสมาชิกวิธีการและวิธีการผ่าน :: ซึ่งส่วนใหญ่แบ่งออกเป็นสามหมวดหมู่:
วิธีการคงที่
(args) -> classname.staticmethod (args)
เปลี่ยนเป็น
classname :: StaticMethod
ตัวอย่างวิธีการพารามิเตอร์
(args) -> args.instancemethod ()
เปลี่ยนเป็น
classname :: Instancemethod // classname เป็นประเภท args
วิธีอินสแตนซ์ภายนอก
(args) -> ext.instancemethod (args)
เปลี่ยนเป็น
Ext :: Instancemethod (Args)
อ้างถึง:
http://www.codeceo.com/article/lambda-of-java-8.html
ข้างต้นคือการแสดงออกของแลมบ์ดาของคุณสมบัติ JDK8 ใหม่ที่ตัวแก้ไขแนะนำให้คุณรู้จัก ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ หากคุณมีคำถามใด ๆ โปรดฝากข้อความถึงฉันและบรรณาธิการจะตอบกลับคุณทันเวลา ขอบคุณมากสำหรับการสนับสนุนเว็บไซต์ Wulin.com!