【问题标题】:How to use a bitwise operator to pass multiple Integer values into a function for Java?如何使用按位运算符将多个整数值传递给 Java 函数?
【发布时间】:2009-03-15 15:52:20
【问题描述】:

在应用程序框架中,我经常看到允许您将多个 Int 值(通常用于代替枚举)传递给函数的框架。

例如:

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
        ...
    }
}

那么 multiValueExample 中应该存在什么逻辑,以便我正确评估使用按位运算符传入的多个 int 值?

【问题讨论】:

  • 请澄清。我不明白。这些不是多个值。价值观.ONE |价值观。三 | Values.FIVE = 0x7f020006,对吧?未命名位的用途是什么?
  • 您是否有特定原因要使用按位运算? enum/EnumSet 解决方案更清晰,更类似于 Java。

标签: java function bit-manipulation bitwise-operators integer


【解决方案1】:

你的值应该是 2 的幂。

这样,当您对它们进行按位或运算时,您不会丢失任何信息。

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;

等等

那么你可以这样做:

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.
}

【讨论】:

  • 不应该是按位与(单&)吗?
  • 我相信您的意思是 2 的幂,而不是 2 的倍数。您无法区分 2 | 6 中的 4。此外,&& 是逻辑 AND,而不是二进制 AND,因此它的计算结果始终为 true。
  • 我发现设置数字的最佳方法是 int ONE = 0x1;整数二 = 0x1
  • Android 使用此约定通过 xml 将多个属性应用于对象。很棒的帖子!
  • 是否可以一次检查传递的值是否包含一和二?例如,如果 1 和 2 的操作相同,我们可以执行类似的操作:if ((values & Values.ONE & Values.Two ) > 0) {//action here} 或类似的操作,我知道我们可以条件,但想知道是否有更短的方法
【解决方案2】:

如前所述,考虑使用枚举而不是位值。

根据Effective Java 2“第32项:使用EnumSet代替位域”

使用EnumSet对内存使用非常有效,非常方便。

这是一个例子:

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");
    }
  }
}

【讨论】:

  • 是的,感谢您的解决方案。不幸的是,我正在使用移动技术,其中枚举在内存管理方面受到很大影响。因此,我使用按位运算来提高性能。
  • 同意,在移动应用程序中是有意义的。
【解决方案3】:

您将整数值设置为 2 的幂,以便每个枚举值都是二进制表示中的单个位。

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

然后您使用按位 OR 来组合值并按位 AND 来测试设置值。

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

【讨论】:

    【解决方案4】:

    你结合的价值观| (二进制 OR,而不是逻辑 OR [即 ||])在其位表示中不能有重叠的“1”。例如,

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

    那么你可以结合ONE和TWO,例如:

    ONE | TWO = 0000 0011
    

    但你无法区分 ONE |三中之二,因为有重叠的位。因此,您组合的数字应该是 2 的幂,这样它们在 OR'ed 在一起时不会重叠。要测试是否在“值”中传递了一个数字,请执行以下操作:

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

    为了更好地理解其工作原理和方式,我建议您阅读一些有关二进制表示和逻辑的内容。一个好地方是Chapter 3 of the Art of Assembly

    【讨论】:

      【解决方案5】:

      好吧,如果它们是 2 的幂,您可以在下面的代码中执行类似“显示”方法的操作。

      Here is a link in wikipedia 也可以解释为什么你想要 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();
          }
      }
      

      【讨论】:

        【解决方案6】:

        在计算每个位时,使用位掩码很流行。今天的另一种方法是使用更易于操作和扩展的枚举。

        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.
                }
            }
        }
        

        【讨论】:

          【解决方案7】:

          首先,您不能以这种方式定义值来进行按位比较。相反,设置不同的位:

          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
          

          其次,您可能应该使用 java.util.BitSet 进行这些操作:

          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}"
          

          【讨论】:

          • 有什么 Java 没有类吗? =)
          • public static final int FIVE = 0x10; // Fifth bit is set 不正确,您同时设置了第 4 位和第 2 位。你的意思是:public static final int FIVE = 0x16; // Fifth bit is set(我会编辑答案,但我不能,除非我有更大的改变要做(这可能会在审查中被拒绝))!
          【解决方案8】:

          按位运算的 Java 教程章节位于

          http://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html

          非常简洁,但可以参考。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-02-16
            • 1970-01-01
            • 1970-01-01
            • 2021-12-07
            相关资源
            最近更新 更多