java.util.BitSet,采用位运算;

官方API:http://docs.oracle.com/javase/7/docs/api/java/util/BitSet.html

摘要: BitSet的使用场景及简单示例,可用于在JAVA程序中实现unqiue功能。

BitSet简介

类实现了一个按需增长的位向量。位 set 的每个组件都有一个boolean值。用非负的整数将BitSet的位编入索引。可以对每个编入索引的位进行测试、设置或者清除。通过逻辑与、逻辑或和逻辑异或操作,可以使用一个BitSet修改另一个BitSet的内容。

默认情况下,set 中所有位的初始值都是false。

每个位 set 都有一个当前大小,也就是该位 set 当前所用空间的位数。注意,这个大小与位 set 的实现有关,所以它可能随实现的不同而更改。位 set 的长度与位 set 的逻辑长度有关,并且是与实现无关而定义的。

除非另行说明,否则将 null 参数传递给BitSet中的任何方法都将导致NullPointerException。

在没有外部同步的情况下,多个线程操作一个BitSet是不安全的

基本原理

BitSet是位操作的对象,值只有0或1即false和true,内部维护了一个long数组,初始只有一个long,所以BitSet最小的size是64,当随着存储的元素越来越多,BitSet内部会动态扩充,最终内部是由N个long来存储,这些针对操作都是透明的。

用1位来表示一个数据是否出现过,0为没有出现过,1表示出现过。使用用的时候既可根据某一个是否为0表示,此数是否出现过。

一个1G的空间,有 8*1024*1024*1024=8.58*10^9bit,也就是可以表示85亿个不同的数

使用场景

常见的应用是那些需要对海量数据进行一些统计工作的时候,比如日志分析、用户数统计等等

如统计40亿个数据中没有出现的数据,将40亿个不同数据进行排序等。
    现在有1千万个随机数,随机数的范围在1到1亿之间。现在要求写出一种算法,将1到1亿之间没有在随机数中的数求出来

代码示例

package util;

import java.util.Arrays;
import java.util.BitSet; public class BitSetDemo { /**
* 求一个字符串包含的char
*
*/
public static void containChars(String str) {
BitSet used = new BitSet();
for (int i = 0; i < str.length(); i++)
used.set(str.charAt(i)); // set bit for char StringBuilder sb = new StringBuilder();
sb.append("[");
int size = used.size();
System.out.println(size);
for (int i = 0; i < size; i++) {
if (used.get(i)) {
sb.append((char) i);
}
}
sb.append("]");
System.out.println(sb.toString());
} /**
* 求素数 有无限个。一个大于1的自然数,如果除了1和它本身外,不能被其他自然数整除(除0以外)的数称之为素数(质数) 否则称为合数
*/
public static void computePrime() {
BitSet sieve = new BitSet(1024);
int size = sieve.size();
for (int i = 2; i < size; i++)
sieve.set(i);
int finalBit = (int) Math.sqrt(sieve.size()); for (int i = 2; i < finalBit; i++)
if (sieve.get(i))
for (int j = 2 * i; j < size; j += i)
sieve.clear(j); int counter = 0;
for (int i = 1; i < size; i++) {
if (sieve.get(i)) {
System.out.printf("%5d", i);
if (++counter % 15 == 0)
System.out.println();
}
}
System.out.println();
} /**
* 进行数字排序
*/
public static void sortArray() {
int[] array = new int[] { 423, 700, 9999, 2323, 356, 6400, 1,2,3,2,2,2,2 };
BitSet bitSet = new BitSet(2 << 13);
// 虽然可以自动扩容,但尽量在构造时指定估算大小,默认为64
System.out.println("BitSet size: " + bitSet.size()); for (int i = 0; i < array.length; i++) {
bitSet.set(array[i]);
}
//剔除重复数字后的元素个数
int bitLen=bitSet.cardinality(); //进行排序,即把bit为true的元素复制到另一个数组
int[] orderedArray = new int[bitLen];
int k = 0;
for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
orderedArray[k++] = i;
} System.out.println("After ordering: ");
for (int i = 0; i < bitLen; i++) {
System.out.print(orderedArray[i] + "\t");
} System.out.println("iterate over the true bits in a BitSet");
//或直接迭代BitSet中bit为true的元素iterate over the true bits in a BitSet
for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
System.out.print(i+"\t");
}
System.out.println("---------------------------");
} /**
* 将BitSet对象转化为ByteArray
* @param bitSet
* @return
*/
public static byte[] bitSet2ByteArray(BitSet bitSet) {
byte[] bytes = new byte[bitSet.size() / 8];
for (int i = 0; i < bitSet.size(); i++) {
int index = i / 8;
int offset = 7 - i % 8;
bytes[index] |= (bitSet.get(i) ? 1 : 0) << offset;
}
return bytes;
} /**
* 将ByteArray对象转化为BitSet
* @param bytes
* @return
*/
public static BitSet byteArray2BitSet(byte[] bytes) {
BitSet bitSet = new BitSet(bytes.length * 8);
int index = 0;
for (int i = 0; i < bytes.length; i++) {
for (int j = 7; j >= 0; j--) {
bitSet.set(index++, (bytes[i] & (1 << j)) >> j == 1 ? true
: false);
}
}
return bitSet;
} /**
* 简单使用示例
*/
public static void simpleExample() {
String names[] = { "Java", "Source", "and", "Support" };
BitSet bits = new BitSet();
for (int i = 0, n = names.length; i < n; i++) {
if ((names[i].length() % 2) == 0) {
bits.set(i);
}
} System.out.println(bits);
System.out.println("Size : " + bits.size());
System.out.println("Length: " + bits.length());
for (int i = 0, n = names.length; i < n; i++) {
if (!bits.get(i)) {
System.out.println(names[i] + " is odd");
}
}
BitSet bites = new BitSet();
bites.set(0);
bites.set(1);
bites.set(2);
bites.set(3);
bites.andNot(bits);
System.out.println(bites);
} public static void main(String args[]) {
//BitSet使用示例
BitSetDemo.containChars("How do you do? 你好呀");
BitSetDemo.computePrime();
BitSetDemo.sortArray();
BitSetDemo.simpleExample(); //BitSet与Byte数组互转示例
BitSet bitSet = new BitSet();
bitSet.set(3, true);
bitSet.set(98, true);
System.out.println(bitSet.size()+","+bitSet.cardinality());
//将BitSet对象转成byte数组
byte[] bytes = BitSetDemo.bitSet2ByteArray(bitSet);
System.out.println(Arrays.toString(bytes)); //在将byte数组转回来
bitSet = BitSetDemo.byteArray2BitSet(bytes);
System.out.println(bitSet.size()+","+bitSet.cardinality());
System.out.println(bitSet.get(3));
System.out.println(bitSet.get(98));
for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
System.out.print(i+"\t");
}
}
}

参考:http://www.cnblogs.com/yellowb/p/3647442.html

参考:http://blog.csdn.net/haojun186/article/details/8482343

转载自:https://my.oschina.net/cloudcoder/blog/294810

Java中BitSet使用(转)的更多相关文章

  1. java中的BitSet

    (1)BitSet类     大小可动态改变, 取值为true或false的位集合.用于表示一组布尔标志. 此类实现了一个按需增长的位向量.位 set 的每个组件都有一个 boolean 值.用非负的 ...

  2. Bitmap在Java中的实现和应用

    >>40亿数据排序问题 给定一个最多包含40亿个随机排列的32位整数的顺序文件,找出一个不在文件中的32位整数(在文件中至少缺失这样一个数——为什么?).在具有足够内存的情况下,如何解决该 ...

  3. 解决java中对URL编码的问题

    首先查看javascript中的encodeURI和encodeURLComponent方法的区别. encodeURI:不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行 ...

  4. Java数据结构: java.util.BitSet源码学习

    接着上一篇Blog:一道面试题与Java位操作 和 BitSet 库的使用,分析下Java源码中BitSet类的源码. 位图(Bitmap),即位(Bit)的集合,是一种常用的数据结构,可用于记录大量 ...

  5. java.util.BitSet 详细分析 学习笔记

    1,BitSet类    大小可动态改变, 取值为true或false的位集合.用于表示一组布尔标志.   此类实现了一个按需增长的位向量.位 set 的每个组件都有一个 boolean 值.用非负的 ...

  6. Bitmap在Java中的应用

    一.40亿数据排序问题 给定一个最多包含40亿个随机排列的32位整数的顺序文件,找出一个不在文件中的32位整数(在文件中至少缺失这样一个数——为什么?).在具有足够内存的情况下,如何解决该问题?(编程 ...

  7. Java中的数组与集合

    此文转载自:http://student-lp.iteye.com/blog/2082362 在java编程的过程中,我们不能确定某一类型的对象到底会需要多少,为了解决这个问题,java提供了容纳对象 ...

  8. Java面试题:Java中的集合及其继承关系

    关于集合的体系是每个人都应该烂熟于心的,尤其是对我们经常使用的List,Map的原理更该如此.这里我们看这张图即可: 1.List.Set.Map是否继承自Collection接口? List.Set ...

  9. Java中的容器(集合)之ArrayList源码解析

    1.ArrayList源码解析 源码解析: 如下源码来自JDK8(如需查看ArrayList扩容源码解析请跳转至<Java中的容器(集合)>第十条):. package java.util ...

随机推荐

  1. ExtJS学习-----------Ext.String,ExtJS对javascript中的String的扩展

    关于ExtJS对javascript中的String的扩展,能够參考其帮助文档,文档下载地址:http://download.csdn.net/detail/z1137730824/7748893 以 ...

  2. Observer 观察者模式

    简介       观察者模式(Observer),有时又被称为[发布]publish-[订阅]Subscribe模式.模型-视图(View)模式.源-收听者(Listener)模式或从属者模式.在此种 ...

  3. 9.7noip模拟试题

    题目名称 日历游戏 最大公约数 密码 英文代号 calendar gcd pasuwado 输入文件名 calendar.in gcd.in pasuwado.in 输出文件名 calendar.ou ...

  4. 9.2noip模拟试题

      题目名称 改造二叉树 数字对 交换 英文名称 binary pair swap 输入文件名 binary.in pair.in swap.in 输出文件名 binary.out pair.out ...

  5. Filter过滤器实现同一地址手机和电脑页面不同

    最近做一个网站,客户要求在访问主域名的时候实现电脑访问时展示电脑页面,手机访问时展示h5的手机页面,这种需求的使用还是比较多的:尤其网站需要百度推广的时候,百度推广就要求同一域名下,手机访问时展示手机 ...

  6. Linq编程101例

    原文地址:101 LINQ Samples in C# Part1 - Restriction Operators Part2 - Projection Operators Part3 - Parti ...

  7. c - 向一个排序好的数组插入一个数,插入后数组依然是排序好的

    概述 因为这里只是演示插入1个数,这里我不用malloc再重新分配,而是将原先数组的腾出一个占位符. 完整代码如下: #include <stdio.h> #define LEN 6 // ...

  8. Protocol Buffer Xcode 正确使用思路 成功安装 Xcode7.1

    1. 下载protobuf编译工具 序列化是将数据转换为一个特定的类 http://pan.baidu.com/s/1qWrxHxU 下载解压,它不是用来放在你的项目里 2.打开终端 依次输入并等待指 ...

  9. 二套小清新(APP界面)

                   

  10. WebAPI下的如何实现参数绑定

    本文将概述在WebAPI方式下将如何将参数绑定到一个action方法,包括参数是如何被读取,一系列规则决定特定环境采用的那种绑定方式,文章最后将给出一些实际的例子. Parameter binding ...