【问题标题】:java - how to create and manipulate a bit array with length of 10 million bitsjava - 如何创建和操作长度为 1000 万位的位数组
【发布时间】:2013-03-22 03:00:00
【问题描述】:

我刚遇到一个问题;用伪代码很容易解决,但是当我开始用 java 编码时;我开始意识到我不知道从哪里开始......

这是我需要做的:

  1. 我需要一个大小为 1000 万(位)的位数组(我们称之为 A)。
  2. 我需要能够将此数组中的元素设置为 1 或 0 (A[99000]=1)。
  3. 我需要遍历这 1000 万个元素。

【问题讨论】:

  • @HunterMcMillen:这应该是答案,也是唯一可以接受的答案。
  • 感谢亨特麦克米伦!
  • 你们建议如何设置一个位数组 1000000000000000 ?对于我的一生,我似乎可以找到答案!

标签: java bitmap


【解决方案1】:

Java 中的“正确”方法是使用 Hunter McMillen 指出的已经存在的 BitSet 类。如果您只是为了思考一个有趣的问题而弄清楚如何管理大型位数组,那么计算字节数组中位的位置只是基本的模运算。

public class BitArray {

    private static final int ALL_ONES = 0xFFFFFFFF;
    private static final int WORD_SIZE = 32;
    private int bits[] = null;

    public BitArray(int size) {
        bits = new int[size / WORD_SIZE + (size % WORD_SIZE == 0 ? 0 : 1)];
    }

    public boolean getBit(int pos) {
        return (bits[pos / WORD_SIZE] & (1 << (pos % WORD_SIZE))) != 0;
    }

    public void setBit(int pos, boolean b) {
        int word = bits[pos / WORD_SIZE];
        int posBit = 1 << (pos % WORD_SIZE);
        if (b) {
            word |= posBit;
        } else {
            word &= (ALL_ONES - posBit);
        }
        bits[pos / WORD_SIZE] = word;
    }

}

【讨论】:

  • 谢谢你,我不得不稍微改变一下,因为我正在做的是小端序
  • @Midnightas,你是如何改变它的? Java 本身与字节序无关。数组首先存储最不重要的 int,这已经是 little-endian 方式。但总体而言,该类的设计使得排序从用户那里抽象出来。
  • (另外,虽然从这个例子中学习很好,但您可能应该在现实生活中使用 BitSet 以获得更快的速度/稳健性。)
  • @mwfearnley 它按以下顺序读取位:7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,等等……
  • @mwfearnley 而且 BitSet 没有我需要的一些功能。
【解决方案2】:

使用BitSet(正如 Hunter McMillen 在评论中指出的那样)。您可以轻松地使用getset 位。要进行迭代,只需使用普通的 for 循环即可。

【讨论】:

    【解决方案3】:

    这里是 phatfingers 'BitArray'

    的更优化的实现
    class BitArray {
    
        private static final int MASK = 63;
        private final long len;
        private long bits[] = null;
    
        public BitArray(long size) {
            if ((((size-1)>>6) + 1) > 2147483647) {
                throw new IllegalArgumentException(
                    "Field size to large, max size = 137438953408");
            }else if (size < 1) {
                throw new IllegalArgumentException(
                    "Field size to small, min size = 1");
            }
            len = size;
            bits = new long[(int) (((size-1)>>6) + 1)];
        }
    
        public boolean getBit(long pos) {
            return (bits[(int)(pos>>6)] & (1L << (pos&MASK))) != 0;
        }
    
        public void setBit(long pos, boolean b) {
            if (getBit(pos) != b) { bits[(int)(pos>>6)] ^= (1L << (pos&MASK)); }
        }
    
        public long getLength() {
            return len;
        }
    }
    

    由于我们使用 64 个字段,我们将最大大小扩展到 137438953408 位,这大致适合 16GB 的内存。此外,我们使用掩码和位移来代替除法和模运算,以减少计算时间。改进是相当可观的。

    【讨论】:

      【解决方案4】:
      byte[] A = new byte[10000000];
      A[99000] = 1;
      for(int i = 0; i < A.length; i++) {
          //do something
      }
      

      如果你真的想要位,你可以使用布尔值,让 true = 1,false = 0。

      boolean[] A = new boolean[10000000];
      //etc
      

      【讨论】:

      • @SotiriosDelimanolis 这使用了 8000 万位。所以 1000 万字节。
      • hmmm - 一个布尔值大小为一位的问题?
      • 布尔值作为 32 位实体进行操作,但布尔数组每个元素使用 1 个字节。
      猜你喜欢
      • 2014-10-07
      • 2010-11-19
      • 2021-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-23
      相关资源
      最近更新 更多