【问题标题】:Is byte more efficient than boolean[8] [duplicate]字节比布尔值更有效[8] [重复]
【发布时间】:2013-12-24 03:21:57
【问题描述】:

如果我在一个类中需要 8 个布尔成员变量,Java 是否有效地将它们全部放在一个字节中?或者它会为每个使用一个字节?换句话说,内存占用是否不同:

boolean a;
boolean b;
boolean c;
boolean d;
boolean e;
boolean f;
boolean g;
boolean h;

对比

public static final int a = 0x01;
public static final int b = 0x02;
public static final int c = 0x04;
public static final int d = 0x08;
public static final int e = 0x10;
public static final int f = 0x20;
public static final int g = 0x40;
public static final int h = 0x80;
byte flags;

我问是因为我将实例化 很多 这些对象。所以让它占用 1 个字节而不是 8 个字节的内存将是一个显着的节省。

更新:这绝对类似于列出布尔值存储在 int 中的链接问题(感谢您提供这些链接,抱歉在询问之前我没有找到它们)。这个问题有点不同,因为它提出了使用字节和位标志的具体替代方案。我不知道这是否足以使这个问题不再重复。

更新 2: 我刚刚使用 SizeofUtil 运行了它,发现以下内容。 8 个布尔值需要 24 个字节/对象或 3 个字节/布尔值。单字节方法需要 10 个字节/对象。我会理解 8 它将一个字节扩展为本机 int (我在 64 位系统上)。但是另外 2 个字节是怎么回事?

【问题讨论】:

  • 我敢打赌,在 64 位机器上,它会将它们分开 8 个字节。但这取决于JVM。在内存方面浪费,但在性能方面却没有。
  • 是的,效率更高
  • 出于不言自明的原因,boolean 必须是保存布尔值以满足通常要求的最佳数据结构;否则将使用其他东西。我有一种感觉,通常的要求可能是以牺牲内存为代价的访问速度。你想牺牲访问速度吗?
  • Boolean 只是 JLS 的 定义 中的 最佳 类型。在速度方面,boolean 在 VM 的实现中有一些怪癖,这使得它可能比 uning 一个完整的 int 用于相同的目的(使用 C 风格的非零 == TRUE) .布尔值的问题在于,它们几乎不可避免地需要在代码中引入分支的字节码(例如,实现“boolean b = x == y”,其中 c-style 可以说“int b = x - y”)。您可以使用 javap 进行检查。

标签: java


【解决方案1】:

Java 中布尔值表示的实际信息是一位:1 为真,0 为假。然而,布尔变量在内存中的实际大小并没有被 Java 规范精确定义。

布尔数据类型只有两个可能的值:真和假。 将此数据类型用于跟踪真/假条件的简单标志。 这种数据类型代表一位信息,但它的“大小” 不是精确定义的东西。

因此,如果您要创建大量布尔值,最好使用byte

【讨论】:

    【解决方案2】:

    阅读主题"How much memory does a boolean consume?"。他们建议 BitSet 作为大型布尔值集的解决方案,但在您的情况下,byte 可以更好地解决问题,因为您不会拥有大量布尔值,您将拥有大量 8 个布尔对象。

    总结:字节优于 8 个布尔值。

    【讨论】:

    • 除非他想出一种方法来对 BitSet 进行分区,以便通过这 8 个布尔字段在数百个对象之间共享...每个对象都可以有一个索引号 n,并使用字段8*n8*n +7 在 8 个布尔值的共享位集中。这可能比你真正想要处理的更混乱。
    • @dcsohl 它在内存使用上的结果几乎相同,所以我认为使用字节会更好。就像 Andrey 回答节目一样,在 JDK 中,它们也使用掩码存储布尔值。
    • @dcsohl 共享的 BitSet 需要 一些 形式的引用,该引用至少会占用与字节一样多的内存。不是一个实际的想法。
    • 是的,你是对的。那好吧。
    【解决方案3】:

    这取决于 VM 如何在内存中实现字段。

    但常识表明,在对象中使用每个字段在其自己的内存槽中实现它要容易得多,而且它的大小也取决于 VM,可能是一个字节或更大的东西(我猜是 int )。

    您可以通过创建包含大量此类对象的数组(比如说 10M)并检查使用了多少内存(例如运行时 API)来衡量特定 VM 的情况。

    但只有当我有严重的内存问题时,我才会担心这个。使用布尔值,您可以在真正需要时将其重新实现为标志字段(前提是您不会使用 直接 字段访问并使用 getters )。

    【讨论】:

      【解决方案4】:

      如果查看 JDK 8 的 Spliterator,他们仍在使用位掩码,我能想到的唯一原因是内存效率:

       public static final int DISTINCT   = 0x00000001;
       public static final int SORTED     = 0x00000004;
       public static final int ORDERED    = 0x00000010;
       public static final int SIZED      = 0x00000040;
      

      所以这应该是一个很好的方法。

      【讨论】:

      • 我会等到 JDK 8 最终确定后再推荐它的实现...
      猜你喜欢
      • 2016-07-06
      • 2016-04-02
      • 2015-05-02
      • 1970-01-01
      • 1970-01-01
      • 2014-02-13
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      相关资源
      最近更新 更多