2009-03-15 35 views
13

Trong các khung ứng dụng, tôi tiếp tục thấy các khuôn khổ cho phép bạn truyền vào nhiều giá trị Int (thường được sử dụng thay cho một enum) thành một hàm.Làm thế nào để sử dụng toán tử bitwise để chuyển nhiều giá trị Integer vào một hàm cho Java?

Ví dụ:

public class Example 
{ 
    public class Values 
    { 
     public static final int ONE = 0x7f020000; 
     public static final int TWO = 0x7f020001; 
     public static final int THREE = 0x7f020002; 
     public static final int FOUR = 0x7f020003; 
     public static final int FIVE = 0x7f020004; 
    } 

    public static void main(String [] args) 
    { 
     // should evaluate just Values.ONE 
     Example.multiValueExample(Values.ONE); 

     // should evalueate just values Values.ONE, Values.THREE, Values.FIVE 
     Example.multiValueExample(Values.ONE | Values.THREE | Values.FIVE); 

     // should evalueate just values Values.TWO , Values.FIVE 
     Example.multiValueExample(Values.TWO | Values.FIVE); 
    } 

    public static void multiValueExample(int values){ 
     // Logic that properly evaluates bitwise values 
     ... 
    } 
} 

Vì vậy, những gì logic nên tồn tại trong multiValueExample cho tôi để đánh giá đúng nhiều giá trị int được thông qua việc sử dụng các nhà điều hành Bitwise?

+0

Xin làm rõ. Tôi không hiểu. Đó không phải là nhiều giá trị. Values.ONE | Giá trị.THREE | Values.FIVE = 0x7f020006, phải không? Và mục đích của các bit chưa được đặt tên là gì? –

+0

Có lý do cụ thể nào khiến bạn muốn sử dụng các hoạt động bitwise không? Các giải pháp enum/EnumSet là clearner và giống Java hơn. –

Trả lời

30

giá trị của bạn nên được quyền hạn của 2.

Bằng cách đó, bạn không mất bất kỳ thông tin khi bạn Bitwise-OR họ.

public static final int ONE = 0x01; 
public static final int TWO = 0x02; 
public static final int THREE = 0x04; 
public static final int FOUR = 0x08; 
public static final int FIVE = 0x10; 

, vv

Sau đó, bạn có thể làm điều này:

public static void main(String [] args) { 
    Example.multiValueExample(Values.ONE | Values.THREE | Values.FIVE); 
} 

public static void multiValueExample(int values){ 
    if ((values & Values.ONE) == Values.ONE) { 
    } 

    if ((values & Values.TWO) == Values.TWO) { 
    } 

    // etc. 
} 
+0

Không phải là bitwise AND (đơn &)? – Hamid

+2

Tôi tin rằng bạn có nghĩa là quyền hạn của 2, không bội số của 2. Bạn không thể phân biệt 2 | 4 từ 6. Ngoài ra, && là hợp lý AND, không phải là nhị phân AND, vì vậy nó sẽ luôn luôn đánh giá đúng. –

+0

@Hamid và Joao: cảm ơn vì đã sửa chữa. –

3

Trước tiên, bạn không thể xác định giá trị theo cách đó để làm so sánh Bitwise. Thay vào đó, thiết lập bit khác nhau:

public static final int ONE = 0x1; // First bit is set 
public static final int TWO = 0x2; // Second bit is set 
public static final int THREE = 0x4; // Third bit is set 
public static final int FOUR = 0x8; // Fourth bit is set 
public static final int FIVE = 0x10; // Fifth bit is set 

Thứ hai, bạn có lẽ nên được sử dụng java.util.BitSet cho các loại hoạt động:

BitSet bits = new BitSet(5); 
bits.set(2); 
bits.set(4); 

System.out.println("these bits are set: " + bits); 
// Prints "these bits are set: {2, 4}" 

BitSet otherBits = new BitSet(5); 
otherBits.set(3); 
otherBits.set(4); 

System.out.println("these bits are set: " + bits.or(otherBits)); 
// Prints "these bits are set: {2, 3, 4}" 
+0

Có điều gì Java không có lớp học không? =) –

+1

Đúng! http://stackoverflow.com/questions/639035/making-the-perfect-programming-language/639042#639042;) –

+0

haha, chức năng đó chỉ tồn tại trong Python (http://xkcd.com/353/). =) –

4

Các giá trị bạn kết hợp với | (nhị phân OR, không hợp lý HOẶC [đó là ||]) không được chồng chéo "1" s trong biểu diễn bit của chúng. Ví dụ,

ONE = 0x1 = 0000 0001 
TWO = 0x2 = 0000 0010 
THREE = 0x3 = 0000 0011 
FOUR = 0x4 = 0000 0100 

Sau đó, bạn có thể kết hợp một và hai, ví dụ:

ONE | TWO = 0000 0011 

Nhưng bạn không thể phân biệt ONE | HAI từ BA, bởi vì có các bit chồng lên nhau. Do đó, các con số bạn kết hợp nên là sức mạnh của hai, sao cho chúng không chồng lên nhau khi OR 'lại với nhau. Để kiểm tra xem một số đã được thông qua trong "giá trị", làm:

if (values & ONE) { 
    // ... then ONE was set 
} 

Để hiểu rõ hơn tại sao và cách làm việc này, tôi khuyên bạn nên đọc một chút về biểu diễn nhị phân và logic. Một địa điểm tốt là Chapter 3 of the Art of Assembly.

5

Bạn thiết lập giá trị số nguyên là lũy thừa của hai để mỗi giá trị được liệt kê là một bit trong biểu diễn nhị phân.

int ONE = 0x1; //0001 
int TWO = 0x2; //0010 
int THREE = 0x4; //0100 
int FOUR = 0x8; //1000 

Sau đó, bạn sử dụng bit hoặc OR để kết hợp các giá trị và bitwise AND để kiểm tra giá trị đã đặt.

int test_value = (ONE | FOUR); //-> 1001 
bool has_one = (test_value & ONE) != 0; //-> 1001 & 0001 -> 0001 -> true 
3

Vâng, nếu chúng là sức mạnh của 2 bạn sẽ làm một cái gì đó như phương pháp "hiển thị" trong mã bên dưới.

Here is a link in wikipedia về chủ đề cũng nên giải thích lý do bạn muốn quyền hạn của 2.

public class Main 
{ 
    private static final int A = 0x01; 
    private static final int B = 0x02; 
    private static final int C = 0x04; 

    public static void main(final String[] argv) 
    { 
     display(A); 
     display(B); 
     display(C); 
     display(A | A); 
     display(A | B); 
     display(A | C); 
     display(B | A); 
     display(B | B); 
     display(B | C); 
     display(C | A); 
     display(C | B); 
     display(C | C); 
     display(A | A | A); 
     display(A | A | B); 
     display(A | A | C); 
     display(A | B | A); 
     display(A | B | B); 
     display(A | B | C); 
     display(A | C | A); 
     display(A | C | B); 
     display(A | C | C); 
     display(B | A | A); 
     display(B | A | B); 
     display(B | A | C); 
     display(B | B | A); 
     display(B | B | B); 
     display(B | B | C); 
     display(B | C | A); 
     display(B | C | B); 
     display(B | C | C); 
     display(C | A | A); 
     display(C | A | B); 
     display(C | A | C); 
     display(C | B | A); 
     display(C | B | B); 
     display(C | B | C); 
     display(C | C | A); 
     display(C | C | B); 
     display(C | C | C); 
    } 

    private static void display(final int val) 
    { 
     if((val & A) != 0) 
     { 
      System.out.print("A"); 
     } 

     if((val & B) != 0) 
     { 
      System.out.print("B"); 
     } 

     if((val & C) != 0) 
     { 
      System.out.print("C"); 
     } 

     System.out.println(); 
    } 
} 
3

Sử dụng mặt nạ bit phổ biến khi mỗi bit được tính. Một cách khác để làm điều này ngày hôm nay là sử dụng enums với thao tác đơn giản và mở rộng.

import static Example.Values.*; 
import java.util.Arrays; 

public class Example { 
    public enum Values { ONE, TWO, THREE, FOUR, FIVE } 

    public static void main(String [] args) { 
     // should evaluate just Values.ONE 
     multiValueExample(ONE); 

     // should evaluate just values Values.ONE, Values.THREE, Values.FIVE 
     multiValueExample(ONE, THREE, FIVE); 

     // should evaluate just values Values.TWO , Values.FIVE 
     multiValueExample(TWO, FIVE); 
    } 

    public static void multiValueExample(Values... values){ 
     // Logic that properly evaluates 
     System.out.println(Arrays.asList(values)); 
     for (Values value : values) { 
      // do something. 
     } 
    } 
} 
9

Như đã đề cập, hãy xem xét sử dụng enums thay vì giá trị bit.

Theo Effective Java 2: "Item 32: Sử dụng EnumSet thay vì lĩnh vực chút"

Sử dụng EnumSet là khá hiệu quả cho việc sử dụng bộ nhớ và rất thuận tiện.

Dưới đây là một ví dụ:

package enums; 

import java.util.EnumSet; 
import java.util.Set; 

public class Example { 
    public enum Values { 
    ONE, TWO, THREE, FOUR, FIVE 
    } 

    public static void main(String[] args) { 
    // should evaluate just Values.ONE 
    Example.multiValueExample(EnumSet.of(Values.ONE)); 

    // should evalueate just values Values.ONE, Values.THREE, Values.FIVE 
    Example.multiValueExample(EnumSet.of(Values.ONE, Values.THREE, Values.FIVE)); 

    // should evalueate just values Values.TWO , Values.FIVE 
    Example.multiValueExample(EnumSet.of(Values.TWO, Values.FIVE)); 
    } 

    public static void multiValueExample(Set<Values> values) { 
    if (values.contains(Values.ONE)) { 
     System.out.println("One"); 
    } 

    // Other checks here... 

    if (values.contains(Values.FIVE)) { 
     System.out.println("Five"); 
    } 
    } 
} 
+2

+1 giải pháp giống Java nhất –

+0

Có, cảm ơn giải pháp này. Thật không may tôi đang làm việc với công nghệ di động, nơi enums mất khá một hit về quản lý bộ nhớ. Như vậy, tôi đang sử dụng hoạt động bitwise để cải thiện hiệu suất. – AtariPete

+0

Đồng ý, trong một ứng dụng dành cho thiết bị di động, điều đó có ý nghĩa. –

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