2013-03-13 39 views
20

Tôi có enum như:Làm cách nào để truy xuất tên Enum bằng id?

public enum EnumStatus { 

    PASSED(40L, "Has Passed"), 
    AVERAGE(60L, "Has Average Marks"), 
    GOOD(80L, "Has Good Marks"); 

    private java.lang.String name; 

    private java.lang.Long id; 

    EnumStatus(Long id, java.lang.String name) { 
     this.name = name; 
     this.id = id; 
    } 

    public java.lang.String getName() { 
     return name; 
    } 

    public java.lang.Long getId() { 
     return id; 
    } 
} 

Tôi có để có được những tên Enum (PASSED, AVERAGE, GOOD) chỉ sử dụng id (40,60, 80). Tôi phải làm nó như thế nào?

Trả lời

39

Tạo phương pháp tĩnh trong enum của bạn tìm kiếm trong values (phương thức/thành viên ngầm, không biết chính xác nó là gì) và trả về giá trị tương ứng. Đối với các trường hợp mà phương pháp không thể tìm thấy giá trị phù hợp, bạn nên tạo một mục nhập đặc biệt, ví dụ: UNKNOWN, bạn có thể quay lại. Bằng cách này, bạn không phải trả lại null, mà luôn luôn là một ý tưởng tồi.

public static EnumStatus getById(Long id) { 
    for(EnumStatus e : values()) { 
     if(e.id.equals(id)) return e; 
    } 
    return UNKNOWN; 
} 

Btw - mã của bạn có vẻ sai. Khung sau GOOD dường như không thuộc về đó.

+5

IMHO, bạn không nên trả về null trong loại phương pháp này của Enum. Một RuntimeException (tức là IllegalArgumentException) sẽ tốt hơn. – jalopaba

+0

Tôi nghĩ rằng bạn đang đúng, 'null' là khá xấu xí. Tôi cũng là một fan hâm mộ của các giá trị giả để enum sẽ chứa một giá trị bổ sung 'UNKNOWN' với các giá trị mà không phù hợp với bất cứ điều gì. Tất nhiên điều này phụ thuộc vào môi trường của bạn. – Joshua

8

Điều này có thể được thực hiện bằng cách sử dụng bản đồ tĩnh cùng với một initializer tĩnh:

public enum EnumStatus { 

    PASSED(40L, "Has Passed"), 
    AVERAGE(60L, "Has Average Marks"), 
    GOOD(80L, "Has Good Marks"); 

    private static final Map<Long, EnumStatus> byId = new HashMap<Long, EnumStatus>(); 
    static { 
     for (EnumStatus e : EnumStatus.values()) { 
      if (byId.put(e.getId(), e) != null) { 
       throw new IllegalArgumentException("duplicate id: " + e.getId()); 
      } 
     } 
    } 

    public static EnumStatus getById(Long id) { 
     return byId.get(id); 
    } 

    // original code follows 

    private java.lang.String name; 

    private java.lang.Long id; 

    EnumStatus(Long id, java.lang.String name) { 
     this.name = name; 
     this.id = id; 
    } 

    public java.lang.String getName() { 
     return name; 
    } 

    public java.lang.Long getId() { 
     return id; 
    } 

} 

này sẽ cung cấp một phương pháp O(1)getById(), và sẽ tự động phát hiện nếu bạn vô tình có id trùng lặp trong enum.

+0

Tôi thích ý tưởng của bạn bằng cách sử dụng bản đồ cho thời gian truy cập liên tục. Đối với enums lớn chắc chắn là một điều tốt. Ngoài ra kiểm tra giá trị trả lại của đặt là thực sự mát mẻ. – Joshua

+0

Về O (1) đối với loại phương pháp này, nếu id như vậy và thứ tự bên trong có liên quan bởi một phương trình, bạn có thể tận dụng mảng tĩnh được tạo ra để lấy O (1) (xem câu trả lời của tôi). – jalopaba

+0

@NPE Tôi thực sự thích ý tưởng của một bản đồ tĩnh và kiểm tra các bất biến mà mỗi hằng số có một id.Thanks duy nhất. – Geek

0

lặp qua tất cả các giá trị và so sánh Id

for (EnumStatus enumStatus : EnumStatus.values()) { 
    if (..) {..} 
} 
1

Thêm một phương pháp trong Enum của bạn và làm cho nó bằng cách thông qua id.

public static ArrayList<EnumStatus> getEnumStatusById(ArrayList<Long> idList) { 
    ArrayList<EnumStatus> listById = new ArrayList(); 
    for(EnumStatus es: EnumStatus.values()) { 
     if(idList.contains(es.getId())) { 
      listById.add(es); 
     } 
    } 
    return listById; 
} 
2

Bạn thực hiện công việc này như sau:

public static String fromId(long id) { 
     for (EnumStatus es : EnumStatus.values()) { 
      if (es.id.equals(id)) { 
       return es.getName(); 
      } 
     } 
     throw new IllegalArgumentException(); 
} 
1
public static EnumStatus getById(long id) 
{ 
    for (EnumStatus e : EnumStatus.values()) 
    { 
    if (id == e.getId()) return e; 
    } 
    throw new IllegalArgumentException("oh no"); 
} 
0

Đôi khi thứ tự của enum có mối quan hệ rõ ràng với loại này của id, cho phép một cách gọn gàng để có được O (1) trong các phương pháp. Trong mã của bạn, rõ ràng là

EnumStatus.X = 40 + 20 * ordinal,

để bạn có thể tận dụng static array that is generated under the hoods.

public static EnumStatus fromId(Long id) { 
    int index = (id - 40L)/20L; 
    return values()[index]; 
} 
+1

Tôi nghĩ rằng điều này nên ít nhất là xác nhận rằng giả định là chính xác. Nếu không, điều này có thể dễ dàng dẫn đến mã mong manh. – NPE

0

Xác định hợp đồng

/** 
* Contract that will allow Types with id to have generic implementation. 
*/ 
public interface IdentifierType<T> { 
    T getId(); 
} 

Áp dụng hợp đồng

public enum EntityType implements IdentifierType<Integer> { 
    ENTITY1(1, "ONE), ENTITY2(2, "TWO"); 

    private Integer id; 
    private String name; 

    private EntityType(int id, String name) { 
    this.id = id; 
    this.name = name; 
    } 

    public static EntityType valueOf(Integer id) { 
    return EnumHelper.INSTANCE.valueOf(id, EntityType.values()); 
    } 

    @Override 
    public Integer getId() { 
    return id; 
    } 
} 

Helper/util

public enum EnumHelper { 
    INSTANCE; 

    /** 
    * This will return {@link Enum} constant out of provided {@link Enum} values with the specified id. 
    * @param id the id of the constant to return. 
    * @param values the {@link Enum} constants of specified type. 
    * @return the {@link Enum} constant. 
    */ 
    public <T extends IdentifierType<S>, S> T valueOf(S id, T[] values) { 
    if (!values[0].getClass().isEnum()) { 
     throw new IllegalArgumentException("Values provided to scan is not an Enum"); 
    } 

    T type = null; 

    for (int i = 0; i < values.length && type == null; i++) { 
     if (values[i].getId().equals(id)) { 
      type = values[i]; 
     } 
    } 

    return type; 
    } 
} 
Các vấn đề liên quan