ส่งกลับค่าหลายค่าจากวิธี Java: เหตุใดจึงไม่มีวัตถุ n-tuple

เหตุใดจึงไม่มีโซลูชัน (มาตรฐาน ได้รับการรับรองจาก Java) ซึ่งเป็นส่วนหนึ่งของภาษา Java เอง เพื่อส่งคืนค่าหลายค่าจากวิธี Java แทนที่จะให้นักพัฒนาต้องใช้วิธีของตนเอง เช่น Maps, Lists, Pairs ฯลฯ .? เหตุใด Java จึงไม่รองรับวัตถุ n-tuple

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


person Saket    schedule 19.09.2011    source แหล่งที่มา
comment
หืม............? การใช้โครงสร้างข้อมูลดังกล่าว คือ มาตรฐานใช่ไหม   -  person mrkhrts    schedule 19.09.2011
comment
เพราะไม่มีใครทำงานเพื่อนำหนึ่งในโซลูชันที่กำหนดเองเหล่านั้นมาสร้างมาตรฐานได้แน่นอน!   -  person Donal Fellows    schedule 19.09.2011
comment
มีวิธีมาตรฐาน: เรียกว่าวัตถุ   -  person toto2    schedule 19.09.2011
comment
ใช่ นั่นเป็นโครงสร้างข้อมูลมาตรฐาน แต่ไม่มีวิธีใดที่จะทำให้มันเป็นส่วนหนึ่งของโครงสร้างภาษาแทนที่จะรวมไว้ในคอลเลกชัน การเปรียบเทียบง่ายๆ ถ้าฉันทำได้ก็คือคุณสามารถส่งผ่านข้อโต้แย้งหลายข้อไปยังวิธีการหนึ่งได้สองวิธี: (a) มีตัวแปรพารามิเตอร์ตัวเดียวซึ่งก็คือ List‹?› และแยกพารามิเตอร์แต่ละตัวออกจากตัวแปรนั้น หรือ (b) มีตัวแปรพารามิเตอร์ที่แตกต่างกันสำหรับแต่ละอาร์กิวเมนต์ แค่คิดก็ดังแล้ว...   -  person Saket    schedule 19.09.2011
comment
สิ่งที่คุณพยายามทำไม่ได้มาตรฐาน แนวทางมาตรฐาน ได้แก่ การใช้แผนที่ รายการ หรือวัตถุแบบกำหนดเอง!   -  person adarshr    schedule 19.09.2011
comment
@adarshr - บางทีอาจฟังดู 'ไม่ได้มาตรฐาน' เพราะยังไม่มีมาตรฐาน แต่ ซึ่งเป็นสิ่งที่กำลังพยายามค้นหา :) อีกครั้ง ฉันแค่พยายามเปิดการสนทนา   -  person Saket    schedule 19.09.2011
comment
อาจซ้ำกันของ stackoverflow.com/questions/457629/   -  person Raedwald    schedule 19.09.2011
comment
ฉันเห็นโพสต์ด้านบนซึ่งพูดถึงวิธีในการดำเนินการนี้ แต่สิ่งที่ฉันพยายามจะเปิดใจก็คือ เหตุใดจึงต้องมีวิธีการดังกล่าว   -  person Saket    schedule 19.09.2011
comment
ฉันแค่พยายามเปิดการสนทนา: การสนทนาไม่ใช่รูปแบบที่แนะนำที่นี่ ดู stackoverflow.com/faq#dontask   -  person Raedwald    schedule 19.09.2011
comment
@Raedwald - 'การสนทนา'...ไม่ใช่ตัวอักษร :) ฉันกำลังพยายาม (รวมถึงคนอื่นๆ ด้วย) เข้าใจ/เรียนรู้ทฤษฎีเบื้องหลัง   -  person Saket    schedule 19.09.2011
comment
ดูเพิ่มเติมที่: stackoverflow.com/questions/457775/does-java-need-tuples   -  person Raedwald    schedule 19.09.2011
comment
บางที java กำลังทำเพื่อบังคับให้คุณใช้ค่าส่งคืนสไตล์ที่มีชื่อ ดังนั้นจึงไม่มีความสับสนเกี่ยวกับสิ่งที่เริ่มต้นส่งคืน...   -  person rogerdpack    schedule 17.04.2013
comment
ภาษาอื่นๆ ทำเช่นนี้ได้โดยใช้ไวยากรณ์การอ้างอิงแบบส่งผ่าน (หรือการอ้างอิงแบบหลอก เช่น การใช้ & (ตัวดำเนินการที่อยู่) ในภาษา C หรือ C++ นั่นคือวิธีที่ผู้คนใช้วิธีนี้ในสมัยก่อน ฉัน กำลังพยายามตัดสินใจว่าจะทำอย่างไรเพื่อบางสิ่งบางอย่าง และฉันอาจเลือกคลาสคงที่ส่วนตัวที่อธิบายด้านล่างเป็นคำตอบที่เลือก   -  person titania424    schedule 09.10.2013
comment
ทำไมไม่สร้างคลาส Tuple ของคุณเองเหมือนใน คำถามนี้   -  person jk7    schedule 10.01.2018


คำตอบ (6)


ฉันถือว่า OP หมายถึง "เหตุใด Java จึงไม่รองรับวัตถุ n-tuple" Python, Haskell, Lisp, ML ฯลฯ มีความสามารถ n-tuple ที่ต่างกัน บ่อยครั้งที่ความสามารถในการส่งคืนอ็อบเจ็กต์หลายรายการในภาษาหนึ่ง ๆ นั้นเป็นน้ำตาลเชิงวากยสัมพันธ์ (เช่นใน python return 'a', 'b')

เหตุผลก็คือการออกแบบภาษาและความสม่ำเสมอ Java ชอบความชัดเจนมากและไม่ชอบโครงสร้างข้อมูลที่ไม่เปิดเผยตัวตน (แม้ว่าฉันหวังว่าเราจะมีการปิดแบบไม่ระบุชื่อก็ตาม)

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

IMHO แม้ว่ามันจะน่ารำคาญ แต่ฉันมักจะต่อสู้กับปัญหานี้ด้วยการสร้างคลาสอินไลน์แบบคงที่:

private static class Combo {
   String name;
   int weight;
}

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

ฉันควรทราบว่าสำหรับ 2-tuples บางคนใช้ (หรือใช้ในทางที่ผิด) java.util.Map.Entry เนื่องจากมี java.util.AbstractMap.SimpleEntry ใน Java 6 นอกจากนี้ บางคนยังใช้ การสนับสนุนการจับคู่ของ Commons Lang3 (2-tuple)

Scala มีการสนับสนุน n-tuple โดยการเรียงลำดับของการโกงและมีอินเทอร์เฟซ tuple 2-16 ชุดที่เป็นมาตรฐานในภาษาและถูกซ่อนทางวากยสัมพันธ์จากโปรแกรมเมอร์

ด้วยเหตุผลด้านการศึกษาเพียงอย่างเดียว คุณอาจต้องการดูว่า ภาษาอื่นๆ บรรลุเป้าหมายนี้ได้อย่างไร

อัปเดต: สำหรับ Java 8

Java 8 จะ/อาจจะ (ดังนั้นนี่คือหมายเลขของฉัน... โทรหาฉันหน่อยสิ) รองรับอินเทอร์เฟซที่เรียกว่า java.lang.BiValue ด้วยการใช้งานที่เป็นรูปธรรมที่คุณสามารถใช้ได้ที่เรียกว่า java.lang.BiVal คลาสเหล่านี้มีไว้เพื่อช่วยสนับสนุนฟังก์ชันแลมบ์ดาใหม่ แต่สังเกตว่านี่เป็นเพียงสิ่งอันดับ 2 เท่านั้น

อัปเดต: สำหรับปี 2015

Java 8 ไม่ ได้รับการสนับสนุนสำหรับสิ่งอันดับ

อัปเดต: จากผู้เขียนปี 2015

หากคุณยังคงต้องการการสนับสนุน tuple มีไลบรารีสามแห่งที่รองรับ tuple ได้ดี:

  • javatuples - รองรับ JDK 5 ขึ้นไป มากถึง 10 สิ่ง
  • JOOλ - จากผู้เขียน jOOQ แต่ต้องใช้ JDK 8
  • Commons Lang 3 - ขณะนี้รองรับ Triple (3-tuple) และรองรับ JDK 6 และ ข้างบน.
person Adam Gent    schedule 19.09.2011
comment
Map.Entry เป็นสิ่งที่ฉันชอบ เหตุใดจึงสร้างอ็อบเจ็กต์ที่มีชื่อสำหรับงานง่ายๆ ที่ภาษาอื่นทำได้ทันที - person Erel Segal-Halevi; 26.02.2013
comment
อาจมีปัญหาเกิดขึ้นพร้อมกันกับรูปแบบนี้ (การเผยแพร่ที่ปลอดภัย) รูปแบบที่อธิบายไว้ในคำตอบสำหรับคำถามที่คล้ายกันนี้ (final + ตัวสร้าง) ควรแก้ไขปัญหานี้ - person Bruno; 10.10.2013
comment
ใช่ ฉันใส่ข้อความข้างต้นเพื่อความกระชับเท่านั้น และไม่ใช่เพื่อการใช้ซ้ำทั้งหมด วัตถุที่ไม่เปลี่ยนรูปมักเป็นตัวเลือกที่ดีเสมอ - person Adam Gent; 10.10.2013
comment
ถ้าฉันต้องคืนวัตถุ 3 ชิ้นล่ะ? - person Dejell; 17.12.2013
comment
+1 สำหรับการย้อนกลับและอัปเดตคำตอบจริง ๆ เมื่อเผชิญกับเงื่อนไขที่เปลี่ยนแปลง ฉันหวังว่าผู้คนจำนวนมากทำเช่นนี้ - person Chris Warth; 12.06.2015
comment
ฉันไม่เห็น java.lang.BiValue ที่สร้างไว้ใน Java 8 ตามที่แนะนำข้างต้น อาจจะลบการกล่าวถึงมันออกไป - person matanster; 05.04.2018

วิธีการ Java ส่งคืนค่าศูนย์หรือค่าเดียว นั่น คือ มาตรฐานสำหรับ java หากคุณต้องการส่งคืนค่าหลายค่า ให้สร้างออบเจ็กต์ที่มีหลายค่าแล้วส่งคืน

person DwB    schedule 19.09.2011
comment
สิ่งเดียวก็คือสำหรับวิธีการเล็กๆ น้อยๆ (ส่วนตัว) มันฟังดูเกินกำลังในบางครั้ง... - person Saket; 19.09.2011
comment
void เป็นประเภทส่งคืนใน java btw - person Buhake Sindi; 19.09.2011
comment
@The Elite Gentleman การพูดซึ่งคุณสามารถโยน null ได้ซึ่งหมายความว่า null จะต้องเป็นข้อยกเว้น :) - person Adam Gent; 19.09.2011
comment
นี่ไม่ใช่คำตอบว่าทำไมจึงไม่มีคำถาม - person Alexey; 03.07.2015
comment
คำถามว่าทำไมไม่มีจึงมีความหมายเท่ากับลิงเป็นอย่างไร? มันเป็นคำถามที่โง่ ไม่มีค่าส่งคืนหลายค่าสำหรับ java - person DwB; 03.02.2016

หากคุณต้องการส่งคืนวัตถุสองชิ้น คุณมักจะต้องการส่งคืนวัตถุเดียวที่ห่อหุ้มวัตถุทั้งสองแทน

person Psychologist    schedule 19.09.2011

มีวิธีที่แฮ็กได้หลายวิธีในการบรรลุเป้าหมายนี้ วิธีหนึ่งคือการส่งคืน Object[] แต่เมื่อคุณมีดัชนีที่ต้องกังวล และการตรวจสอบตัวชี้ค่าว่าง มันก็น่ารังเกียจ อีกวิธีหนึ่งคือการส่งคืน String แต่คุณต้องแยกวิเคราะห์มัน และมันก็น่ารังเกียจ

ฉันคิดว่าคำถามที่แท้จริงคือทำไม

ประเด็นสำคัญคือ หากฉันกำลังทำโปรเจ็กต์ร่วมกับคุณ และเห็นพฤติกรรมประเภทนี้ ฉันจะเขียนมันใหม่เพื่อให้คุณเห็นว่าควรจัดการอย่างไร หากคุณให้ตัวอย่างโค้ด ฉันจะเขียนใหม่เพื่อให้เห็นภาพ

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

person Travis    schedule 19.09.2011
comment
อาร์กิวเมนต์ที่ดีด้วยความรับผิดชอบเดียว - person Wivani; 19.09.2011
comment
การใช้วัตถุและการเจาะลึกวิธีการเล็ก ๆ เป็นแนวทางที่ดีมากตามที่อธิบายไว้ในคำตอบ - person Jayy; 19.09.2011
comment
@Travis สมมติว่าเรามีวัตถุดิสก์แคชพร้อมวิธีการที่ส่งคืนทั้งค่าแคชและคำอธิบายประกอบ (เช่น เวลาที่แก้ไขครั้งล่าสุด) ค่าที่ส่งคืนหลายค่านั้นสะอาดกว่ามากเมื่อใช้อ็อบเจ็กต์ wrapper เราไม่สามารถใช้การเรียกเมธอดสองครั้งได้ เนื่องจากแคชสามารถเปลี่ยนแปลงระหว่างการเรียกเมธอดได้ - person fhucho; 16.03.2013
comment
@fhucho นี่เป็นกรณีที่มันจะนำไปใช้ซึ่งสมเหตุสมผล สิ่งที่คุณกำลังมองหาคือการเขียนครั้งล่าสุดและรายละเอียด/ข้อมูลเมตา เหตุใดจึงไม่ควรห่อหุ้มไว้ในวัตถุ - person Travis; 18.03.2013
comment
@Travis ฉันคิดว่ามันจะส่งผลให้โค้ดสะอาดขึ้นเล็กน้อยและเข้าใจง่ายขึ้น นอกจากนี้ยังไม่จำเป็นต้องมีคลาส wrapper แต่นี่เป็นเรื่องของความคิดเห็นที่ฉันเดา - person fhucho; 19.03.2013

มีรูปแบบรูปแบบใหม่ให้เลือกใช้งาน และสอดคล้องกับลักษณะ "อะซิงโครนัสทั้งหมด" ที่คุณอาจพบเห็นในภาษาต่างๆ เช่น JavaScript

ทุกวันนี้รหัสของฉันมีลักษณะเช่นนี้ :-)

public class Class1 {

    public interface Callback {
       void setData(String item1, String item2);
    }
    public void getThing(Callback callback) {
        callback.setData("a", "b");
    }
}

public class Class2 {

    public void doWithThing(Class1 o) {
        o.getThing(new Class1.Callback() {
            public void setData(String item1, String item2) {
                ... do something with item 1 and item 2 ...
            }
        });
    }

}

ไม่มีวัตถุใหม่ที่จะสร้างและมีคลาสพิเศษไม่มากนักเนื่องจากอินเทอร์เฟซเป็นคลาสภายในของวัตถุ

นี่คือสิ่งที่ทำให้ Swift ยอดเยี่ยมมาก รหัสอาจมีลักษณะดังนี้:

o.getThing({ item1, item2 -> Void in
    ... do something with item 1 and item 2 ...
});

และเนื่องจากข้อโต้แย้งเพียงอย่างเดียวคือบล็อก แม้แต่สิ่งนี้:

o.getThing { item1, item2 -> Void in
    ... do something with item 1 and item 2 ...
};

Java ต้องการการปรับปรุงเพื่อทำให้โค้ดที่รับภาระในการเรียกกลับอ่านง่ายขึ้นมาก

person Paul Hamilton    schedule 23.05.2015

เนื่องจากการส่งคืนค่าหลายค่าจากวิธีการหนึ่งๆ ไม่ใช่แนวทางปฏิบัติที่แนะนำ (ใน Java)

หากคุณต้องการค่าที่ไม่เกี่ยวข้องจากวิธีการ คุณต้องมีโครงสร้างข้อมูลที่แตกต่างกัน เช่น วัตถุที่มีค่าเหล่านั้น หากคุณต้องการหลายอินสแตนซ์ของคลาสเดียวกัน (เช่น หลาย Strings ) คุณจะต้องส่งคืนอาร์เรย์หรือคอลเลกชันบางส่วนขึ้นอยู่กับความต้องการของคุณ

การส่งกลับค่าหลายค่าในภาษาอื่น ( Go for instance ) ใช้สำหรับอินสแตนซ์เพื่อส่งคืนรหัสข้อผิดพลาด แต่ Java ได้รับการออกแบบให้แตกต่างออกไปโดยใช้ข้อยกเว้น

person OscarRyz    schedule 19.09.2011