简体   繁体   English

Java:BitSet比较

[英]Java: BitSet comparison

Suppose we have two BitSet objects in Java with values as 假设我们在Java中有两个BitSet对象,其值为

//<MSB....LSB>
B1:<11000101>
B2:<10111101>

How can we compare B1 and B2 to know that the value represented by B1 is greater than that by B2 . 我们如何比较B1和B2才能知道B1代表的值大于B2代表的值。

are logical operators (>,<,==) overloaded for BitSet? 是否为BitSet重载了逻辑运算符(>,<,==) or Do I have to write my own implementation? 或者我是否必须编写自己的实现?

Update: just found that "The operator > is undefined for the argument type(s) java.util.BitSet, java.util.BitSet" . 更新:刚发现“运算符>未定义参数类型java.util.BitSet,java.util.BitSet” Is there any built-in way to do so? 有没有内置方法可以这样做?

You can do it by xor -ing the two sets together, and comparing the length of the result to lengths of bit sets: 你可以通过xor -ing两个集合,并将结果的长度与位集的length进行比较来实现:

  • If xor is empty, bit sets are equal. 如果xor为空,则位集相等。 You can bypass this operation by calling equals() 您可以通过调用equals()来绕过此操作
  • Otherwise, the length of xor result will be equal to the position of the most significant bit that is different between the two values. 否则, xor结果的长度将等于两个值之间不同的最高有效位的位置。
  • Whichever of the two operands has this bit set is the greater one of the two. 这个位设置的两个操作数中的哪一个是两者中较大的一个。

Here is a sample implementation: 这是一个示例实现:

int compare(BitSet lhs, BitSet rhs) {
    if (lhs.equals(rhs)) return 0;
    BitSet xor = (BitSet)lhs.clone();
    xor.xor(rhs);
    int firstDifferent = xor.length()-1;
    if(firstDifferent==-1)
            return 0;

    return rhs.get(firstDifferent) ? 1 : -1;
}

Demo. 演示。

No, the operators aren't overloaded, because a) there is no operator overloading in Java, b) what you expect is kind of wrong and illogical. 不,运算符没有超载,因为a)Java中没有运算符重载,b)你期望的是错误和不合逻辑的。

BitSet is, like the name signifies a set of bits . BitSet就像名称表示一组位 You can't tell a "greater" and "smaller" set - it's like saying one color is "bigger" than the other. 你无法分辨出“更大”和“更小”的设置 - 就像说一种颜色比另一种颜色“更大”。 If you want to compare bit sets, you have to create a comparison metric - I think what you want is to compare values of the integers created from bits - if that's the case, use the code from eg BitSet to and from integer/long , and then call 如果你想比较位集,你必须创建一个比较指标 - 我想你想要的是比较从位创建的整数的值 - 如果是这种情况,使用例如BitSet的代码到整数/长 ,然后打电话

static int compare( BitSet bs1, BitSet bs2 ) {
  return Long.compare(Bits.convert(bs1),Bits.convert(bs2));
}

or, as a Comparator , 或者,作为Comparator

class BitSetComparator implements Comparator<BitSet> {
  int compare( BitSet bs1, BitSet bs2 ) {
    return Long.compare(Bits.convert(bs1),Bits.convert(bs2));
  }
}

Note that in this particular case both sets have to fit into long (63 bits max). 请注意,在这种特殊情况下,两个集合必须适合long (最多63位)。 Alternatively, assuming your metric is "the set with higher unsigned integer representation is bigger", you can use XORing, or loop through the bits, or any other construct that goes through all the bits - 或者,假设您的度量标准是“具有更高无符号整数表示的集合更大”,您可以使用XORing,或循环遍历位或任何其他通过所有位的构造 -

int compare( BitSet bs1, BitSet bs2 ) {
  BitSet x = ((BitSet)bs1.clone()).xor(bs2);
  return ( x.isEmpty() ) ? 0 : ( x.length() == bs2.length() ? 1 : -1 );
}

but in all of those cases , if you're aiming at comparing your bits, your best bet is just to use long to store your data and then compare it directly as unsigned values, using https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html#compareUnsigned-long-long- - otherwise you're losing the space-time efficiency of bit storage with doing to-and-fro conversions to deal with a case that's based on using a class for things it's not designed for. 但在所有这些情况下 ,如果你的目标是比较你的位,最好的办法就是用long来存储你的数据,然后使用https://docs.oracle.com/javase直接将它作为无符号值进行比较。 /8/docs/api/java/lang/Long.html#compareUnsigned-long-long- - 否则你通过往复转换来处理基于案例的情况,从而失去了位存储的时空效率使用类不是为了它而设计的。 Both BitSet#xor() & (especially) BitSet#length() aren't the light-weight operations you'd expect from bit ops, mainly due to recalculateWordsInUse(); BitSet#xor()和(特别是) BitSet#length()都不是比特操作所期望的轻量级操作,主要是由于recalculateWordsInUse(); , checkInvariants(); checkInvariants(); & Long.numberOfLeadingZeros() used in them. Long.numberOfLeadingZeros()在其中使用。 All in all, all methods other than native integer use (especially any comparing code as shown above) will result in serious performance loss in any performance-dependent scenarios. 总而言之,除了本机整数使用之外的所有方法(尤其是如上所示的任何比较代码)都会在任何依赖于性能的场景中导致严重的性能损失。

You can use the logical operator on bit basis (boolean values received from get()): 您可以在位的基础上使用逻辑运算符(从get()接收的布尔值):

// Assumed equal length
boolean less(BitSet b1, BitSet b2) {
 int N = b1.length();

 for (int i = N-1; i >= 0; i--) {
    if (b1.get(i) ^ b2.get(i)) return b2.get(i);
 }

 return false;
}

Or you can have a comparator in place: 或者你可以有一个比较器:

class BitsComparator implements Comparator<BitSet> {
  @Override
  int compare (BitSet b1, BitSet b2) {
    if (b1.length() > b2.length())
       return 1;
    if (b1.length() == b2.length()) {
      int N = b1.length();
      for (int i = N-1; i >= 0; i--) {
        if ((b1.get(i) ^ b2.get(i)) && b2.get(i)) return -1;
      }
      return 0;
    }
    return -1;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM