A 'for' วนซ้ำเพื่อวนซ้ำ enum ใน Java


876

ฉันมีenumJava สำหรับทิศทางสำคัญ & กลาง:

public enum Direction {
   NORTH,
   NORTHEAST,
   EAST,
   SOUTHEAST,
   SOUTH,
   SOUTHWEST,
   WEST,
   NORTHWEST
}

ฉันจะเขียนforลูปที่วนซ้ำผ่านแต่ละenumค่าเหล่านี้ได้อย่างไร


คำตอบ:


1400

.values()

คุณสามารถเรียกvalues()วิธีการใน enum ของคุณ

for (Direction dir : Direction.values()) {
  // do what you want
}

นี้values()วิธีการที่ประกาศโดยปริยายคอมไพเลอร์ ดังนั้นจึงไม่ปรากฏในEnumเอกสาร


43
ทำไมค่าวิธีนี้()ไม่อยู่ในรายการที่นี่ภายใต้ java.lang.enum
jacktrades

80
@jacktrades: มันเป็นวิธีโดยนัยที่มีอยู่ในคอมไพเลอร์เท่านั้น ดังนั้นคลาสพื้นฐานไม่สามารถประกาศเมธอดที่มีชื่อเดียวกันดังนั้นจึงไม่ได้รวมอยู่ใน Javadocs ที่สร้างขึ้นโดยอัตโนมัติ docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
Torben

4
มันถูกกล่าวถึงในเอกสารvalueOf ()
greg7gkb

129

ค่าคงที่ทั้งหมดของชนิด enum สามารถรับได้โดยการเรียกpublic static T[] values()เมธอดimplicit ของชนิดนั้น:

 for (Direction d : Direction.values()) {
     System.out.println(d);
 }

@ RAnders00 จริง แต่ก็ยังคงคำตอบนั้นถูกต้องและรูปแบบก็ไม่สำคัญ (อย่างน้อยสำหรับฉัน)
dARKpRINCE

อะไร#ทำอย่างไร
YoTengoUnLCD

@YoTengoUnLCD โดยทั่วไปจะบอกว่าค่า () เป็นส่วนหนึ่งของวัตถุ Enum เช่นEnum#values()=Enum.values()
ปอตไลต์

อืมฉันขอโทษฉันไม่ปฏิบัติตามมันเหมือนกับการใช้.(เสมอหรือไม่)?
YoTengoUnLCD

3
@YoTengoUnLCD hashtag เป็นไวยากรณ์ JavaDoc ไม่ใช่รหัส Java
Jeff G

62

คุณสามารถทำได้ดังนี้:

for (Direction direction : EnumSet.allOf(Direction.class)) {
  // do stuff
}

1
ให้คุณนำเข้า java.util.EnumSet
Nate

8
Super มีประโยชน์สำหรับ Java8 foreach loeach EnumSet.allOf (Enum.class) .forEach (blah -> method (blah))
Hiro2k

1
@ Hiro2k คุณสามารถทำได้Arrays.stream(Enum.values()).forEach(...)- สตรีมจะต่อเนื่องกัน
RAnders00

1
@schatten ดีมันเป็นแทนset arrayไม่ใช่ "ดีกว่า" ถึงแม้ว่ามันจะอธิบายค่า enum ที่ดีกว่าในความคิดของฉันเพราะจากคำจำกัดความของชุดค่าในชุดไม่สามารถทำซ้ำได้ (เช่นใน enum) ในขณะที่ค่าในอาร์เรย์สามารถเป็นได้
Jezor

2
@Jezor มันเป็นตัวเลือกที่ดีกว่าเมื่อคุณต้องการ enums ที่รวดเร็วมาก ๆ อย่างเช่นค่าสถานะบิต แต่ดูเหมือนว่าซับซ้อนเกินไปสำหรับการทำซ้ำง่าย ๆ
Schatten

44

ลำธาร

ก่อนหน้าจาวา 8

for (Direction dir : Direction.values()) {
            System.out.println(dir);
}

Java 8

เราสามารถใช้แลมบ์ดาและสตรีม ( บทช่วยสอน ):

Stream.of(Direction.values()).forEachOrdered(System.out::println);

ทำไมforEachOrderedและไม่ใช่forEachกับสตรีม

พฤติกรรมของforEachคือ nondeterministic อย่างชัดเจนโดยที่การforEachOrderedดำเนินการสำหรับแต่ละองค์ประกอบของสตรีมนี้ในลำดับการเผชิญหน้าของสตรีมหากสตรีมมีลำดับการเผชิญหน้าที่กำหนดไว้ ดังนั้นforEachไม่รับประกันว่าคำสั่งจะถูกเก็บไว้

นอกจากนี้เมื่อทำงานกับสตรีม (โดยเฉพาะอย่างยิ่งคู่ขนาน) โปรดคำนึงถึงธรรมชาติของสตรีม ตามเอกสาร :

ผลลัพธ์ไปป์ไลน์ของสตรีมอาจไม่ได้กำหนดไว้หรือไม่ถูกต้องหากพารามิเตอร์พฤติกรรมไปยังการดำเนินการของสตรีมนั้นเป็นของรัฐ แลมบ์ดาแบบรัฐเป็นสิ่งที่ผลลัพธ์ขึ้นอยู่กับสถานะใด ๆ ซึ่งอาจเปลี่ยนแปลงได้ในระหว่างการดำเนินการไปป์ไลน์

Set<Integer> seen = Collections.synchronizedSet(new HashSet<>());
stream.parallel().map(e -> { if (seen.add(e)) return 0; else return e; })...

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

ผลข้างเคียงในพารามิเตอร์พฤติกรรมในการทำงานของการสตรีมนั้นโดยทั่วไปหมดกำลังใจเพราะพวกเขามักจะนำไปสู่การละเมิดความต้องการไร้สัญชาติโดยไม่รู้ตัวรวมทั้งอันตรายจากความปลอดภัยของด้ายอื่น ๆ

ลำธารอาจมีหรือไม่มีคำสั่งเผชิญหน้า การสตรีมนั้นมีลำดับการเผชิญหน้าหรือไม่นั้นขึ้นอยู่กับแหล่งที่มาและการดำเนินการระดับกลาง


เช่นเดียวกับการดำเนินงานสตรีมทั้งหมดจะตระหนักถึงความไร้สัญชาติด้ายและผลข้างเคียงข้อ จำกัดdocs.oracle.com/javase/8/docs/api/java/util/stream/... ตัวเลือกการวนซ้ำ 2 ตัวนี้มีความแตกต่างอย่างมากในเรื่องนี้
buzz3791


19

หากคุณไม่สนใจคำสั่งนี้ควรใช้งานได้:

Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
    // do stuff
}

2
ให้คุณนำเข้า java.util.EnumSet และ java.util.Set
Nate

4
จากเอกสารEnumSet : iterator ที่ส่งกลับโดยวิธี iterator ลัดเลาะองค์ประกอบในของพวกเขาเพื่อธรรมชาติ (ลำดับที่ค่าคงที่ enum จะประกาศ) Enum.values()การค้ำประกันนี้ว่าคำสั่งของย้ำตรงกับคำสั่งซื้อที่ส่งกลับโดย
Jeff G


5

Java8

Stream.of(Direction.values()).forEach(System.out::println);

จาก Java5 +

for ( Direction d: Direction.values()){
 System.out.println(d);
}

1
โอ้ขอโทษ. ฉันเพิ่งรู้ว่า akhil_mittal โพสต์คำตอบเดียวกันแล้ว
Raghu K Nair

ฉันควรใช้ Stream.of (o) .forEach เมื่อใดและเพราะเหตุใด ห่วงสำหรับดูเหมือนว่าอ่านได้มากขึ้น
Jeremy

ไม่ใช่ถ้าคุณคุ้นเคยกับการเขียนโปรแกรมที่ใช้งานได้
Alexis Dufrenoy

5

ลองใช้ a สำหรับแต่ละอัน

for ( Direction direction : Direction.values()){
  System.out.println(direction.toString());
}

4

วิธีการเพิ่มเติมใน java 8:

ใช้EnumSetกับforEach

EnumSet.allOf(Direction.class).forEach(...);

ใช้Arrays.asListกับforEach

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