是否有用于无符号数类型包装器的Java库?

10 浏览
0 Comments

是否有用于无符号数类型包装器的Java库?

显然,Java本身不支持原生的无符号数类型,而且这种情况不会很快发生改变(从2002年开始的评论)。然而,在处理数据库(如MySQL)时,偶尔可能会用到它们。关于如何模拟无符号数的问题有很多。例如:

所有这些问题都描述了如何实现。但是是否有任何库能够完全实现对UByte、UShort、UInteger、ULong等适当包装器的支持呢?最好是这些包装器能够扩展java.lang.Number并提供类似于java.math.BigInteger的算术API。

正如在这份文档中所示,涉及到很多要考虑的问题,也有很多可能出错的地方(如如何位移、如何乘法等),所以我不想自己去做。此外,我也不想仅仅使用更高的类型(如使用Short代替Byte等)。我希望保留8位、16位、32位、64位数字的概念,以便与数据库等进行最佳交互。

更新:

在你回答之前!请考虑到我知道所有的解决方法,但我真的非常希望有这4种类型,具备以上的属性。也许已经有人做过了,所以我才会提问。无需提醒我解决方法。

0
0 Comments

有没有一个Java库可以用来包装无符号数类型?这个问题的出现原因是,Guava库支持无符号整数类型UnsignedInteger和UnsignedLong,并且它们扩展了Number类并实现了算术操作。但是,出于某种原因,Guava库没有ushort和ubyte类型,特别是ubyte类型是最有用的类型。原因是什么呢?有人提出了关于short类型的问题:code.google.com/p/guava-libraries/issues/detail?id=670,对于byte类型有UnsignedBytes库。但是,UnsignedBytes库只提供了对byte类型的静态方法操作。

0
0 Comments

没有人按你所希望的方式创建这些包装器的原因有几个:

1. 性能

2. 垃圾回收开销

3. 没有自动装箱/拆箱

4. 糟糕/无用的接口

5. 存在更简单的处理方法

前四点可以通过一个小的C示例来证明:

unsigned int x=42, y, m=5, t=18;
y = x * m + t;

这将被转换为:

UInteger m = new UInteger(5);
UInteger t = new UInteger(18);
UInteger x = new UInteger(42);
UInteger y = x.multiplyBy(m);
y = y.add(t);

需要创建几个包装器对象,`multiplyBy`和`add`会生成更多的对象。如果使用这种方式进行大量计算,将给垃圾回收器带来很大的负担。包装和解包也会浪费CPU资源。

即使是简单的算术运算也很难写或阅读。

出于相同的原因,没有人使用有符号的包装器类型进行算术运算。

如果使用下一个更大的有符号类型进行计算并截断上部分,所有这些都是不必要的:

long x=42, y, m=5, t=18
y = (x*m + t) & 0xFFFFFFFF;

在Java和数据库之间的传输也可以使用下一个更大的有符号类型完成。由于JDBC不会创建这些无符号的包装器类型,你必须自己完成这个过程,然后将数据转换为无符号的包装器。

我自己进行了一些CPU密集型的数据处理和处理二进制协议。在这些场合,我希望也有无符号数据类型。但是用包装类型在Java中模拟它们比直接处理每个单独的情况更麻烦。

我同意,当二进制协议使用无符号64位整数时,情况确实变得“丑陋”..你好,BigInteger 🙁

你说得很对。另一方面,有时你确实需要BigInteger和/或BigDecimal。那么你别无选择,只能使用那个冗长的API。出于同样的原因,如果你确实需要UInteger,为什么不使用它(如果它可用的话)?如果你追求速度,你仍然可以自己进行计算...我目前正在评估是否要在jooq.org中使用这样的包装器,或者是否有其他方法...在我的情况下,速度可能不是个问题。

你知道你仍然可以使用BigInteger包装器(对于64位无符号)和下一个更大的值进行算术运算,并告诉数据库正确存储值吗?我相当确定你至少可以对某些数据库这样做。

:我了解到很多解决方法。我只是真的想要一个可以通信有多少位的包装器。在数据库术语中,BigInteger最适合n>19的DECIMAL(n,0)。对我来说,这与无符号长整型的语义不同...

在这种情况下,不要重新实现算术运算,只需在包装器中存储一个简单的int bitsize;值(或仅为每种类型编写包装器)。然后为所有重要的数据库实现“如何在DB Y中存储bitsize X的值”的逻辑(不知道这是否标准化?),就完成了。如果性能不重要,编写抽象基类是简单的。有趣的部分在于DB通信。

:不那么有趣:-)JDBC的PreparedStatement.setString()和ResultSet.getString()可以用于至少12个数据库...我已经实现了简单的包装器。只是想知道是否有人已经在之前完成了...

我没有考虑字符串-因为每次访问时都需要解析,所以性能特性很差,并且存储时(恭喜,你刚刚将4字节值转换为20字节)变得更糟(假设在数据库中使用UTF-16编码的字符串,这是经常使用的方法)。

:那只是JDBC(Java)。然后,驱动程序会将字符串转换回DB的int unsigned,例如。我认为现代JVM可以处理奇怪的字符串解析。但也许,我可以将无符号版本的值作为int,long等传递...

你不需要一个完整的无符号类型的类,因为对于有符号和无符号类型,基本操作(如加法、减法、非扩展乘法和所有位操作,除了右移)是相同的。对于剩下的操作,你可以编写一个函数来处理。这不是一些实用方法的问题,而是关于一个真正的包装类型。可以在方法签名中使用它,以明确表示该值是无符号的,如果混用有符号和无符号将会得到编译器错误。如果你只是需要帮助方法-那正是我回答的第二部分。

0
0 Comments

在我需要在jOOQ中使用这个功能时,我没有找到类似的东西,所以我自己开发了一个开源库,我称之为jOOU(U代表Unsigned):

http://github.com/jOOQ/jOOU

我知道有些人可能认为这是多余的,但我真的很想要那些包装器精确地包装其他编程语言中称为ubyteushortuintulong的类型。希望随着Valhalla的到来,这些包装器可以变成值类型。

当然,对算术/位操作实现的贡献非常受欢迎!

0