2012-06-15 29 views
63

Trước đây, tôi đã enums Legno tôi định nghĩa đơn giản là:Bắt enum gắn liền với giá trị int

NO_LEG, LEG_ONE, LEG_TWO 

và bằng cách gọi return LegNo.values()[i];, tôi đã có thể nhận được giá trị gắn liền với mỗi enum.

Nhưng bây giờ tôi đã quyết định rằng tôi muốn LegNo enum NO_LEG là int -1 thay vì 0 vì vậy tôi quyết định sử dụng một constructor tin để khởi và thiết lập giá trị của nó int

NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

private LegNo(final int leg) { legNo = leg; } 

chỉ điều bây giờ là bởi vì tôi đang làm theo cách này, phương pháp values() sẽ không hoạt động đối với trường hợp NO_LEG enum. Làm thế nào để tôi nhận được enum liên kết với int? Có cách nào hiệu quả để thực hiện việc này ngoài cách sử dụng tuyên bố chuyển đổi trường hợp hoặc if-elseif-elseif

Tôi có thể thấy rất nhiều câu hỏi SO để làm với giá trị int từ enum, nhưng tôi sau khi đảo ngược.

Trả lời

115

Bạn sẽ phải duy trì ánh xạ bên trong enum.

public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private int legNo; 

    private static Map<Integer, LegNo> map = new HashMap<Integer, LegNo>(); 

    static { 
     for (LegNo legEnum : LegNo.values()) { 
      map.put(legEnum.legNo, legEnum); 
     } 
    } 

    private LegNo(final int leg) { legNo = leg; } 

    public static LegNo valueOf(int legNo) { 
     return map.get(legNo); 
    } 
} 

Khối tĩnh sẽ chỉ được gọi một lần, vì vậy thực tế không có vấn đề về hiệu suất tại đây.

EDIT: Đổi tên phương thức thành valueOf vì nó phù hợp hơn với các lớp Java khác.

+0

xin lỗi im không chắc chắn nếu tôi đã đủ rõ ràng. tôi muốn vượt qua trong int và nhận được enum liên kết với nó. –

+0

@ L-Samuels Đoán tôi đã không đọc câu hỏi của bạn đúng cách. Xem cập nhật của tôi. – adarshr

+1

Tôi biết điều này có vẻ hiển nhiên, nhưng sử dụng nó như vậy: 'LegNo foo = LegNo.valueOf (2);'. Mã trước đó sẽ trả về 'LegNo.LEG_TWO'. – FirstOne

1

Vì enum của bạn chỉ chứa 3 phần tử, cách nhanh nhất là chỉ sử dụng một loạt các if else, như bạn đã đề xuất.

chỉnh sửa: câu trả lời mà adarshr cung cấp phù hợp hơn cho các trường hợp chung, nơi có nhiều giá trị enum, nhưng tôi nghĩ rằng đó là quá mức cần thiết cho sự cố của bạn.

+0

Có 'Bản đồ' trong mã của bạn là chắc chắn không phải là quá mức cần thiết. Bên cạnh đó nó làm cho phương pháp sạch hơn rất nhiều so với một spaghetti nếu điều kiện khác. – adarshr

+0

Tôi đồng ý rằng Bản đồ sẽ tốt hơn khi bạn có nhiều giá trị enum, nhưng đối với 3 giá trị tôi sẽ dính vào một cấu trúc if/else. Đó là một vấn đề của hương vị tôi đoán. – DieterDP

+0

Bất kể phương pháp nào chúng ta chọn, chữ ký phương thức của 'giá trị LegNo công khaiOf (giá trị int)' không được thay đổi. Nếu không thì có thể được viết trong chính enum. Nếu if-else thoát ra khỏi enum, thì nó chắc chắn sẽ trở thành một mã không-để-sạch. – adarshr

-4
public enum body 
{ 
    NO_LEG = 0,   // bit 1 
    LEG_ONE = 2,  // bit 2 
    LEG_TWO = 4,  // bit 3 
    NO_ARM = 8,   // bit 4 
    ARM_ONE = 16, // bit 5 
    ARM_TWO = 32 // bit 6 

} 

sử dụng nó như thế này (int) body.LEG_ONE; /// trả về 2

điều này cũng rất nhanh và dễ đọc vì nó được thực hiện trên thời gian biên dịch.

+7

Điều đó không hợp lệ đối với các enums Java. –

17

Bạn cũng có thể bao gồm một phương pháp tĩnh trong enum mà lặp qua tất cả các thành viên và trả về đúng.

public enum LegNo { 
    NO_LEG(-1), 
    LEG_ONE(1), 
    LEG_TWO(2); 

    private int legIndex; 

    private LegNo(int legIndex) { this.legIndex = legIndex; } 

    public static LegNo getLeg(int legIndex) { 
     for (LegNo l : LegNo.values()) { 
      if (l.legIndex == legIndex) return l; 
     } 
     throw new IllegalArgumentException("Leg not found. Amputated?"); 
    } 
} 

Bây giờ, nếu bạn muốn nhận được một giá trị Enum bởi các số nguyên, bạn chỉ cần sử dụng:

int myLegIndex = 1; //expected : LEG_ONE 
LegNo myLeg = LegNo.getLeg(myLegIndex); 
+0

Tôi cho rằng điều này sẽ thanh lịch hơn so với sử dụng câu lệnh if else if. Nhưng nếu có nhiều tìm kiếm hơn thì chiến lược bản đồ được đề xuất bởi @adarshr sẽ tốt hơn. Mặc dù bỏ phiếu cho sự hài hước. –

+1

Tôi cũng thích chiến lược bản đồ. Đặc biệt là khi enum hoặc có rất nhiều giá trị hoặc nó phải được tra cứu thông qua cơ chế này rất thường xuyên. Tuy nhiên, nếu tìm kiếm giá trị của int liên quan là một sự xuất hiện tương đối hiếm hoi hoặc bạn có rất nhiều enums khác nhau với cùng một yêu cầu tra cứu, tôi tin rằng cách của tôi sẽ thân thiện hơn với tài nguyên, vì chi phí cho bản đồ được lưu. Thêm vào đó, tôi thấy nó làm cho mã ít lộn xộn hơn. Tôi có một vài trường hợp sử dụng, mặc dù tôi chắc chắn sẽ chuyển sang Map-type. –

+0

Bạn không bao giờ nên lấy giá trị enum liên quan theo thứ tự của nó. Sử dụng một bản đồ tĩnh là phương pháp được đề xuất bởi các kiến ​​trúc sư Java. – hfontanez

0
public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private int legNo; 

    private LegNo(int leg) { legNo = leg; } 

    public static LegNo valueOf(int legNo) { 
     for (LegNo leg : LegNo.values()) { 
      if (leg.legNo == legNo) return leg; 
     } 
    } 
} 

assert LegNo.valueOf(2) == LegNo.LEG_TWO 
assert LegNo.valueOf(3) == null 
+4

Được chấp nhận cho enums có <10 giá trị nhưng hoàn toàn không hiệu quả đối với số lượng lớn các giá trị enum vì độ phức tạp tra cứu O (n) – Alfishe

10

adarshr's answer thích nghi với Java 8:

import static java.util.Arrays.stream; 
import static java.util.stream.Collectors.toMap; 

import java.util.Map; 

public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private final int legNo; 

    private final static Map<Integer, LegNo> map = 
      stream(LegNo.values()).collect(toMap(leg -> leg.legNo, leg -> leg)); 

    private LegNo(final int leg) { 
     legNo = leg; 
    } 

    public static LegNo valueOf(int legNo) { 
     return map.get(legNo); 
    } 
} 
4

Bạn có thể cũng truy cập giá trị Enum tương ứng với giá trị số nguyên đã cho chỉ đơn giản bằng cách gọi phương thức values ​​() trên enum LegNo. Nó trả về trường của Legno enums: LegNo.values[0]; //returns LEG_NO LegNo.values[1]; //returns LEG_ONE LegNo.values[2]; //returns LEG_TWO

Không chính xác thứ mà anh đang tìm kiếm, nhưng khá gần và thực sự rất đơn giản. (Mặc dù chủ đề đã chết, nó có thể hữu ích cho người khác.)

3

Java 8 chiều với giá trị mặc định:

public enum LegNo { 
    NO_LEG(-1), LEG_ONE(1), LEG_TWO(2); 

    private final int legNo; 

    LegNo(int legNo) { 
     this.legNo = legNo; 
    } 

    public static LegNo find(int legNo, Supplier<? extends LegNo> byDef) { 
     return Arrays.asList(LegNo.values()).stream() 
       .filter(e -> e.legNo == legNo).findFirst().orElseGet(byDef); 
    } 
} 

gọi:

LegNo res = LegNo.find(0,() -> LegNo.NO_LEG); 

hay với Ngoại lệ:

LegNo res = LegNo.find(0,() -> { 
    throw new RuntimeException("No found"); 
}); 
Các vấn đề liên quan