我在Java中有一个用于表示基本方向和中间方向的enum
:
public enum Direction {
NORTH,
NORTHEAST,
EAST,
SOUTHEAST,
SOUTH,
SOUTHWEST,
WEST,
NORTHWEST
}
我该如何编写一个for
循环来遍历这些enum
值?
可以通过调用该类型的隐式 public static T[] values()
方法来获取枚举类型的所有常量:
for (Direction d : Direction.values()) {
System.out.println(d);
}
#
是什么作用? - YoTengoUnLCDEnum#values()
= Enum.values()
。 - Spotlight.
(总是?)一样吗? - YoTengoUnLCDfor (Direction direction : EnumSet.allOf(Direction.class)) {
// do stuff
}
Arrays.stream(Enum.values()).forEach(...)
- 这个流将是顺序的。 - randersEnum.values()
更好吗? - schattenset
而不是array
。它并不是“更好”,尽管在我看来它更好地描述了枚举值,因为从集合的定义来看,集合中的值不能重复(就像枚举一样),而数组中的值可以重复。 - Jezorfor (Direction dir : Direction.values()) {
System.out.println(dir);
}
我们还可以利用lambda表达式和流(教程):
Stream.of(Direction.values()).forEachOrdered(System.out::println);
为什么使用流时要使用forEachOrdered
而不是forEach
?
forEach
的行为是明确非确定性的,而forEachOrdered
会为流中的每个元素执行一个操作,如果流具有定义的遇见顺序,则按照该顺序进行。因此,forEach
不能保证顺序被保留。
此外,当使用流(特别是并行流)时,请牢记流的本质。根据文档:
如果流操作的行为参数是有状态的,则流管道结果可能是不确定或不正确的。有状态的lambda是其结果依赖于在执行流管道期间可能更改的任何状态的lambda。
Set<Integer> seen = Collections.synchronizedSet(new HashSet<>());
stream.parallel().map(e -> { if (seen.add(e)) return 0; else return e; })...
如果在并行执行映射操作,则由于线程调度差异,相同输入的结果可能会因运行而异,而使用无状态 lambda 表达式将始终产生相同的结果。
通常不建议在流操作的行为参数中引入副作用,因为它们经常会导致无意识地违反无状态要求以及其他线程安全隐患。
流可以有或没有定义的遍历顺序。是否有遍历顺序取决于源和中间操作。
如果您不关心顺序,这个方法应该可以:
Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
// do stuff
}
EnumSet
文档所述:iterator
方法返回的迭代器以枚举类型常量被声明的 自然顺序 遍历元素。这保证了迭代的顺序与 Enum.values()
返回的顺序相匹配。 - Jeff GJava8
Stream.of(Direction.values()).forEach(System.out::println);
从Java5+开始
for ( Direction d: Direction.values()){
System.out.println(d);
}
Java 8中的更多方法:
forEach
中使用EnumSet
EnumSet.allOf(Direction.class).forEach(...);
Arrays.asList
和forEach
的时候进行操作Arrays.asList(Direction.values()).forEach(...);
场景:假设我们有一定数量的卡片类型。每种卡片类型都有相关费用和加入奖励。
package enumPkg;
public enum CardTypes {
//Each enum is object
DEBIT(10,20),
CREDIT(0,10),
CRYPTO(5,30);
//Object properties
int fees;
int bonus;
//Initilize object using constructor
CardTypes(int fee, int bonus){
this.fees = fee;
this.bonus = bonus;
}
//access object property
public int getFees(){
return this.fees;
}
public int getBonus(){
return this.bonus;
}
}
现在要在其他类中访问枚举。按照以下步骤进行Java操作:
package enumPkg;
public class EnumClass {
public static void main(String[] args) {
CardTypes cardType = CardTypes.CREDIT; //Each enum element is public static final, when accessed returns a object
System.out.println(cardType);
System.out.println("Debit card fees : "+CardTypes.DEBIT.getFees());
System.out.println("Debit card bonus : "+CardTypes.DEBIT.getBonus());
CardTypes[] cardTypes = CardTypes.values();//return array of CardTypes i.e all enum elements we have defined
for (CardTypes type : CardTypes.values()) {
System.out.println(type); //particular enum object
System.out.println(type.ordinal()); //return enum position
System.out.println("Bonus : "+type.getBonus()); //return enum object property: Bonus
System.out.println("Fees : "+type.getFees());//return enum object property: Fees
}
}
}
输出:
CREDIT
Debit card fees : 10
Debit card bonus : 20
DEBIT
0
Bonus : 20
Fees : 10
CREDIT
1
Bonus : 10
Fees : 0
CRYPTO
2
Bonus : 30
Fees : 5
Stream.of(Direction.values()).filter(name -> !name.toString().startsWith("S")).forEach(System.out::println);