ความแตกต่างระหว่างแลมบ์ดาและการอ้างอิงวิธีการคืออะไร

ที่มา: Reddit IntelliJ IDEA แนะนำให้แทนที่นิพจน์แลมบ์ดาด้วยการอ้างอิงวิธีการ ความแตกต่างระหว่างพวกเขาคืออะไร? คอฟฟี่เบรค #163.  ความแตกต่างระหว่างแลมบ์ดาและการอ้างอิงวิธีการคืออะไร  5 วิธีในการต่อสตริง Null ใน Java - 1ปรากฎว่ามีความแตกต่างเล็กน้อยระหว่างนิพจน์แลมบ์ดาและการอ้างอิงวิธีการ ตัวอย่างเช่น เปรียบเทียบ: myInstance::getStuffและ() ->myInstance.getStuff( ) โดยทั่วไปแล้วทั้งสองตัวเลือกจะเทียบเท่ากัน แต่ถ้า myInstance เป็นโมฆะ และ lambda สร้างตัวชี้ null เมื่อประเมิน lambda การอ้างอิงเมธอดจะถูกสร้างขึ้นทันทีเมื่อพยายามเข้าถึงการอ้างอิง และอะไร? โดยทั่วไป นี่เป็นสิ่งสำคัญหากโค้ดที่ประเมินนิพจน์ lambda อยู่ภายใน try-catch ที่มีตัวชี้ null ตัวอย่างเช่น ฉันมีฟังก์ชันmightBeNull(Supplier<T> function)ที่ทำสิ่งนี้:
try {
    doStuff(function.get().getSomeMore().getSomeMore());
} catch (NullPointerException e) {
    doOtherStuff();
}
หากการเรียกmightBeNull(() -> myNullVariable.getStuff())ทำงานได้โดยไม่มีข้อยกเว้น ดังนั้น “equivalent”: mightBeNull(myNullVariable::getStuff)จะส่ง NullPointerException ทันทีเมื่อมีการเรียกใช้ฟังก์ชัน นั่นคือความแตกต่าง บันทึก. ตาม Stackoverflow หากคุณแทนที่ lambda ด้วยการอ้างอิงเมธอด โค้ดไบต์ของคลาสจะมีขนาดกะทัดรัดมากขึ้น ซึ่งหมายความว่าคลาสจะโหลดเข้าสู่ JVM ได้เร็วขึ้น อย่างไรก็ตาม เพื่อที่จะได้รับประสบการณ์ดังกล่าว จำเป็นต้องมีแลมบ์ดาที่ไม่ได้เพิ่มประสิทธิภาพจำนวนหลายพันตัว อย่างไรก็ตามในโครงการขนาดใหญ่สามารถสะสมจำนวนดังกล่าวได้ง่าย มิฉะนั้น การเลือกระหว่างแลมบ์ดาและการอ้างอิงวิธีการจะขึ้นอยู่กับรสนิยมและความสามารถในการอ่านโค้ด ตัวอย่างเช่น หาก lambda มีหลายบรรทัด ความสามารถในการอ่านจะลดลง และโค้ดจะได้รับประโยชน์ก็ต่อเมื่อ lambda ถูกวางในวิธีแยกต่างหากและใช้การอ้างอิงเท่านั้น

5 วิธีในการต่อสตริง Null ใน Java

ที่มา: Gitconnected หลังจากอ่านโพสต์นี้ คุณจะได้เรียนรู้วิธีเพิ่มเติมในการทำงานกับสตริงใน Java Java มีหลายวิธีในการต่อสตริงเข้าด้วยกัน แต่บางครั้งเมื่อเราไม่ใส่ใจกับสตริงว่าง เราก็อาจจบลงด้วย null ซึ่งเห็นได้ชัดว่าไม่ใช่สิ่งที่เราต้องการ ดังนั้นให้ใช้วิธีการแนะนำของฉันเพื่อหลีกเลี่ยงค่า Null เมื่อเชื่อมสตริงเข้าด้วยกัน

การวิเคราะห์ปัญหา

หากเราต้องการเชื่อมอาร์เรย์สตริงเข้าด้วยกัน เราก็สามารถใช้ตัวดำเนินการ + ได้ อย่างไรก็ตาม เราอาจพบ ค่า ว่าง เมื่อทำสิ่ง นี้
String[] values = {"https", "://", "gist.", "github", ".com", null};
String result = "";

for (String value : values) {
    result = result + value;
}
การรวมองค์ประกอบทั้งหมดเหล่านี้เข้าด้วยกันทำให้เราได้ผลลัพธ์นี้:
https://gist.github.comnull
แม้ว่าเราจะพบปัญหาแล้ว แต่ ค่าNull ที่เป็นผลลัพธ์ ก็จะถูกต่อเป็นสตริงด้วย ซึ่งเห็นได้ชัดว่าไม่ใช่สิ่งที่เราหวังไว้ และแม้ว่าเราจะทำงานบน Java 8 หรือสูงกว่า โดยใช้เมธอดString.join() แบบคงที่ เพื่อรวมสตริง เราก็จะยังคงได้ ค่า nullอยู่
String[] values = {"https", "://", "gist.", "github", ".com", null};
String result = String.join("", values);
ผลลัพธ์ก็เหมือนกัน:
https://gist.github.comnull
แล้วจะแก้ไขปัญหานี้อย่างไร? มีวิธีแก้ไขหลายประการ เพื่อให้ง่ายต่อการสาธิตโค้ดในภายหลัง เราจะแยกวิธีการที่สามารถส่งผ่านสตริงและส่งกลับสตริงที่ไม่ใช่ค่าว่าง
public String nullToString(String value) {
    return value == null ? "" : value;
}

1. String.concat ()

String.concat()เป็นวิธีการที่มาพร้อมกับ คลาส String สะดวกมากสำหรับการต่อสายอักขระ
for (String value : values) {
    result = result.concat(getNonNullString(value));
}
เนื่องจาก การเรียกใช้เมธอด nullToString() จึงไม่มีค่า Nullตามมา

2.ตัวสร้างสตริง

คลาสStringBuilderมีวิธีการที่เป็นประโยชน์และสะดวกมากมายสำหรับการสร้างสตริง วิธี ที่ใช้กันมากที่สุดคือ เมธอด append()ซึ่งใช้append()เพื่อเชื่อมสตริงเข้าด้วยกันและรวมกับ เมธอด nullToString()เพื่อหลีกเลี่ยงค่า Null
String[] values = {"https", "://", "gist.", "github", ".com", null};
StringBuilder result = new StringBuilder();

for (String value : values) {
    result = result.append(nullToString(value));
}
ด้วยเหตุนี้ คุณจะได้รับผลลัพธ์ดังต่อไปนี้:
https://gist.github.com

3. คลาส StringJoiner (Java 8+)

คลาสStringJoinerมีฟังก์ชันที่มีประสิทธิภาพมากขึ้นสำหรับการเข้าร่วมสตริง ไม่เพียงระบุตัวคั่นระหว่างการต่อข้อมูลเท่านั้น แต่ยังระบุคำนำหน้าและส่วนต่อท้ายได้ด้วย เมื่อเชื่อมสตริงเข้าด้วยกัน เราสามารถใช้ เมธอด add() ของมัน ได้ เมธอด nullToString()จะถูกนำมาใช้ที่นี่เพื่อหลีกเลี่ยงค่า Null
String[] values = {"https", "://", "gist.", "github", ".com", null};
StringJoiner result = new StringJoiner("");

for (String value : values) {
    result = result.add(nullToString(value));
}

4. Streams.filter (Java 8+)

Stream API เป็นคลาสการดำเนินการสตรีมที่ทรงพลังที่นำมาใช้ใน Java 8 ซึ่งสามารถทำการกรองมาตรฐาน การจับคู่ การแวะผ่าน การจัดกลุ่ม สถิติ และการดำเนินการอื่นๆ
  • ตัวกรองการทำงานของตัวกรองสามารถรับ ฟังก์ชัน ภาคแสดงได้
  • อินเทอร์เฟซของ ฟังก์ชัน ภาคแสดงจะเหมือนกับ อินเทอ ร์เฟซฟังก์ชันที่แนะนำก่อนหน้านี้
  • นี่คืออินเทอร์เฟซที่ใช้งานได้
  • สามารถใช้พารามิเตอร์ทั่วไป<T>และค่าที่ส่งคืนเป็นประเภทบูลีน
  • ภาคแสดงมักใช้สำหรับ ข้อมูล ตัวกรอง
ดังนั้นเราจึงสามารถกำหนดเพรดิเคตเพื่อตรวจสอบ สตริง ว่างและส่งผ่านไปยัง เมธอด filter()จาก Stream API นอกจากนี้ คุณสามารถใช้ เมธอด Collectors.joining()เพื่อรวมสตริงที่ไม่ใช่ null ที่เหลือได้
String[] values = {"https", "://", "gist.", "github", ".com", null};

String result = Arrays.stream(values)
    .filter(Objects::nonNull)
    .collect(Collectors.joining());

5. ใช้ตัวดำเนินการ +

การใช้ ตัวดำเนินการ +อาจช่วยแก้ปัญหาได้เช่นกัน แต่ไม่แนะนำ เรารู้ว่าStringเป็นวัตถุที่ไม่เปลี่ยนรูป การใช้เครื่องหมาย + มักจะสร้างอ็อบเจ็กต์สตริง และทุกครั้งที่มีการสร้างสตริงใหม่ในหน่วยความจำ ดังนั้นประสิทธิภาพของการใช้เครื่องหมาย + เพื่อต่อสตริงจึงสูงมาก

บทสรุป

บทความนี้นำเสนอวิธีการต่างๆ สำหรับการต่อสายอักขระและการจัดการ NULLs ซึ่งวิธีการที่แตกต่างกันอาจเหมาะสมกับสถานการณ์ที่แตกต่างกัน การวิเคราะห์แสดงให้เห็นว่าประสิทธิภาพของ StringBuilderนั้นดีที่สุด แต่ในสภาวะจริง คุณต้องรวมสถานการณ์บางอย่างเข้าด้วยกัน จากนั้นเลือกวิธีที่สูญเสียประสิทธิภาพน้อยที่สุด