Java: รับไอเท็มแรกจากคอลเล็กชัน


277

หากฉันมีคอลเล็กชันเช่นCollection<String> strsฉันจะนำไอเท็มแรกออกมาได้อย่างไร ฉันสามารถเรียกIteratorใช้ครั้งแรกnext()แล้วโยนIteratorออกไป มีวิธีที่สิ้นเปลืองน้อยลงหรือไม่?


1
แน่นอนอาจจะมีวิธีที่ดีกว่าในการเข้าถึงองค์ประกอบแรกถ้าคุณรู้ว่าชั้นภาชนะดำเนินการ ...
Rooke

การวางนัยทั่วไปสำหรับดัชนีใด ๆ : stackoverflow.com/questions/1047957/ …
Ciro Santilli 法轮功冠状病病六四事件法轮功

1
ดูเหมือนว่าคุณต้องการ Queue.peek ()
โยฮันเนส

คำตอบ:


131

Iterables.get (yourC, indexYouWant)

เพราะถ้าคุณใช้ Collections คุณควรใช้ Google Collections


7
นั่นก็เหมือนกันมันแค่ตรวจสอบว่ามันเป็นรายการแรกหรือไม่และรับโดยดัชนีถ้ามันเป็น นอกจากนี้ยังมีรหัสบางอย่างเพื่อพยายามล้มเหลวได้เร็วขึ้นในคอลเลกชันจริง (นั่นคือถ้าดัชนีมีขนาดใหญ่เกินไปก็พยายามที่จะคิดออกโดยไม่ต้องวนซ้ำทุกสิ่งและโยนข้อยกเว้นในตอนท้าย)
Yishai

1
สุจริตอาจทำให้ช้ากว่า c.iterator () ถัดไป () - แต่รหัสนั้นชัดเจนและง่ายกว่าในการปรับเปลี่ยน
Carl

2
ฉันเห็นด้วยอย่างแน่นอนว่ามันสะอาดกว่า แต่ OP ก็เกี่ยวกับสิ้นเปลือง แต่ฉันเดาว่าเนื่องจากคำตอบของคุณได้รับการยอมรับว่าเป็นสิ่งที่ต้องการ
Yishai

8
สำหรับผู้ที่มาถึงที่นี่: ฉันคิดว่าคำตอบของ jheddings น่าจะเป็นคำตอบที่ "ทำให้เสร็จ" ที่สุดแม้ว่าฉันจะชอบ @ DonaldRaab (ทางลงหน้า) สำหรับกรณีที่ฉันใช้ห้องสมุด GC อยู่แล้ว คำตอบของฉันเป็นจริงสำหรับกรณีที่หนึ่งอาจต้องการเขียนในความยืดหยุ่นสำหรับภายหลัง (พูดหากตัดสินใจว่าองค์ประกอบที่สองคือความร้อนใหม่)
คาร์ล

4
บางครั้งคุณแค่ใช้รหัสที่ใช้ Collections จึงมีอะไรให้ทำมากมาย
erickrf

436

ดูเหมือนว่าเป็นวิธีที่ดีที่สุดที่จะทำ:

String first = strs.iterator().next();

คำถามที่ดี ... ในตอนแรกดูเหมือนว่าการกำกับดูแลสำหรับCollectionอินเทอร์เฟซ

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

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

ยกตัวอย่างเช่นมองไปที่ชนิดส่งกลับโดยวิธีการที่เราเห็นว่ามันเป็นArrayList<String>.iterator() ArrayList::Itrนี่เป็นคลาสภายในที่เข้าถึงองค์ประกอบของรายการโดยตรงแทนที่จะคัดลอก

เพียงให้แน่ใจว่าคุณตรวจสอบการกลับมาiterator()เพราะมันอาจจะว่างเปล่าหรือnullขึ้นอยู่กับการใช้งาน


3
สิ่งสำคัญคือต้องทราบว่า "เคล็ดลับ" นี้จะใช้งานได้เมื่อการรวบรวมมีเนื้อหาเท่านั้น หากไม่มีตัววนซ้ำตัววนซ้ำอาจส่งคืนข้อผิดพลาดซึ่งต้องตรวจสอบขนาดการรวบรวมก่อน
spaceemotion

20
นี่ควรเป็นคำตอบที่ถูกต้อง ฉันไม่เข้าใจว่าทำไมคำตอบคือ "ใช้ห้องสมุดอื่นเสมอ" .
Kuzeko

องค์ประกอบที่สองของคอลเลกชันเป็นอย่างไร ทำไมก่อน -> ถัดไป () ไม่ทำงาน ฉันควรทำอย่างไรดี? ขอบคุณ!
pb772

ไม่ปลอดภัยพอไม่รับประกันว่าการสะสมจะชี้ไปที่องค์ประกอบที่ 1 เสมอ
นักพัฒนาต่อไป

84

ใน java 8:

Optional<String> firstElement = collection.stream().findFirst();

สำหรับ java เวอร์ชันเก่ามีวิธี getFirst ใน Guava Iterables :

Iterables.getFirst(iterable, defaultValue)

6
โซลูชัน java 8 มีประโยชน์อย่างยิ่งเนื่องจากจัดการกับเคสที่คอลเล็กชันว่างเปล่าอย่างงดงาม
SpaceTrucker

4
ไม่ดี. คุณเพิ่มโอเวอร์เฮดของสตรีม () เพื่อรับ (0) เพียงเพราะคุณขี้เกียจเขียนโค้ด 4 บรรทัด if (! CollectionUtils.isEmpty (productList)) {return Optional.of (productList.get (0)); } return optional.empty ();
RS

ฉันไม่มีgetFirstวิธีให้ใช้ มีgetและgetLastวิธีการคือ
user1209216

4
@RS และจะเกิดอะไรขึ้นหากคุณไม่สามารถเรียก productList.get (0) ได้ว่าเป็นคอลเล็กชัน .. (ตามคำถาม OP)
Denham Coote

40

ไม่มีสิ่งใดเป็นรายการ "แรก" ในรายการCollectionเพราะมันเป็น .. คอลเลกชันที่ง่าย

จากเมธอดCollection.iterator ()ของ Java doc :

ไม่มีการรับประกันใด ๆ เกี่ยวกับลำดับการคืนองค์ประกอบ ...

ดังนั้นคุณไม่สามารถ

หากคุณใช้อินเทอร์เฟซอื่นเช่นรายการคุณสามารถทำสิ่งต่อไปนี้:

String first = strs.get(0);

แต่โดยตรงจากคอลเลกชันนี้เป็นไปไม่ได้


11
ฉันไม่คิดว่าget(int n)ถูกกำหนดไว้สำหรับCollection
Nick Heiner

2
คุณพูดถูกฉันพลาดจุดนั้น ฉันได้อัพเดตคำตอบแล้ว คุณทำไม่ได้! (ยกเว้นกรณีที่คอลเลกชันจะดำเนินการโดยบางระดับ underlaying ที่ช่วยให้การรับประกัน)
OscarRyz

รับไม่ได้อยู่ในอินเตอร์เฟซการเก็บ
แอนดี้ Gherna

21
ออสการ์ฉันคิดว่าคุณคุยโวเรื่องนี้มากไป องค์ประกอบแรกของคอลเลคชั่นอาจจะสุ่มในบางกรณีเช่น HashSet แต่มีการกำหนดไว้อย่างดีนั่นคือ. itatorator () ถัดไป () นอกจากนี้ยังมีเสถียรภาพในการใช้งานคอลเลกชันทุกครั้งที่ฉันเคยเห็น (ที่เกี่ยวข้องทราบว่าในขณะที่ชุดไม่ได้รับประกันการสั่งซื้อทุกชนิดย่อยเดียวของชุดใน JDK ยกเว้น HashSet ไม่.)
เควิน Bourrillion

3
อาจเป็นได้ แต่พิจารณากรณีเมื่อคุณเพิ่มองค์ประกอบใหม่ลงในคอลเลกชันคุณไม่ทราบ (โดยอินเทอร์เฟซ) ถ้าองค์ประกอบนั้นเป็นครั้งแรกที่ผ่านมาหรือมันจะถูกแทรกอยู่ตรงกลาง เพื่อผลลัพธ์ที่แม่นยำคุณควรใช้อินเทอร์เฟซอื่น ทว่าสิ่งที่ Rosarch ต้องการคือองค์ประกอบที่ 1 ไม่ว่าอะไรก็ตาม การรู้จักคอลเลคชั่นที่อยู่ภายใต้อาจช่วยได้ แต่ก็ป้องกันไม่ให้คุณเปลี่ยนมัน
OscarRyz

4

ดูเหมือนว่าคอลเล็กชันของคุณต้องการเป็นแบบรายการดังนั้นฉันขอแนะนำ:

List<String> myList = new ArrayList<String>();
...
String first = myList.get(0);

2

ใน Java 8 คุณมีโอเปอเรเตอร์จำนวนมากที่จะใช้เช่นขีด จำกัดอินสแตนซ์

     /**
 * Operator that limit the total number of items emitted through the pipeline
 * Shall print
 * [1]
 * @throws InterruptedException
 */
@Test
public void limitStream() throws InterruptedException {
    List<Integer> list = Arrays.asList(1, 2, 3, 1, 4, 2, 3)
                               .stream()
                               .limit(1)
                               .collect(toList());
    System.out.println(list);
}

2
@Vitalii Fedorenko คำตอบstackoverflow.com/a/18165855/1562662ดีกว่า
Chacko Mathew

2

Guava จัดให้มีonlyElement Collectorแต่ใช้เฉพาะเมื่อคุณคาดหวังว่าคอลเลกชันมีองค์ประกอบเดียวเท่านั้น

Collection<String> stringCollection = ...;
String string = collection.stream().collect(MoreCollectors.onlyElement())

findFirstหากคุณไม่แน่ใจว่าหลายองค์ประกอบที่มีการใช้งาน

Optional<String> optionalString = collection.stream().findFirst();

1

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

Collection<String> getStrings();

และหลังจากเรียกใช้คุณต้องมีองค์ประกอบแรกคุณสามารถทำสิ่งนี้ได้:

List<String> listString = (List) getStrings();
String firstElement = (listString.isEmpty() ? null : listString.get(0));

0

หากคุณรู้ว่าคอลเล็กชันนั้นเป็นคิวคุณสามารถส่งคอลเล็กชันไปที่คิวและรับได้ง่าย

มีโครงสร้างหลายอย่างที่คุณสามารถใช้เพื่อรับออเดอร์ได้ แต่คุณจะต้องทำการแคสต์มัน


ฉันเห็นด้วยถ้าคุณไม่ต้องการทำซ้ำอย่าใช้คอลเล็กชัน ใช้อินเทอร์เฟซเฉพาะเจาะจงอื่น ๆ แทน
Adeel Ansari

1
ฉันสงสัยว่า ... สมมติว่าข้อมูลจริงที่แท้จริงคือ SortedSet ดังนั้นลำดับจึงสมเหตุสมผล แต่คุณมีมุมมองแบบสะสมเท่านั้น (ด้วยเหตุผลที่ไม่โง่เลยสมมุติว่า); ถ้าคุณส่งคอลเล็กชันไปที่รายการ, คิว, ฯลฯ และลองรับ / สำรวจ / ฯลฯ ภัยพิบัติจะเกิดขึ้นไหม ในทำนองเดียวกันถ้าโครงสร้างพื้นฐานเป็นรายการเป็นต้นไปเรื่อย ๆ
Carl

@ Cal - ฉันยังไม่ได้ลอง แต่ถ้าคุณโยนคอลเลกชันเป็นประเภทที่แตกต่างจากเดิมคุณควรได้รับข้อผิดพลาด แต่ฉันไม่ได้ลองดังนั้นฉันอาจจะผิด
James Black

0

มันขึ้นอยู่กับการใช้งานที่คุณใช้ไม่ว่าจะเป็นรายการที่เชื่อมโยงรายการหรือการใช้งานชุดอื่น ๆ

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

ถ้ามันเป็นการใช้งานของรายการมันเป็นเรื่องง่ายโดยการกำหนดหมายเลขดัชนี


0

วิธีการทำงาน:

public static <T> Optional<T> findFirst(List<T> result) {
    return Optional.ofNullable(result)
            .map(List::stream)
            .flatMap(Stream::findFirst);
}

ข้อมูลโค้ดข้างต้นสงวนจาก NullPointerException และ IndexOutOfBoundsException


1
ตัวเลือกของคุณList<T>ไม่เป็นไปตามเงื่อนไขที่ควรใช้กับ a Collection<String>แต่แน่นอนว่าสามารถแก้ไขได้โดยใช้Collection<T>กับการเปลี่ยนแปลงเพิ่มเติม: .map(Collection::stream).
Scratte

-2

คุณสามารถทำได้:

String strz[] = strs.toArray(String[strs.size()]);
String theFirstOne = strz[0];

javadoc สำหรับการเก็บรวบรวมให้คำสั่งการเขียนองค์ประกอบของอาเรย์ดังต่อไปนี้:

หากคอลเลกชันนี้ทำให้การรับประกันใด ๆ เป็นสิ่งที่สั่งซื้อองค์ประกอบของมันจะถูกส่งกลับโดย iterator ของมันวิธีการนี้จะต้องกลับองค์ประกอบในลำดับเดียวกัน


2
สิ่งนี้จะสร้างอาร์เรย์ของสตริงใหม่ซึ่งมีราคาแพงกว่าการสร้างตัววนซ้ำ
Jim Ferrans

ใช่ฉันคิดเกี่ยวกับสิ่งนั้นหลังจากที่ฉันโพสต์สิ่งนี้ โดยไม่คำนึงถึงวิธีการที่ใช้การสั่งซื้อขึ้นอยู่กับการใช้งานพื้นฐานของคอลเลกชัน "First" จากนั้นกลายเป็นคำที่เกี่ยวข้อง อย่างไรก็ตามวิธีการทำซ้ำ () ในการทำมันอาจจะดีกว่าในกรณีส่วนใหญ่
Andy Gherna

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