考虑以下代码(java8):
@Test
public void testBigIntegerVsBitSet() throws Throwable
{
String bitString529 = "00000010 00010001"; // <- value = 529 (LittleEndian)
byte[] arr529 = new byte[] { 0x02, 0x11 }; // <- the same as byte array (LittleEndian)
BigInteger bigIntByString = new BigInteger( bitString529.replace( " ", ""), 2); // throws if there is a blank!
BigInteger bigIntByArr = new BigInteger( arr529);
BitSet bitsetByArr = BitSet.valueOf( arr529); // interpretes bit-order as LittleEndian, but byte-order as BigEndian !!!
System.out.println( "bitString529 : " + bitString529); // bitString529 : 00000010 00010001
System.out.println( "arr529.toString : " + Arrays.toString( arr529)); // arr529.toString : [2, 17]
System.out.println( "bigIntByString : " + bigIntByString); // bigIntByString : 529
System.out.println( "bigIntByArr : " + bigIntByArr); // bigIntByArr : 529
System.out.println( "bitsetByArr : " + bitsetByArr.toString() ); // bitsetByArr : {1, 8, 12}
System.out.println( "expecting : {0, 4, 9}"); // expecting : {0, 4, 9}
String bigIntByStringStr = toBitString( bigIntByString::testBit);
String bigIntByArrStr = toBitString( bigIntByArr::testBit);
String bitsetByArrStr = toBitString( bitsetByArr::get);
System.out.println( "bigIntByStringStr: " + bigIntByStringStr); // bigIntByStringStr: 1000100001000000
System.out.println( "bigIntByArrStr : " + bigIntByArrStr); // bigIntByArrStr : 1000100001000000
System.out.println( "bitsetByArrStr : " + bitsetByArrStr ); // bitsetByArrStr : 0100000010001000
}
private String toBitString( Function<Integer, Boolean> aBitTester)
{
StringBuilder sb = new StringBuilder();
for ( int i = 0; i < 16; i++ )
{
sb.append( aBitTester.apply( i) ? "1" : "0");
}
return sb.toString();
}
证明BitSet将字节数组解析为BIG_ENDIAN,而它将(单字节的)位顺序解释为LITTLE_ENDIAN。相比之下,BigInteger在LITTLE_ENDIAN中解释,即使用位串加载也是如此。
特别是对两个类的位索引的迭代(BitInteger :: testBit与BitSet :: get)会产生不同的结果。
这种不一致是否有原因?
答案 0 :(得分:3)
Endianess主要指的是字节的排序,而不是单个位的排序。后者在大多数应用程序中都不相关,因为您无法例如处理内存中的各个位。因此,字节中的位的字节顺序仅用于重要的情况,例如串行数据总线,否则字节通常被视为它们所代表的数字而没有任何字节顺序(cf. Wikipedia和{{3的答案}})。
因此,BitSet
将字节视为首先具有最低有效位,这样当你给它字节0x01
时,你得到了设置最低位的预期结果,无论是什么它用于字节排序的字节序。这就是使用BigInteger
和BitSet
的输出仅以字节顺序不同的原因。
请注意,对于字节顺序,BitSet
使用little-endianness,而BigInteger
使用big endianness(与您声明的不同)。
至于为什么BitSet
使用与BigInteger
不同的字节序,我们只能推测。请注意,受尊重的BitSet
方法更新(仅在Java 1.7中引入),因此,自引入BigInteger
以来,可能认为小端与大端的重要性已发生变化。