Java 8: TriFunction (และ kin) ใน java.util.function อยู่ที่ไหน หรือมีทางเลือกอย่างไร?


113

ฉันเห็น java.util.function.BiFunction ดังนั้นฉันจึงสามารถทำได้:

BiFunction<Integer, Integer, Integer> f = (x, y) -> { return 0; };

จะเกิดอะไรขึ้นถ้าสิ่งนั้นไม่ดีพอและฉันต้องการ TriFunction? มันไม่มี!

TriFunction<Integer, Integer, Integer, Integer> f = (x, y, z) -> { return 0; };

ฉันเดาว่าฉันควรเพิ่มว่าฉันรู้ว่าฉันสามารถกำหนด TriFunction ของตัวเองได้ฉันแค่พยายามเข้าใจเหตุผลเบื้องหลังโดยไม่รวมไว้ในไลบรารีมาตรฐาน


1
ด้วยอินเทอร์เฟซ bifunction คุณสามารถกำหนดคลาส N-function ได้อย่างง่ายดายหากคุณกำหนด trifunction เป็นอินเทอร์เฟซแยกต่างหาก sb แรกจะถามว่าทำไมไม่เป็น quadofunction และประการที่สองคุณต้องทำซ้ำวิธีการทั้งหมดที่ใช้ Bifunction เป็นพารามิเตอร์
user902383

6
มีจุดผลตอบแทนที่ลดน้อยลงสำหรับ API เช่นนี้ (โดยส่วนตัวแล้วฉันคิดว่า JDK8 ผ่านมันไปได้สักพักแล้ว แต่มันก็เกินกว่านั้น)
Louis Wasserman

ฉันเชื่อว่าเหตุผลคือการบอกว่า Function และ BiFunction ถูกนำไปใช้อย่างสมบูรณ์กับวัตถุและประเภทดั้งเดิม การรวม TriFunctions กับรูปแบบต่างๆทั้งหมดจะทำให้ JRE มีคลาสและวิธีการมากมาย
Thorbjørn Ravn Andersen

1
คำตอบสั้น ๆ ใน Java ถ้าคุณไม่เห็นคุณสร้างของคุณเอง (ดูคำตอบของ Alex P แน่นอน) Sidenote ใน C # ผู้ใช้งานดอทเน็ตให้ข้อมูลสำเร็จรูปแก่คุณ (ไม่เกิน 16 อาร์กิวเมนต์) แต่ไม่มีชื่อนำหน้า ("Bi" ที่นี่): ดู docs.microsoft.com/en-us/dotnet/api/… เพียงแค่ "Func" ง่ายๆ นี่คือหนึ่งในสถานที่ที่ฉันชอบ dotnet มากกว่า java โปรดอย่าเปลี่ยนส่วนความคิดเห็นนี้ให้กลายเป็นสงคราม และ จำกัด ความคิดเห็นไว้ที่ BiFunction เท่านั้น
granadaCoder

คำตอบ:


81

เท่าที่ฉันรู้มีเพียงสองประเภทของฟังก์ชั่นทำลายล้างและสร้างสรรค์

ในขณะที่ฟังก์ชั่นสร้างสรรค์ตามที่ชื่อมีความหมายสร้างบางสิ่งบางอย่างสิ่งที่ทำลายล้างจะทำลายบางสิ่ง แต่ไม่ใช่ในแบบที่คุณคิดในตอนนี้

ตัวอย่างเช่นฟังก์ชัน

Function<Integer,Integer> f = (x,y) -> x + y  

เป็นที่สร้างสรรค์อย่างใดอย่างหนึ่ง ตามที่คุณต้องการสร้างบางสิ่ง ในตัวอย่างที่คุณสร้าง tuple (x, y) ฟังก์ชันที่สร้างสรรค์มีปัญหาเนื่องจากไม่สามารถจัดการกับอาร์กิวเมนต์ที่ไม่มีที่สิ้นสุดได้ แต่สิ่งที่แย่ที่สุดคือคุณไม่สามารถเปิดการโต้แย้งไว้ได้ คุณไม่สามารถแค่พูดว่า "ดีให้ x: = 1" และลองใช้ทุก y ที่คุณอาจต้องการลอง คุณต้องสร้างทุกครั้ง tuple x := 1ทั้งหมดด้วย ดังนั้นถ้าคุณต้องการที่จะเห็นสิ่งที่ฟังก์ชั่นกลับมาคุณจะต้องเขียนy := 1, y := 2, y := 3f(1,1) , f(1,2) , f(1,3)

ใน Java 8 ควรจัดการฟังก์ชันเชิงสร้างสรรค์ (โดยส่วนใหญ่) โดยใช้การอ้างอิงเมธอดเนื่องจากไม่มีประโยชน์มากนักในการใช้ฟังก์ชันแลมบ์ดาที่สร้างสรรค์ เป็นเหมือนวิธีการคงที่ คุณสามารถใช้ได้ แต่ไม่มีสถานะที่แท้จริง

อีกประเภทหนึ่งคือประเภททำลายล้างต้องใช้อะไรบางอย่างและรื้อถอนเท่าที่จำเป็น ตัวอย่างเช่นฟังก์ชันการทำลายล้าง

Function<Integer, Function<Integer, Integer>> g = x -> (y -> x + y) 

ทำเช่นเดียวกับฟังก์ชันfที่สร้างสรรค์ ประโยชน์ของฟังก์ชันทำลายล้างคือคุณสามารถจัดการกับอาร์กิวเมนต์ที่ไม่มีที่สิ้นสุดได้แล้วซึ่งสะดวกเป็นพิเศษสำหรับสตรีมและคุณสามารถเปิดอาร์กิวเมนต์ไว้ได้ ดังนั้นหากคุณอีกครั้งต้องการที่จะเห็นสิ่งที่จะส่งผลให้เป็นเช่นหากx := 1และy := 1 , y := 2 , y := 3คุณสามารถพูดh = g(1)และ h(1)เป็นผลสำหรับy := 1, h(2)สำหรับy := 2และสำหรับh(3)y := 3

ที่นี่คุณมีสถานะคงที่! มันเป็นแบบไดนามิกและนั่นคือเวลาส่วนใหญ่ที่เราต้องการจากแลมด้า

รูปแบบเช่น Factory นั้นง่ายกว่ามากหากคุณสามารถใส่ฟังก์ชันที่เหมาะกับคุณได้

คนที่ทำลายล้างจะรวมเข้าด้วยกันได้อย่างง่ายดาย หากประเภทถูกต้องคุณก็สามารถแต่งได้ตามต้องการ ด้วยการใช้สิ่งนั้นคุณสามารถกำหนด morphisms ซึ่งทำให้การทดสอบ (ด้วยค่าที่ไม่เปลี่ยนรูป) ง่ายขึ้นมาก!

คุณสามารถทำเช่นนั้นได้ด้วยองค์ประกอบที่สร้างสรรค์ แต่องค์ประกอบการทำลายล้างดูดีกว่าและเหมือนรายการหรือมัณฑนากรมากกว่าและองค์ประกอบที่สร้างสรรค์ดูเหมือนต้นไม้มาก และสิ่งต่างๆเช่นการย้อนรอยด้วยฟังก์ชันที่สร้างสรรค์นั้นไม่ดี คุณสามารถบันทึกฟังก์ชันบางส่วนของฟังก์ชันการทำลายล้าง (การเขียนโปรแกรมแบบไดนามิก) และใน "backtrack" เพียงแค่ใช้ฟังก์ชันการทำลายล้างแบบเก่า ซึ่งทำให้โค้ดมีขนาดเล็กลงและอ่านได้ดีขึ้น ด้วยฟังก์ชันที่สร้างสรรค์คุณจะมีข้อโต้แย้งทั้งหมดไม่มากก็น้อยที่จะจำอาร์กิวเมนต์ซึ่งอาจเป็นจำนวนมาก

เหตุใดจึงจำเป็นต้องBiFunctionมีคำถามมากกว่าว่าทำไมจึงไม่มีTriFunction?

ก่อนอื่นคุณมักจะมีค่าไม่กี่ค่า (น้อยกว่า 3) และต้องการผลลัพธ์ดังนั้นจึงไม่จำเป็นต้องใช้ฟังก์ชันการทำลายล้างแบบปกติเลยซึ่งสิ่งที่สร้างสรรค์จะทำได้ดี และมีหลายอย่างเช่น monads ที่ต้องการฟังก์ชันที่สร้างสรรค์จริงๆ แต่นอกเหนือจากนั้นยังไม่มีเหตุผลที่ดีมากมายว่าทำไมถึงมีBiFunctionเลย ซึ่งไม่ได้หมายความว่าควรเอาออก! ฉันสู้เพื่อ Monads ของฉันจนกว่าฉันจะตาย!

ดังนั้นหากคุณมีอาร์กิวเมนต์จำนวนมากซึ่งคุณไม่สามารถรวมเป็นคลาสคอนเทนเนอร์แบบลอจิคัลได้และหากคุณต้องการให้ฟังก์ชันสร้างสรรค์ให้ใช้การอ้างอิงเมธอด มิฉะนั้นให้ลองใช้ความสามารถใหม่ที่ได้รับจากฟังก์ชันการทำลายล้างคุณอาจพบว่าตัวเองทำสิ่งต่างๆมากมายโดยใช้สายรหัสน้อยลงมาก


2
คุณตอบคำถามของฉัน ... ฉันคิดว่า ... ฉันไม่รู้ว่านักออกแบบภาษาจาวามาจากแนวความคิดนี้หรือไม่ แต่ฉันไม่เชี่ยวชาญในการเขียนโปรแกรมเชิงฟังก์ชัน ขอบคุณสำหรับคำอธิบาย
Richard Finegan

81
ฉันไม่เคยเห็นคำที่สร้างสรรค์และทำลายล้างเพื่ออ้างถึงแนวคิดที่คุณอธิบาย ฉันคิดว่าcurriedและnon-curriedเป็นคำศัพท์ทั่วไปมากกว่า
Feuermurmel

17
ตัวอย่างฟังก์ชันแรกไม่ถูกต้องตามหลักไวยากรณ์ ควรเป็น BiFunction ไม่ใช่ Function เพราะต้องใช้อาร์กิวเมนต์อินพุตสองตัว
แจ้ง

3
IMO BiFunctionถูกสร้างขึ้นเพื่อให้ลดข้อมูลได้ง่ายและStreamการดำเนินการเทอร์มินัลส่วนใหญ่เป็นเพียงการลดข้อมูล ตัวอย่างที่ดีคือBinaryOperator<T>ใช้ในหลายCollectorsๆ องค์ประกอบแรกจะลดลงพร้อมกับองค์ประกอบที่สองมากกว่าที่จะลดลงได้ด้วยองค์ประกอบถัดไปและอื่น ๆ แน่นอนคุณสามารถสร้างFunction<T, Function<T, T>func = x -> (y -> / * รหัสลดที่นี่ * /) แต่อย่างจริงจัง? BinaryOperator<T> func = (x, y) -> /*reduction code here*/ทั้งหมดนี้เมื่อคุณสามารถทำ นอกจากนี้วิธีการลดข้อมูลนี้ดูเหมือนวิธีการ "ทำลายล้าง" ของคุณมากสำหรับฉัน
FBB

32
วิธีนี้ทำให้ได้รับการโหวตเพิ่มขึ้นมากมาย? มันเป็นคำตอบที่แย่และน่าสับสนเพราะมันขึ้นอยู่กับหลักฐานว่าFunction<Integer,Integer> f = (x,y) -> x + yเป็น Java ที่ถูกต้องซึ่งไม่ใช่ นั่นควรจะเป็น BiFunction เริ่มต้นด้วย!
wvdz

162

หากคุณต้องการ TriFunction เพียงแค่ทำสิ่งนี้:

@FunctionalInterface
interface TriFunction<A,B,C,R> {

    R apply(A a, B b, C c);

    default <V> TriFunction<A, B, C, V> andThen(
                                Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (A a, B b, C c) -> after.apply(apply(a, b, c));
    }
}

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

  public class Main {

    public static void main(String[] args) {
        BiFunction<Integer, Long, String> bi = (x,y) -> ""+x+","+y;
        TriFunction<Boolean, Integer, Long, String> tri = (x,y,z) -> ""+x+","+y+","+z;


        System.out.println(bi.apply(1, 2L)); //1,2
        System.out.println(tri.apply(false, 1, 2L)); //false,1,2

        tri = tri.andThen(s -> "["+s+"]");
        System.out.println(tri.apply(true,2,3L)); //[true,2,3]
    }
  }

ฉันเดาว่ามีการใช้งานจริงสำหรับ TriFunction java.util.*หรือjava.lang.*อาจมีการกำหนดไว้ ฉันจะไม่ไปเกิน 22 อาร์กิวเมนต์แม้ว่า ;-) หมายความว่าอย่างไรรหัสใหม่ทั้งหมดที่อนุญาตให้สตรีมคอลเลกชันไม่จำเป็นต้องใช้ TriFunction เป็นพารามิเตอร์วิธีใด ๆ ดังนั้นจึงไม่รวม

อัปเดต

เพื่อความสมบูรณ์และปฏิบัติตามคำอธิบายฟังก์ชันการทำลายล้างในคำตอบอื่น (ที่เกี่ยวข้องกับการแกง) นี่คือวิธีที่สามารถจำลอง TriFunction ได้โดยไม่ต้องใช้อินเทอร์เฟซเพิ่มเติม:

Function<Integer, Function<Integer, UnaryOperator<Integer>>> tri1 = a -> b -> c -> a + b + c;
System.out.println(tri1.apply(1).apply(2).apply(3)); //prints 6

แน่นอนว่าเป็นไปได้ที่จะรวมฟังก์ชันในรูปแบบอื่น ๆ เช่น:

BiFunction<Integer, Integer, UnaryOperator<Integer>> tri2 = (a, b) -> c -> a + b + c;
System.out.println(tri2.apply(1, 2).apply(3)); //prints 6
//partial function can be, of course, extracted this way
UnaryOperator partial = tri2.apply(1,2); //this is partial, eq to c -> 1 + 2 + c;
System.out.println(partial.apply(4)); //prints 7
System.out.println(partial.apply(5)); //prints 8

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


6
ขอบคุณสำหรับการแก้ปัญหา และใช่มีการใช้งานสำหรับ BiFunction, TriFunction, ... ไม่เช่นนั้นคนจะไม่ค้นหา เดาว่าแลมด้าทั้งหมดเป็นของใหม่เกินไปสำหรับ Oracle ในตอนนี้และจะขยายออกไปในเวอร์ชัน Java ในภายหลัง ในขณะนี้เป็นการพิสูจน์แนวคิด
Stefan Endrullis

Hy @Alex ช่วยกำหนดบรรทัดต่อไปนี้ได้ไหม เกิดอะไรขึ้นที่นี่เริ่มต้น <V> TriFunction <A, B, C, V> และจากนั้น (ฟังก์ชัน <? super R,? ขยาย V> หลัง) {Objects.requireNonNull (หลัง); return (A a, B b, C c) -> after.apply (ใช้ (a, b, c)); }
Muneeb Nasir

@MuneebNasir - ช่วยให้คุณทำองค์ประกอบของฟังก์ชัน: TriFunction<Integer,Integer,Integer,Integer> comp = (x,y,z) -> x + y + z; comp = comp.andThen(s -> s * 2); int result = comp.apply(1, 2, 3); //12ดูstackoverflow.com/questions/19834611/…
Alex Pakka

เพิ่มandThen()ตัวอย่างการใช้งานในคำตอบ
Alex Pakka

ไม่เพียง แต่การแกงกะหรี่จะไม่ได้รับการปรับให้เข้ากับภาษา Java อย่างดี แต่ยังแก้ไขฉันด้วยหากฉันผิด แต่BiFunctionถูกใช้ในStreamAPI เพื่อลดข้อมูลซึ่งดูเหมือนวิธีการแกงกะหรี่สำหรับฉันมาก: คุณไม่เคยใช้เวลามากกว่าสอง อาร์กิวเมนต์และคุณสามารถประมวลผลองค์ประกอบจำนวนเท่าใดก็ได้โดยลดครั้งละหนึ่งรายการ (ดูความคิดเห็นของฉันเกี่ยวกับคำตอบที่ยอมรับฉันยินดีที่จะทราบว่าฉันคิดผิดหรือไม่ที่เห็นแบบนั้น)
FBB

13

ทางเลือกคือเพิ่มการอ้างอิงด้านล่าง

<dependency>
    <groupId>io.vavr</groupId>
    <artifactId>vavr</artifactId>
    <version>0.9.0</version>
</dependency>

ตอนนี้คุณสามารถใช้ฟังก์ชัน Vavr เช่นด้านล่างไม่เกิน 8 อาร์กิวเมนต์

3 ข้อโต้แย้ง:

Function3<Integer, Integer, Integer, Integer> f = 
      (a, b, c) -> a + b + c;

5 ข้อโต้แย้ง:

Function5<Integer, Integer, Integer, Integer, Integer, Integer> f = 
      (a, b, c, d, e) -> a + b + c + d + e;

2
ฉันกำลังจะอัปเดตคำตอบของฉันเพื่อพูดถึง vavr แต่คุณเป็นคนแรกฉันจึงโหวตให้ หากคุณมาถึงจุดที่คุณต้องการ TriFunction มีโอกาสมากที่คุณจะทำได้ดีขึ้นด้วยการใช้vavrไลบรารีซึ่งจะทำให้การเขียนโปรแกรมรูปแบบการทำงานสามารถใช้งานได้ใน Java มากที่สุด
Alex Pakka

7

ฉันมีคำถามเกือบเหมือนกันและมีคำตอบบางส่วน ไม่แน่ใจว่าคำตอบเชิงสร้างสรรค์ / เชิงสร้างสรรค์คือสิ่งที่นักออกแบบภาษามีอยู่ในใจหรือไม่ ฉันคิดว่าการมี 3 ขึ้นไป N มีกรณีการใช้งานที่ถูกต้อง

ฉันมาจาก. NET และใน. NET คุณมี Func และ Action สำหรับฟังก์ชันโมฆะ เพรดิเคตและกรณีพิเศษอื่น ๆ ยังมีอยู่ ดู: https://msdn.microsoft.com/en-us/library/bb534960(v=vs.110).aspx

ฉันสงสัยว่าทำไมนักออกแบบภาษาจึงเลือกใช้ Function, Bifunction และไม่ดำเนินการต่อจนกว่า DecaExiFunction?

คำตอบสำหรับส่วนที่สองคือการลบประเภท หลังจากรวบรวมแล้ว Func และ Func ไม่มีความแตกต่างกัน ต่อไปนี้จึงไม่รวบรวม:

package eu.hanskruse.trackhacks.joepie;

public class Functions{

    @FunctionalInterface
    public interface Func<T1,T2,T3,R>{
        public R apply(T1 t1,T2 t2,T3 t3);
    }

    @FunctionalInterface
    public interface Func<T1,T2,T3,T4,R>{
        public R apply(T1 t1,T2 t2,T3 t3, T4 t4);
    }
}

ฟังก์ชันภายในถูกใช้เพื่อหลีกเลี่ยงปัญหาเล็กน้อยอื่น ๆ Eclipse ยืนยันที่จะมีทั้งสองคลาสในไฟล์ชื่อ Function ในไดเร็กทอรีเดียวกัน ... ไม่แน่ใจว่าปัจจุบันนี้เป็นปัญหาของคอมไพเลอร์หรือไม่ แต่ฉันไม่สามารถเปลี่ยนข้อผิดพลาดใน Eclipse ได้

Func ถูกใช้เพื่อป้องกันการขัดแย้งของชื่อกับประเภทฟังก์ชัน java

ดังนั้นหากคุณต้องการเพิ่ม Func จาก 3 ไม่เกิน 16 อาร์กิวเมนต์คุณสามารถทำได้สองสิ่ง

  • ทำให้ TriFunc, TesseraFunc, PendeFunc, ... DecaExiFunc ฯลฯ
    • (ฉันควรใช้ภาษากรีกหรือละติน?)
  • ใช้ชื่อแพ็กเกจหรือคลาสเพื่อทำให้ชื่อแตกต่างกัน

ตัวอย่างสำหรับวิธีที่สอง:

 package eu.hanskruse.trackhacks.joepie.functions.tri;

        @FunctionalInterface
        public interface Func<T1,T2,T3,R>{
            public R apply(T1 t1,T2 t2,T3 t3);
        }

และ

package eu.trackhacks.joepie.functions.tessera;

    @FunctionalInterface
    public interface Func<T1,T2,T3,T4,R>{
        public R apply(T1 t1,T2 t2,T3 t3, T4 t4);
    }

แนวทางที่ดีที่สุดคืออะไร?

ในตัวอย่างข้างต้นฉันไม่ได้รวมการนำไปใช้สำหรับเมธอด andThen () และ compose () หากคุณเพิ่มสิ่งเหล่านี้คุณต้องเพิ่ม 16 โอเวอร์โหลดแต่ละตัว: TriFunc ควรมี andthen () พร้อม 16 อาร์กิวเมนต์ นั่นจะทำให้คุณมีข้อผิดพลาดในการคอมไพล์เนื่องจากการอ้างอิงแบบวงกลม นอกจากนี้คุณจะไม่มีการโอเวอร์โหลดเหล่านี้สำหรับ Function และ BiFunction ดังนั้นคุณควรกำหนด Func ด้วยอาร์กิวเมนต์เดียวและ Func ด้วยสองอาร์กิวเมนต์ ในการอ้างอิงแบบวงกลม. NET จะถูกหลีกเลี่ยงโดยใช้วิธีการขยายซึ่งไม่มีอยู่ใน Java


2
ทำไมคุณต้องandThenมี 16 ข้อโต้แย้ง? ผลลัพธ์ของฟังก์ชันใน Java คือค่าเดียว andThenรับค่านี้และทำอะไรกับมัน นอกจากนี้ไม่มีปัญหาในการตั้งชื่อ ชื่อคลาสควรแตกต่างกันและอยู่ในไฟล์อื่นที่มีชื่อเหมือนกัน - ตามตรรกะที่กำหนดโดยนักพัฒนาภาษา Java ที่มี Function และ BiFunction นอกจากนี้จำเป็นต้องมีชื่อที่แตกต่างกันทั้งหมดนี้หากประเภทอาร์กิวเมนต์แตกต่างกัน หนึ่งสามารถสร้างVargFunction(T, R) { R apply(T.. t) ... }สำหรับประเภทเดียว
Alex Pakka

2

ฉันพบซอร์สโค้ดสำหรับ BiFunction ที่นี่:

https://github.com/JetBrains/jdk8u_jdk/blob/master/src/share/classes/java/util/function/BiFunction.java

ฉันแก้ไขเพื่อสร้าง TriFunction เช่นเดียวกับ BiFunction จะใช้ andThen () และไม่ compose () ดังนั้นสำหรับบางแอปพลิเคชันที่ต้องใช้ compose () อาจไม่เหมาะสม ควรจะใช้ได้ดีสำหรับวัตถุประเภทปกติ บทความดีๆเกี่ยวกับ andThen () และ compose () สามารถพบได้ที่นี่:

http://www.deadcoderising.com/2015-09-07-java-8-functional-composition-using-compose-and-andthen/

import java.util.Objects;
import java.util.function.Function;

/**
 * Represents a function that accepts two arguments and produces a result.
 * This is the three-arity specialization of {@link Function}.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #apply(Object, Object)}.
 *
 * @param <S> the type of the first argument to the function
 * @param <T> the type of the second argument to the function
 * @param <U> the type of the third argument to the function
 * @param <R> the type of the result of the function
 *
 * @see Function
 * @since 1.8
 */
@FunctionalInterface
public interface TriFunction<S, T, U, R> {

    /**
     * Applies this function to the given arguments.
     *
     * @param s the first function argument
     * @param t the second function argument
     * @param u the third function argument
     * @return the function result
     */
    R apply(S s, T t, U u);

    /**
     * Returns a composed function that first applies this function to
     * its input, and then applies the {@code after} function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of output of the {@code after} function, and of the
     *           composed function
     * @param after the function to apply after this function is applied
     * @return a composed function that first applies this function and then
     * applies the {@code after} function
     * @throws NullPointerException if after is null
     */
    default <V> TriFunction<S, T, U, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (S s, T t, U u) -> after.apply(apply(s, t, u));
    }
}

2

คุณยังสามารถสร้างฟังก์ชันของคุณเองโดยใช้พารามิเตอร์ 3 ตัว

@FunctionalInterface
public interface MiddleInterface<F,T,V>{
    boolean isBetween(F from, T to, V middleValue);
}

MiddleInterface<Integer, Integer, Integer> middleInterface = 
(x,y,z) -> x>=y && y<=z; // true

1

คุณไม่สามารถหยุดที่ TriFunction ได้เสมอไป บางครั้งคุณอาจต้องส่งพารามิเตอร์จำนวน n ไปยังฟังก์ชันของคุณ จากนั้นทีมสนับสนุนจะต้องสร้าง QuadFunction เพื่อแก้ไขโค้ดของคุณ วิธีแก้ปัญหาระยะยาวคือการสร้าง Object ที่มีพารามิเตอร์พิเศษจากนั้นใช้ฟังก์ชันสำเร็จรูปหรือ BiFunction

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