是否有用于无符号数字类型包装器的 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

所有这些都从表面上描述了它可以如何完成。但是是否有任何库实际上一直在为UByteUShortUIntegerULong 实现合适的包装器?最好,这些包装器将扩展 java.lang.Number 并提供类似于 java.math.BigInteger 的算术 API。

从this document 可以看出,有很多事情要考虑,也有很多可能出错(例如如何按位移位、如何乘法等),所以我不想自己做.另外,我不想只使用下一个更高的类型(例如Short 而不是Byte 等)。例如,为了与数据库进行最佳交互,我希望保留 8-bit16-bit32-bit64-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

我知道有些人可能认为这有点矫枉过正,但我​​真的很想拥有那些包装其他语言称为 ubyteushortuintulong 的包装器。希望通过 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);

必须创建几个包装对象,multiplyByadd 会生成更多。如果以这种方式完成许多计算,这将给垃圾收集器带来相当大的负担。包装和展开也会白白消耗你的 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:我知道许多解决方法。我真的很喜欢一个可以传达有多少位的包装器。在数据库中,BigIntegerDECIMAL(n, 0)n > 19 的最佳匹配。这对我来说有不同的语义,而不是unsigned long... @LukasEder 在这种情况下,不要重新实现算法,而只需在包装器中存储一个简单的 int bitsize; 值(或者只为每种类型编写包装器)。然后只需为所有重要的数据库实现“我如何在 DB Y 中存储位大小 X 的值”逻辑(不知道这是否甚至没有标准化?),你就完成了。如果性能不重要,那么编写抽象基类是微不足道的。有趣的部分在于数据库通信。【参考方案3】:

另一个需要考虑的库是 Google 的 Guava。它支持以下无符号类型:

UnsignedInteger UnsignedLong

他们确实扩展了 Number 并实现了算术运算。

【讨论】:

出于某种原因,Guava 没有 ushortubyte 类型。特别是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 库? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

GO的跨平台数扰类型

SWIG:numpy 包装器的意外结果?

java数据类型是有符号的,那与有些无符号的如何区别

SWIG tcl:log4cpp 包装器的未定义符号错误

JAVA中类型(char、long、int.....一共八个)有符号和无符号是啥意思

SFINAE 用于无符号类型选择