ในตัว Java 8 เพรดิเคตที่คืนค่าจริงเสมอ?


130

Google ฝรั่งมีกริยาที่ผลตอบแทนเสมอ trueJava 8 มีบางอย่างที่คล้ายกันPredicateหรือไม่? ฉันรู้ว่าฉันสามารถใช้แต่ฉันต้องการบางสิ่งบางอย่างที่ทำไว้ล่วงหน้าเพื่อที่คล้ายคลึงกัน(foo)->{return true;}Collections.emptySet()

คำตอบ:


162

ไม่มีเพรดิเคตในตัวเสมอจริงและเสมอ - เท็จใน Java 8 วิธีที่กระชับที่สุดในการเขียนสิ่งเหล่านี้คือ

x -> true

และ

x -> false

เปรียบเทียบสิ่งเหล่านี้กับ

Predicates.alwaysTrue() // Guava

และในที่สุดก็เป็นคลาสภายในที่ไม่ระบุชื่อ:

new Predicate<Object>() {
    public boolean test(Object x) {
        return true;
    }
}

อาจเป็นเหตุผลที่ Guava มีเพรดิเคตในตัวเหล่านี้คือมีข้อได้เปรียบทางวากยสัมพันธ์อย่างมากของการเรียกเมธอดแบบคงที่ในคลาสภายในที่ไม่ระบุตัวตน ใน Java 8 ไวยากรณ์แลมบ์ดามีความกระชับมากจนมีข้อเสียทางวากยสัมพันธ์ในการเขียนการเรียกเมธอดแบบคงที่

นั่นเป็นเพียงการเปรียบเทียบทางวากยสัมพันธ์เท่านั้น อาจมีข้อได้เปรียบด้านพื้นที่เล็กน้อยหากมีเพรดิเคตทั่วโลกที่เป็นจริงเสมอเมื่อเทียบกับx -> trueเหตุการณ์ที่เกิดขึ้นในหลายชั้นเรียนซึ่งแต่ละรายการจะสร้างอินสแตนซ์เพรดิเคตของตัวเอง นี่คือสิ่งที่คุณกังวลหรือไม่? การประหยัดดูไม่น่าสนใจซึ่งอาจเป็นสาเหตุที่ไม่ได้เพิ่มเข้ามาในตอนแรก แต่อาจได้รับการพิจารณาใหม่สำหรับการเปิดตัวในอนาคต

อัพเดท 2015-04-24

เราได้พิจารณานอกเหนือจากความหลากหลายของแบบคงที่ฟังก์ชั่นเช่นชื่อPredicate.alwaysTrue, Runnable.noopฯลฯ และเราได้ตัดสินใจที่จะไม่เพิ่มใด ๆ เพิ่มเติมในรุ่นอนาคตของ Java SE

แน่นอนว่ามีค่าบางอย่างในบางสิ่งที่มีชื่อเทียบกับแลมบ์ดาที่เขียนออกมา แต่ค่านี้ค่อนข้างน้อย เราคาดหวังว่าผู้คนจะเรียนรู้วิธีการอ่านและเขียนx -> trueและ() -> { }การใช้งานของพวกเขาจะกลายเป็นสำนวน แม้แต่มูลค่าFunction.identity()เกินx -> xก็ยังน่าสงสัย

มีข้อได้เปรียบด้านประสิทธิภาพเล็กน้อยในการนำฟังก์ชันที่มีอยู่กลับมาใช้ใหม่แทนที่จะประเมินแลมบ์ดาที่เป็นลายลักษณ์อักษร แต่เราคาดว่าการใช้งานฟังก์ชันประเภทนี้จะมีขนาดเล็กมากจนข้อได้เปรียบดังกล่าวเล็กน้อยไม่คุ้มกับการขยายตัวของ API

Holger ยังกล่าวถึงในความคิดเห็นถึงความเป็นไปได้ในการปรับแต่งฟังก์ชันประกอบเช่นPredicate.orและอื่น ๆ สิ่งนี้ได้รับการพิจารณาเช่นกัน ( JDK-8067971 ) แต่ถือว่าค่อนข้างเปราะบางและเกิดข้อผิดพลาดได้ง่ายและเกิดขึ้นไม่บ่อยพอจนไม่คุ้มกับความพยายามในการนำไปใช้

โปรดดูรายการคำถามที่พบบ่อยของ Lambda


14
ความกังวลสองประการ: ประการแรกคือความกะทัดรัด ถ้า(foo)->{return true;}ดีที่สุดที่ฉันทำได้ฉันต้องการที่ดีกว่านี้ แต่คุณหยิบยกขึ้นมาx->trueซึ่งดีกว่ามากและช่วยบรรเทาปัญหาแรกได้ ประเด็นที่สองคือตรรกะและการประกาศแบบคงที่ ถ้าฉันใช้x->trueก็ยังมีตรรกะที่เกี่ยวข้องซึ่งฉันอาจจะทำให้x->!trueเสียหายโดยไม่ได้ตั้งใจ (เช่น) แต่Predicate.alwaysTrue()มีที่ว่างสำหรับข้อผิดพลาดทางตรรกะเป็นศูนย์เนื่องจากมีวิธีการที่คล้ายกันเพียงหนึ่งหรือสองวิธี แถมยังได้รับรหัส IDE ฟรี x->trueเกือบจะดี แต่ฉันยังคงเขียนPredicate.alwaysTrue()วิธีการด้วยเหตุผลข้างต้น
Garret Wilson

10
@GarretWilson แต่Predicate.alwaysTrue()คุณก็อาจจะเผลอเขียนPredicate.alwaysFalse()ไปด้วยก็ได้
David Conrad

5
@DavidConrad แน่นอน มีหลายวิธีที่ฉันสามารถทำผิดพลาดได้เสมอและอันที่จริงฉันกำลังคิดค้นสิ่งใหม่ ๆ อยู่ตลอดเวลา ;) ฉันไม่ต้องการที่จะเริ่มต้นการโต้เถียงที่นี่มากกว่าบางสิ่งบางอย่างเล็ก ๆ น้อย ๆ แต่ฉันเพียงแค่จะบอกว่าจุดของฉันคือการที่มีการอ้างอิงวิธีการคงฉันมี จำกัด คำศัพท์ที่มีเพียงสองทางเลือกและalwaysTrue() alwaysFalse()ด้วยแลมด้าจริงฉันมีหลายรูปแบบ ฉันกำลังสร้างสูตรขึ้นใหม่ทุกครั้ง ในสาระสำคัญalwaysTrue()คือป้ายกำกับความหมายสำหรับสิ่งที่ฉันต้องการทำ x->trueกำลังทำซ้ำทุกครั้ง ไม่ใหญ่โต แต่ต้องคำนึงถึง
Garret Wilson

25
ข้อดีอย่างหนึ่งที่ใหญ่เป็นที่ยอมรับPredicate.alwaysTrue()และPredicate.alwaysFalse()กรณีคือว่าพวกเขาจะได้รับการยอมรับโดยการรวมวิธีการเช่นPredicate.or, และPredicate.and Predicate.negate()สิ่งนี้จะอนุญาตให้เริ่มต้นPredicateตัวแปรล่วงหน้าalwaysTrue()และเพิ่มเพรดิเคตโดยการรวมผ่านandโดยไม่มีค่าใช้จ่าย x->trueตั้งแต่การแสดงออกแลมบ์ดาไม่มีการรับประกันตัวตนของวัตถุนี้อาจล้มเหลวด้วย ยังไงก็ตามถ้าฉันมีคลาสที่Xมีstaticวิธีการy(){return true;}ใช้งานX::yจะสั้นกว่าx->trueแต่ไม่แนะนำจริงๆ…
Holger

10
สำนวน x -> trueมีข้อเสียที่ฉันต้องใช้ตัวแปรโดยไม่ต้องใช้ สิ่งนี้สร้างภาระสมองโดยไม่จำเป็นและยังเป็นการเตือนใน IDE ของฉัน ฉันพยายามใช้_ -> trueแต่นั่นเป็นข้อผิดพลาดทางไวยากรณ์ Java ไม่มีคีย์เวิร์ด (อ่าน: keyletter) สำหรับ "unused parameters" หวังว่าสิ่งนี้จะมาใน Java 9 (หรืออย่างน้อยก็: Java อะไรก็ได้ก่อนที่ฉันจะตาย ^^)
kap

4

ไม่มีฝรั่ง

Boolean.TRUE::booleanValue

3
นั่นดูน่าสนใจ. ฉันไม่แน่ใจว่ามันสื่อถึงจิตวิญญาณของคำขอได้หรือไม่ แต่ได้รับคะแนนจากความคิดสร้างสรรค์!
Garret Wilson

21
แต่มันไม่ใช่Predicateเพราะมันไม่ได้ใช้การโต้แย้ง
Florent Guillaume

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

16
การอ้างอิงวิธีการของคุณสามารถกำหนดให้กับ Supplier <Boolean> ได้ แต่ไม่ใช่ Predicate <T>
Daniel K.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.