Common usage of enumeration classes (A Guide to Java Enums)


Java 5 introduces enumeration classes, please refer to the official documentation for details .

In a word, what is an enumeration class

pure enum value

public enum PizzaStatus {
    
    
    ORDERED,
    READY, 
    DELIVERED; 
}

Enum value added attribute

public enum Distance {
    
    
    KILOMETER("km", 1000), 
    MILE("miles", 1609.34),
    METER("meters", 1), 
    INCH("inches", 0.0254),
    CENTIMETER("cm", 0.01), 
    MILLIMETER("mm", 0.001);

    private String unit;
    private final double meters;

    private Distance(String unit, double meters) {
    
    
        this.unit = unit;
        this.meters = meters;
    }

    // standard getters and setters
}

Fields, Methods and Constructors in Enums (enum values ​​can also provide methods)

@Data
public class Pizza {
    
    
    public enum PizzaStatus {
    
    
        ORDERED(5) {
    
    
            @Override
            public boolean isOrdered() {
    
    
                return true;
            }
        }, READY(2) {
    
    
            @Override
            public boolean isReady() {
    
    
                return true;
            }
        }, DELIVERED(0) {
    
    
            @Override
            public boolean isDelivered() {
    
    
                return true;
            }
        };

        private int timeToDelivery;

        PizzaStatus(int timeToDelivery) {
    
    
            this.timeToDelivery = timeToDelivery;
        }

        // 下单
        public boolean isOrdered() {
    
    
            return false;
        }

        // 准备
        public boolean isReady() {
    
    
            return false;
        }

        // 交付
        public boolean isDelivered() {
    
    
            return false;
        }

        public int getTimeToDelivery() {
    
    
            return timeToDelivery;
        }
    }

    private PizzaStatus status;

    public boolean isDeliverable() {
    
    
        return this.status.isReady();
    }

    public void printTimeToDeliver() {
    
    
        System.out.println("Time to delivery is " + this.getStatus().getTimeToDelivery());
    }
}

Strategy Pattern (methods can be provided based on the enumeration value, here you can expand the strategy design pattern)

public enum PizzaDeliveryStrategy {
    
    
    EXPRESS {
    
    
        @Override
        public void deliver(Pizza pz) {
    
    
            System.out.println("Pizza will be delivered in express mode");
        }
    }, NORMAL {
    
    
        @Override
        public void deliver(Pizza pz) {
    
    
            System.out.println("Pizza will be delivered in normal mode");
        }
    };
    public abstract void deliver(Pizza pz);
}
    public static void main(String[] args) {
    
    
        Pizza testPz = new Pizza();
        testPz.setStatus(Pizza.PizzaStatus.READY); // true
        testPz.printTimeToDeliver(); // Time to delivery is 2
    }

Custom Enum Methods (tell us that the enumeration class can be used inside the class, as seen above)

@Data
public class Pizza {
    
    
    private PizzaStatus status;
    public enum PizzaStatus {
    
    
        ORDERED,
        READY,
        DELIVERED;
    }

    public boolean isDeliverable() {
    
    
        if (getStatus() == PizzaStatus.READY) {
    
    
            return true;
        }
        return false;
    }
}

Using Enum Types in Switch Statements (classic usage of switch+enum combination)

public int getDeliveryTimeInDays() {
    
    
    switch (status) {
    
    
        case ORDERED: return 5;
        case READY: return 2;
        case DELIVERED: return 0;
    }
    return 0;
}

Comparing Enum Types Using “==” Operator (for enumeration class comparison ==)

the “==” operator provides compile-time and run-time safety.

run-time safety

if(testPz.getStatus().equals(Pizza.PizzaStatus.DELIVERED));null 会报 NullPointerException

if(testPz.getStatus() == Pizza.PizzaStatus.DELIVERED);Either value can be null and we won't get a NullPointerException

compile-time safety

PizzaStatus.DELIVERED.equals(PizzaStatus2.ORDERED)    ← 编译不会报错,会返回false

PizzaStatus.DELIVERED == PizzaStatus2.ORDERED    ← 编译会报错

How to check if an enumeration value exists

How to judge whether an enumeration value exists (Check if an Enum Value Exists in Java)

Singleton Pattern

public enum PizzaDeliverySystemConfiguration {
    
    
    INSTANCE;
    
    PizzaDeliverySystemConfiguration() {
    
    
        // Initialization configuration which involves overriding defaults like delivery strategy
        // 初始化配置,包括覆盖默认值,如交付策略
    }
    
    private PizzaDeliveryStrategy deliveryStrategy = PizzaDeliveryStrategy.NORMAL;
    
    public static PizzaDeliverySystemConfiguration getInstance() {
    
    
        return INSTANCE;
    }
    
    public PizzaDeliveryStrategy getDeliveryStrategy() {
    
    
        return deliveryStrategy;
    }
}

Add the following method to the Pizza class

public void deliver() {
    
    
    if (isDeliverable()) {
    
    
        PizzaDeliverySystemConfiguration.getInstance().getDeliveryStrategy().deliver(this);
        this.setStatus(PizzaStatus.DELIVERED);
    }
}
public static void main(String[] args) {
    
    
    Pizza pz = new Pizza();
    pz.setStatus(Pizza.PizzaStatus.READY);
    pz.deliver(); // Pizza will be delivered in normal mode 
    System.out.println(pz.getStatus() == Pizza.PizzaStatus.DELIVERED); // true
}

EnumSet

More efficient compared to HashSet

@Data
public class Pizza {
    
    
    private static EnumSet<PizzaStatus> undeliveredPizzaStatuses = EnumSet.of(PizzaStatus.ORDERED, PizzaStatus.READY);

    private PizzaStatus status;

    public enum PizzaStatus {
    
    
        ORDERED(5) {
    
    
            @Override
            public boolean isOrdered() {
    
    
                return true;
            }
        }, READY(2) {
    
    
            @Override
            public boolean isReady() {
    
    
                return true;
            }
        }, DELIVERED(0) {
    
    
            @Override
            public boolean isDelivered() {
    
    
                return true;
            }
        };

        private int timeToDelivery;

        PizzaStatus(int timeToDelivery) {
    
    
            this.timeToDelivery = timeToDelivery;
        }

        // 下单
        public boolean isOrdered() {
    
    
            return false;
        }

        // 准备
        public boolean isReady() {
    
    
            return false;
        }

        // 交付
        public boolean isDelivered() {
    
    
            return false;
        }

        public int getTimeToDelivery() {
    
    
            return timeToDelivery;
        }
    }

    public boolean isDeliverable() {
    
    
        return this.status.isReady();
    }

    public void printTimeToDeliver() {
    
    
        System.out.println("Time to delivery is " + this.getStatus().getTimeToDelivery() + " days");
    }

    public static List<Pizza> getAllUndeliveredPizzas(List<Pizza> input) {
    
    
        return input.stream().filter((s) -> undeliveredPizzaStatuses.contains(s.getStatus())).collect(Collectors.toList());
    }
}
public static void main(String[] args) {
    
    
    List<Pizza> pzList = new ArrayList<>();
    Pizza pz1 = new Pizza();
    pz1.setStatus(Pizza.PizzaStatus.DELIVERED);
    Pizza pz2 = new Pizza();
    pz2.setStatus(Pizza.PizzaStatus.ORDERED);
    Pizza pz3 = new Pizza();
    pz3.setStatus(Pizza.PizzaStatus.ORDERED);
    Pizza pz4 = new Pizza();
    pz4.setStatus(Pizza.PizzaStatus.READY);
    pzList.add(pz1);
    pzList.add(pz2);
    pzList.add(pz3);
    pzList.add(pz4);
    
    List<Pizza> undeliveredPzs = Pizza.getAllUndeliveredPizzas(pzList);
    System.out.println(undeliveredPzs.size()); // 3
}

EnumMap

EnumMap is an efficient and compact implementation compared to the corresponding HashMap, internally represented as an array.
EnumMap(A Guide to EnumMap)

public static EnumMap<PizzaStatus, List<Pizza>> groupPizzaByStatus(List<Pizza> pizzaList) {
    
    
    EnumMap<PizzaStatus, List<Pizza>> pzByStatus = new EnumMap<PizzaStatus, List<Pizza>>(PizzaStatus.class);
    for (Pizza pz : pizzaList) {
    
    
        PizzaStatus status = pz.getStatus();
        if (pzByStatus.containsKey(status)) {
    
    
            pzByStatus.get(status).add(pz);
        } else {
    
    
            List<Pizza> newPzList = new ArrayList<Pizza>();
            newPzList.add(pz);
            pzByStatus.put(status, newPzList);
        }
    }
    return pzByStatus;
}

Java 8 and Enums

public static List<Pizza> getAllUndeliveredPizzas(List<Pizza> input) {
    
    
    return input.stream().filter((s) -> undeliveredPizzaStatuses.contains(s.getStatus())).collect(Collectors.toList());
}
public static EnumMap<PizzaStatus, List<Pizza>> groupPizzaByStatus2(List<Pizza> pzList) {
    
    
    EnumMap<PizzaStatus, List<Pizza>> map = pzList.stream().filter(a -> a != null && a.getStatus() != null).collect(Collectors.groupingBy(Pizza::getStatus, () -> new EnumMap<>(PizzaStatus.class), Collectors.toList()));
    return map;
}
public static Map<PizzaStatus, List<Pizza>> groupPizzaByStatus3(List<Pizza> pizzaList) {
    
    
    Map<PizzaStatus, List<Pizza>> collect = pizzaList.stream().filter(a -> a != null && a.getStatus() != null).collect(Collectors.groupingBy(Pizza::getStatus));
    return collect;
}
public static void main(String[] args) {
    
    
    List<Pizza> pzList = new ArrayList<>();
    Pizza pz1 = new Pizza();
    pz1.setStatus(Pizza.PizzaStatus.DELIVERED);
    Pizza pz2 = new Pizza();
    pz2.setStatus(Pizza.PizzaStatus.ORDERED);
    Pizza pz3 = new Pizza();
    pz3.setStatus(Pizza.PizzaStatus.ORDERED);
    Pizza pz4 = new Pizza();
    pz4.setStatus(Pizza.PizzaStatus.READY);
    pzList.add(pz1);
    pzList.add(pz2);
    pzList.add(pz3);
    pzList.add(pz4);
    
    EnumMap<Pizza.PizzaStatus, List<Pizza>> map = Pizza.groupPizzaByStatus(pzList);
    System.out.println(map);
    //{ORDERED=[Pizza(status=ORDERED), Pizza(status=ORDERED)], READY=[Pizza(status=READY)], DELIVERED=[Pizza(status=DELIVERED)]}
    
    EnumMap<Pizza.PizzaStatus, List<Pizza>> map2 = Pizza.groupPizzaByStatus2(pzList);
    System.out.println(map2);
    // {ORDERED=[Pizza(status=ORDERED), Pizza(status=ORDERED)], READY=[Pizza(status=READY)], DELIVERED=[Pizza(status=DELIVERED)]}
    
    Map<Pizza.PizzaStatus, List<Pizza>> map3 = Pizza.groupPizzaByStatus3(pzList);
    System.out.println(map3);
    // {READY=[Pizza(status=READY)], ORDERED=[Pizza(status=ORDERED), Pizza(status=ORDERED)], DELIVERED=[Pizza(status=DELIVERED)]}
}

JSON Representation of Enum

Further Reading : Serialization and deserialization of enumeration classes using Jackson (How To Serialize and Deserialize Enums with Jackson)

@Data
public class Pizza {
    
    
    private PizzaStatus status;

    @JsonFormat(shape = JsonFormat.Shape.OBJECT)
    public enum PizzaStatus {
    
    
        ORDERED(5) {
    
    
            @Override
            public boolean isOrdered() {
    
    
                return true;
            }
        }, READY(2) {
    
    
            @Override
            public boolean isReady() {
    
    
                return true;
            }
        }, DELIVERED(0) {
    
    
            @Override
            public boolean isDelivered() {
    
    
                return true;
            }
        };

        private int timeToDelivery;

        PizzaStatus(int timeToDelivery) {
    
    
            this.timeToDelivery = timeToDelivery;
        }

        // 下单
        public boolean isOrdered() {
    
    
            return false;
        }

        // 准备
        public boolean isReady() {
    
    
            return false;
        }

        // 交付
        public boolean isDelivered() {
    
    
            return false;
        }

        @JsonProperty("timeToDelivery")
        public int getTimeToDelivery() {
    
    
            return timeToDelivery;
        }
    }

    public boolean isDeliverable() {
    
    
        return this.status.isReady();
    }
}
Pizza pz = new Pizza();
pz.setStatus(Pizza.PizzaStatus.READY);

ObjectMapper objectMapper = new ObjectMapper();
String s = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(pz);
System.out.println(s);
{
    
    
  "status" : {
    
    
    "ready" : true,
    "ordered" : false,
    "delivered" : false,
    "timeToDelivery" : 2
  },
  "deliverable" : true
}

Application of inheritance in enumeration class

Further Reading : Application of Inheritance in Enumeration Classes (Extending Enums in Java)

-------------------------------------------------- --------------------------- Reading notes are taken from the article: A Guide to Java Enums
------------- -------------------------------------------------- -------------- Reading notes are taken from the article: Enum in Java

Summarize:

  • enum is the keyword

  • Enumeration classes do not support inheritance

  • Enum can implement interface

  • Enum constructors are always private. An instance of an enum cannot be created using the new operator

  • An enum constant is implicitly static final, but its variables can still be changed.

  • We can define methods in enum and enum fields can override them too.

  • We can declare abstract method in java enum, then all enum fields must implement abstract method

  • It is recommended that enumerations use == for comparison

Guess you like

Origin blog.csdn.net/weixin_37646636/article/details/132048657