【问题标题】:Is there a Java library for unsigned number type wrappers? [closed]是否有用于无符号数字类型包装器的 Java 库? [关闭]
【发布时间】:2011-11-19 09:09:32
【问题描述】:

显然,Java 本身不支持无符号数字类型,and that's not going to change soon(cmets 从 2002 年开始)。但是,在使用数据库(例如 MySQL)时,它们可能会时不时地派上用场。关于如何模拟无符号数有很多问题。例如:

所有这些都从表面上描述了它可以如何完成。但是是否有任何库实际上一直在为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。不过,它似乎失去了吸引力。你会在这里找到更多类似的工具:stackoverflow.com/questions/1217228/…

标签: java numbers unsigned


【解决方案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。它支持以下无符号类型:

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

    【讨论】:

    • 出于某种原因,Guava 没有 ushortubyte 类型。特别是ubyte 是最有用的。你知道为什么吗?
    • short 出现问题:code.google.com/p/guava-libraries/issues/detail?id=670byte 出现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
    

    【讨论】:

      猜你喜欢
      • 2017-09-11
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 2010-09-24
      • 2011-01-08
      • 1970-01-01
      • 2013-09-23
      • 2010-11-12
      相关资源
      最近更新 更多