2013-03-12 42 views
16

Tôi muốn nhận được một enum cụ thể dựa trên giá trị trường của nó.Tôi có thể nhận được một enum dựa trên giá trị của lĩnh vực của nó?

Enum:

public enum CrimeCategory { 
    ASBO ("Anti Social Behaviour"), 
    BURG ("Burglary"), 
    CRIMDAM ("Criminal Damage And Arson"), 
    DRUGS ("Drugs"), 
    OTHTHEFT ("Other Theft"), 
    PUPDISOR ("Public Disorder And Weapons"), 
    ROBBERY ("Robbery"), 
    SHOPLIF ("Shoplifting"), 
    VEHICLE ("Vehicle Crime"), 
    VIOLENT ("Violent Crime"), 
    OTHER ("Other Crime"); 

    private String category; 


    private CrimeCategory (String category) { 
     this.category = category; 
    } 

    public String returnString() { 
     return category; 
    } 
} 


Bắt một Enum mới:

aStringRecivedFromJson = "Anti Social Behaviour" 
CrimeCategory crimeCategoryEnum; 
crimeCategoryEnum = CrimeCategory.valueOf(aStringRecivedFromJson); 

Tôi đã cố gắng để tìm ra một cách để ở trên mang lại một một enum để nó có thể được thông qua được lưu trữ trong một số HashMap với thông tin Crime khác.

Kết quả dự kiến: ASBO

+2

toString() sẽ cho bạn biểu diễn Chuỗi của Enum trừ khi bạn ghi đè lên. – Marvo

+0

@ Jethro fyi, bạn không thực sự 'khởi tạo một enum mới' với mã mẫu đó. Bạn không thể làm điều đó, trên thực tế, bởi vì enums trong Java là những người độc thân hiệu quả. Bạn đang thực sự tìm kiếm một giá trị enum hiện có. – sharakan

Trả lời

20

Để tham khảo, đây là một giải pháp thay thế với một HashMap:

enum CrimeCategory { 
    ASBO("Anti Social Behaviour"), 
    BURG("Burglary"), 
    CRIMDAM("Criminal Damage And Arson"), 
    DRUGS("Drugs"), 
    OTHTHEFT("Other Theft"), 
    PUPDISOR("Public Disorder And Weapons"), 
    ROBBERY("Robbery"), 
    SHOPLIF("Shoplifting"), 
    VEHICLE("Vehicle Crime"), 
    VIOLENT("Violent Crime"), 
    OTHER("Other Crime"); 

    private static final Map<String, CrimeCategory> map = new HashMap<>(values().length, 1); 

    static { 
    for (CrimeCategory c : values()) map.put(c.category, c); 
    } 

    private final String category; 

    private CrimeCategory(String category) { 
    this.category = category; 
    } 

    public static CrimeCategory of(String name) { 
    CrimeCategory result = map.get(name); 
    if (result == null) { 
     throw new IllegalArgumentException("Invalid category name: " + name); 
    } 
    return result; 
    } 
} 
+0

Cảm ơn bạn rất nhiều vì điều này, tôi sẽ kết hợp các 'HashMap' nếu nếu giá trị thể loại được gọi là thường xuyên hơn. Hiện tại chỉ được gọi khi một điểm đánh dấu bản đồ được nhấp để hiệu suất hiện tại ổn – Jethro

15

Thêm một phương pháp tĩnh đến CrimeCategory enum:

public static CrimeCategory valueOf(String name) { 
    for (CrimeCategory category : values()) { 
     if (category.category.equals(name)) { 
      return category; 
     } 
    }  
    throw new IllegalArgumentException(name); 
} 
+4

Hoặc nếu hiệu suất là quan trọng, một HashMap tĩnh chứa ánh xạ có thể được sử dụng ... – assylias

+1

Thật vậy ... Tôi đã không chắc chắn nếu các giá trị enum thực tế được tạo ra trước hoặc sau khi khối init tĩnh được chạy mặc dù, vì vậy figured tôi hãy giữ nó đơn giản. – sharakan

+0

@sharakan Có, tự đăng ký từ anh ta xây dựng enum vào một 'Bản đồ' là một trường tĩnh của' enum' sẽ NPE. (Giải pháp: Đặt tĩnh trong một lớp lồng nhau hoặc vòng lặp thông qua 'value()' trong một initialiser tĩnh đưa chúng vào bản đồ.) –

2

phương pháp nhà máy tĩnh trả về hằng số enum dựa trên giá trị của một trường thể hiện trên một trong hai dạng được mô tả trong các câu trả lời khác: một giải pháp dựa trên i terating các giá trị enum, hoặc một giải pháp dựa trên một HashMap.

Đối với các enums có số lượng nhỏ các hằng số, giải pháp lặp lại phải là giải pháp HashMap (yêu cầu tính toán mã băm, khớp với mã băm và giả định rằng sẽ không có xung đột băm).

Đối với các enums lớn hơn, giải pháp dựa trên bản đồ sẽ có hiệu suất cao hơn (nhưng yêu cầu dung lượng lưu trữ trong bộ nhớ). Tuy nhiên, nếu phương pháp nhà máy được gọi không thường xuyên thì cải thiện hiệu suất tổng thể bằng cách sử dụng bản đồ vẫn có thể cực kỳ nhỏ.

Quyết định chung để sử dụng tra cứu lặp lại hoặc tra cứu dựa trên bản đồ cho phương pháp nhà máy tĩnh cuối cùng sẽ phụ thuộc vào yêu cầu của bạn và môi trường. Không bao giờ sai khi bắt đầu với tra cứu lặp lại và sau đó thay đổi thành triển khai dựa trên bản đồ nếu hồ sơ hiển thị vấn đề hiệu suất thực tế.

Cuối cùng, kể từ Java 8, API Streams cho phép giải pháp dựa trên đường ống để lập bản đồ (nên có hiệu suất tương tự như giải pháp lặp). Ví dụ, giả sử bạn muốn tạo một giao diện mà bạn có thể sử dụng trên bất kỳ lớp enum nào để thể hiện ý định của bạn rằng nó phải phù hợp với một trong các trường cá thể của nó. Hãy gọi giao diện này Matchable. Giao diện này định nghĩa một phương thức trả về trường thể hiện mà bạn muốn khớp (ví dụ: getField()). Giao diện này cũng có thể định nghĩa một phương thức tĩnh trở lại một hằng số từ bất kỳ lớp enum thực hiện:

interface Matchable { 

    Object getField(); 

    public static <E extends Enum<E> & Matchable> E forToken(Class<E> cls, Object token) { 

     return Stream.of(cls.getEnumConstants()) 
      .filter(e -> e.getField().equals(token)) 
      .findFirst() 
      .orElseThrow(() -> new IllegalArgumentException("Unknown token '" + 
        token + "' for enum " + cls.getName())); 
    } 
} 

Bây giờ, bất kỳ lớp enum mà bạn xác định mà thực hiện Matchable có thể sử dụng Matchable.forToken() phương thức tĩnh để tìm hằng số enum mà giá trị trường instance khớp với tham số được cung cấp.

Tuyên bố loại chung E extends Enum<E> & Matchable đảm bảo rằng mã thông báo loại được chuyển đến phương thức làm tham số sẽ là cho lớp enum triển khai Matchable (nếu không mã sẽ không biên dịch).

Các vấn đề liên quan