roaringbitmap 源代码解析(3)底层容器相互add过程

今天主要讲述roaringbitmap的add计算。

自己带上来源,防拷贝:http://blog.csdn.net/chenfenggang/article/details/74788617

先判断高位是否存在相同的,如果相同,再低位的容器相add。否则,直接跳过

public static RoaringBitmap and(final RoaringBitmap x1, final RoaringBitmap x2) {
  final RoaringBitmap answer = new RoaringBitmap();
  final int length1 = x1.highLowContainer.size(), length2 = x2.highLowContainer.size();
  int pos1 = 0, pos2 = 0;

  while (pos1 < length1 && pos2 < length2) {
    final short s1 = x1.highLowContainer.getKeyAtIndex(pos1);
    final short s2 = x2.highLowContainer.getKeyAtIndex(pos2);
    if (s1 == s2) {    //相同则求交集,
      final Container c1 = x1.highLowContainer.getContainerAtIndex(pos1);
      final Container c2 = x2.highLowContainer.getContainerAtIndex(pos2);
      final Container c = c1.and(c2);
      if (c.getCardinality() > 0) {
        answer.highLowContainer.append(s1, c);
      }
      ++pos1;
      ++pos2;
    } else if (Util.compareUnsigned(s1, s2) < 0) { // s1 < s2   //不同直接移位pos1到 接近相同的位置
      pos1 = x1.highLowContainer.advanceUntil(s2, pos1);
    } else { // s1 > s2
      pos2 = x2.highLowContainer.advanceUntil(s1, pos2);
    }
  }
  return answer;
}

advanceUntil的主要作用是找到下一个位置。

所以今天主要是正对bitmapContainer 和 arrayContainer 以及runContainer之间的add计算
几个基本准则。
add满足交换律:也就是 runContainer.add(runContainer) = runContainer.add(runContainer);
add满足最小准则:。 bitmapContainer.add(arrayContainer) .结果一定是arrayContainer能放下。

几个加法
1)首先arrayContainer.add(arrayContainer)

@Override
public ArrayContainer and(final ArrayContainer value2) {
  ArrayContainer value1 = this;
  final int desiredCapacity = Math.min(value1.getCardinality(), value2.getCardinality());
  ArrayContainer answer = new ArrayContainer(desiredCapacity);
  answer.cardinality = Util.unsignedIntersect2by2(value1.content, value1.getCardinality(),
      value2.content, value2.getCardinality(), answer.content);
  return answer;
}

这里主要是求出最小能使用到空间,然后求交集。求交集unsignedIntersect2by2 这个做了一些优化。
如果两者直接的差距大于25倍(以前的代码好像是64,所以这个值不值得是统计结果还是测试结果。)采用小数组每次移动一位。
然后跳跃性移动大数组。
否则采用两者都只是移动到下一位,然后进行判断。

@Override
public ArrayContainer and(final ArrayContainer value2) {
  ArrayContainer value1 = this;
  final int desiredCapacity = Math.min(value1.getCardinality(), value2.getCardinality());
  ArrayContainer answer = new ArrayContainer(desiredCapacity);
  answer.cardinality = Util.unsignedIntersect2by2(value1.content, value1.getCardinality(),
      value2.content, value2.getCardinality(), answer.content);
  return answer;
}

第二 bitmap + bitmap
首先估计一下and操作后的长度,如果大于4096 则用bitmap 这个计算简单,否则用Array

@Override
public Container and(final BitmapContainer value2) {
  int newCardinality = 0;
  for (int k = 0; k < this.bitmap.length; ++k) {
    newCardinality += Long.bitCount(this.bitmap[k] & value2.bitmap[k]);
  }
  if (newCardinality > ArrayContainer.DEFAULT_MAX_SIZE) {
    final BitmapContainer answer = new BitmapContainer();
    for (int k = 0; k < answer.bitmap.length; ++k) {
      answer.bitmap[k] = this.bitmap[k] & value2.bitmap[k];
    }
      answer.cardinality = newCardinality;
    return answer;
  }
  ArrayContainer ac = new ArrayContainer(newCardinality);
  Util.fillArrayAND(ac.content, this.bitmap, value2.bitmap);
  ac.cardinality = newCardinality;
  return ac;
}

第三 bitmap+array
因为array and bitmap = bitmap and array。所以实现代码放在bitmap里面

@Override
public ArrayContainer and(final ArrayContainer value2) {
  final ArrayContainer answer = new ArrayContainer(value2.content.length);
  int c = value2.cardinality;
  for (int k = 0; k < c; ++k) {
    short v = value2.content[k];
    answer.content[answer.cardinality] = v;
    answer.cardinality += this.bitValue(v);
  }
  return answer;
}

这个代码好像缺了点什么。应该是循环内部加一个判断才对否则就只直接返回array了

for (int k = 0; k < c; ++k) {
  short v = value2.content[k];
  if(this.contains(v)) {
    answer.content[answer.cardinality] = v;
    answer.cardinality += this.bitValue(v);
  }
}

吓得我感觉去git 提交的一个issue.也不知道会有什么结果。

没想到还真给我回复了,可惜我错了,里面用来一个bitValue。如果这个bitValue==1 则移位到一个坑中。否则即使你放任何值
都会被后面的值覆盖。
这个比较狠。轻松找到是否存在。

protected long bitValue(final short i) {
  final int x = Util.toIntUnsigned(i);
  return (bitmap[x / 64] >>> x ) & 1;
}

run+array 和run+bitmap 思路和上面的差不多,总而言之就是。先确定范围。然后在计算。然后再优化计算。

未完待续。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值