是否有用于无符号数字类型包装器的 Java 库? [关闭]
Posted
技术标签:
【中文标题】是否有用于无符号数字类型包装器的 Java 库? [关闭]【英文标题】:Is there a Java library for unsigned number type wrappers? [closed] 【发布时间】:2011-11-19 09:09:32 【问题描述】:显然,Java 本身不支持无符号数字类型,and that's not going to change soon(cmets 从 2002 年开始)。但是,在使用数据库(例如 mysql)时,它们可能会时不时地派上用场。关于如何模拟无符号数有很多问题。例如:
unsigned short in java Java: Unsigned numbers Understanding Java unsigned numbers所有这些都从表面上描述了它可以如何完成。但是是否有任何库实际上一直在为UByte
、UShort
、UInteger
、ULong
实现合适的包装器?最好,这些包装器将扩展 java.lang.Number
并提供类似于 java.math.BigInteger
的算术 API。
从this document 可以看出,有很多事情要考虑,也有很多可能出错(例如如何按位移位、如何乘法等),所以我不想自己做.另外,我不想只使用下一个更高的类型(例如Short
而不是Byte
等)。例如,为了与数据库进行最佳交互,我希望保留 8-bit
、16-bit
、32-bit
、64-bit
号码的概念。
更新:
在你回答之前!考虑到我知道所有的解决方法,但我真的很想拥有完全具有上述属性的这 4 种类型。也许有人已经这样做了,所以这就是我问的原因。无需提醒我解决方法。
【问题讨论】:
所有关于玩unsigned-in-signed-land的比特捏造警告,没有“像数字一样的数字”通常足以让我拒绝。 Java 刚刚错过了一些领域,这就是其中之一。 @pst:我也有同感。在大多数情况下,我也被拒之门外。但在这种情况下,这样的图书馆真的是一种享受。 前段时间我遇到了 javolution 库,其中包含 Struct 类,其中包含 Uints 8-,16-,32-bit 的实现。 @87element:实际上,这是一个不错的库。不幸的是,在这种情况下,无符号数类既没有扩展java.lang.Number
,也没有提供算术方法......但仍然需要牢记......
@A.H.我知道 OpenHMS 的 SqlBuilder。不过,它似乎失去了吸引力。你会在这里找到更多类似的工具:***.com/questions/1217228/…
【参考方案1】:
当我在 jOOQ 中需要这个功能时,我还没有找到类似的东西,所以我推出了自己的开源库,我称之为 jOOU(U 代表无符号):
http://github.com/jOOQ/jOOU
我知道有些人可能认为这有点矫枉过正,但我真的很想拥有那些包装其他语言称为 ubyte
、ushort
、uint
、ulong
的包装器。希望通过 Valhalla,这些包装器可以转换为值类型。
当然,非常欢迎对算术/按位运算实现的贡献!
【讨论】:
【参考方案2】:没有人按照你想要的方式创建这些包装器是有一些原因的。
性能 垃圾收集器开销 没有自动装箱/拆箱 糟糕/无用的界面。 存在更简单的处理方法前四点用一个小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。
即使是简单的算术也是可以读写的 PITA,这一点也很明显。
出于同样的原因,NOBODY 使用带符号的包装类型进行算术运算。
如果您使用下一个更大的有符号类型进行计算并像这样切断上部,那么所有这些都是不必要的:
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 使用此类包装器,或者是否有其他方法...在我的情况下,速度可能不是问题。
@LukasEder 你知道你仍然可以使用 BigInteger 包装器(对于 64 位无符号)和下一个更大的值来计算其他所有值,然后告诉数据库正确存储这些值?我实际上很确定您至少可以为某些数据库做到这一点。
@Voo:我知道许多解决方法。我真的很喜欢一个可以传达有多少位的包装器。在数据库中,BigInteger
是DECIMAL(n, 0)
与n > 19
的最佳匹配。这对我来说有不同的语义,而不是unsigned long
...
@LukasEder 在这种情况下,不要重新实现算法,而只需在包装器中存储一个简单的 int bitsize;
值(或者只为每种类型编写包装器)。然后只需为所有重要的数据库实现“我如何在 DB Y 中存储位大小 X 的值”逻辑(不知道这是否甚至没有标准化?),你就完成了。如果性能不重要,那么编写抽象基类是微不足道的。有趣的部分在于数据库通信。【参考方案3】:
另一个需要考虑的库是 Google 的 Guava。它支持以下无符号类型:
UnsignedInteger UnsignedLong他们确实扩展了 Number 并实现了算术运算。
【讨论】:
出于某种原因,Guava 没有ushort
和 ubyte
类型。特别是ubyte
是最有用的。你知道为什么吗?
short
出现问题:code.google.com/p/guava-libraries/issues/detail?id=670,byte
出现UnsignedBytes
是的,但是UnsignedBytes
只为byte
操作提供静态方法...【参考方案4】:
commons-primitives 中使用的 unsignedInt 数组的解决方案将其传递一个 long 将其视为 unsigned int。你可以在这里阅读更多:
http://commons.apache.org/primitives/apidocs/org/apache/commons/collections/primitives/ArrayUnsignedIntList.html
【讨论】:
谢谢,我知道所有这些部分解决方案。许多库对无符号数字类型采取了 1-2 步。但我真的在寻找一个完全按照我在问题中描述的库,一个包括算术在内的所有方法......【参考方案5】: // Java 8
int vInt = Integer.parseUnsignedInt("4294967295");
System.out.println(vInt); // -1
String sInt = Integer.toUnsignedString(vInt);
System.out.println(sInt); // 4294967295
long vLong = Long.parseUnsignedLong("18446744073709551615");
System.out.println(vLong); // -1
String sLong = Long.toUnsignedString(vLong);
System.out.println(sLong); // 18446744073709551615
// Guava 18.0
int vIntGu = UnsignedInts.parseUnsignedInt(UnsignedInteger.MAX_VALUE.toString());
System.out.println(vIntGu); // -1
String sIntGu = UnsignedInts.toString(vIntGu);
System.out.println(sIntGu); // 4294967295
long vLongGu = UnsignedLongs.parseUnsignedLong("18446744073709551615");
System.out.println(vLongGu); // -1
String sLongGu = UnsignedLongs.toString(vLongGu);
System.out.println(sLongGu); // 18446744073709551615
【讨论】:
以上是关于是否有用于无符号数字类型包装器的 Java 库? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章