先提一个问题,怎么在40亿个整数中找到那个唯一重复的数字?

  第一想法就是Set的不可重复性,依次把每个数字放入HashSet中,当放不去进去的时候说明这就是重复的数字,输出这个数字。

  

 if(hs.contains(x))
System.out.println("重复的数字是"+x);
else{
hs.add(x);
}

  但是,

  

 HashSet里contains():
public boolean contains(Object o) {
return map.containsKey(o);
}
HashMap里containsKey():
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
HashMap里getEntry():
final Entry<K,V> getEntry(Object key) {
if (size == 0) {
return null;
} int hash = (key == null) ? 0 : hash(key);
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}

  但是怎么说呢,contains()方法消耗的时间,消耗的空间很大,毕竟有约40亿的数据,所以觉得HashSet是不可取的。

  然后百度了,发现了BitSet这个神奇的东西。

  源代码就不贴了,简述下为什么用BitSet能行。

   BitSet就是位图,它的值只有1和0。内部是基于long[]实现的,long是8字节(64位),所以Bitset最小是64位,每次扩大一次扩大64位,即内部大小是64的倍数。每次BitSet新增加一个数字时,就将该位置为1。

  也就是说BitSet并不直接存储每个数据,而是存储数字是否存在过(1表示存在,0表示不存在)。

   

|---------------|-----------|-------------|-------------|----------|
|
| 数字范围 [0,63] [64,127] [128,191] ......... |
|---------------|-----------|-------------|-------------|----------|
|
| long数组索引 0 1 2 ........ |
|---------------|-----------|-------------|-------------|----------|

  若添加一个数字 10 ,那么将long[0]的二进制位中从左往右第十个数置为1,

  若添加一个数字 64 ,那么将long[1]的二进制位中从左往右第一个数置为1,没有添加的数字所在位数是0,用此方法就可记录一个数字是否在BitSet中。

  

 import java.util.*;

 public class Main{
public static void main(String[] args) throws Exception{
BitSet bs = new BitSet();
int[] nums={1,2,3,4,5,6,7,8,9,10,10};
for (int num : nums) {
if(bs.get(num)){
System.out.println(num); //
break;
}else {
bs.set(num);
}
}
}
}

  

再提个问题,40亿个数中,给你一个数X,怎么判断X是否在40亿个数中呢?

  二分查找 (理论上的想法,其实我也不知道能不能行..o(>﹏<)o)

  先将数据转为二进制数(其实很多地方都可以转二进制计算,比如IP地址),31位二进制可表示约21亿,那么40亿需要32位二进制。将40亿数最高位按1、0分开,那么就分成了0-21亿,21-40亿两部分,然后次最高位按1、0分开.....

  

  然后把需要查找的数字转为32位的二进制,只要从最高位依次往下比较即可。假如重复数字是在【A,B】间,B-A=100000(在我电脑上,进行100000次的for循环查找需要3ms,所以是能接受的),大概位数要比较二三十次,在计算机中比较二三十次的位数非常快。

Java BitSet解决海量数据去重的更多相关文章

  1. paip.java OutOfMemoryError 解决方法o33

    paip.java OutOfMemoryError 解决方法o33 java.lang.OutOfMemoryError: Requested # java.lang.OutOfMemoryErro ...

  2. java中解决组件重叠的问题(例如鼠标移动组件时)

    java中解决组件覆盖的问题!     有时候在移动组件的时候会出现两个组件覆盖的情况,但是你想让被覆盖的组件显示出来或者不被覆盖! 在设计GUI时已经可以定义组件的叠放次序了(按摆放组件的先后顺序) ...

  3. java多线程解决生产者消费者问题

    import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class ...

  4. Java 异常解决之java.lang.IllegalArgumentException: Comparison method violates its general contract!

    Java 异常解决 在你的代码前加一句 System.setProperty("java.util.Arrays.useLegacyMergeSort", "true&q ...

  5. [转]java nio解决半包 粘包问题

    java nio解决半包 粘包问题 NIO socket是非阻塞的通讯模式,与IO阻塞式的通讯不同点在于NIO的数据要通过channel放到一个缓存池ByteBuffer中,然后再从这个缓存池中读出数 ...

  6. jsp页面传输到xxAction.java乱码解决

    jsp页面传输到xxAction.java乱码解决:jsp:encodeURI(encodeURI("xx"))java:if(!StringUtils.isBlank(belon ...

  7. 用eclipse 检索SVN 上 myEclipse 建的web项后,成java项目解决方法

    用eclipse 检索SVN 上 myEclipse 建的web项后,成java项目解决方法 在网上找了非常多,都无论用. 说添加.project 文件几个属性.但我发现里面都有,在我这里无论什么用. ...

  8. 【poi】解决java导出excel 海量数据内存溢出问题

    转自百度经验:http://jingyan.baidu.com/article/4853e1e5202c331909f72627.html 那里排版忒恶心,转来这里. 由于项目中有导出海量数据的需求, ...

  9. 海量数据去重之SimHash算法简介和应用

    SimHash是什么 SimHash是Google在2007年发表的论文<Detecting Near-Duplicates for Web Crawling >中提到的一种指纹生成算法或 ...

随机推荐

  1. 图片上传js

    var imgURL; function getImgURL(node) { try{ var file = null; if(node.files && node.files[0] ...

  2. VUE处理 组件赋值 watch 监听不到赋值问题

    开发中,遇到了一个BUG,做的页面类似于 导航切换效果.两个组件传值. 上方导航组件   (主动) 左侧导航组件   (被动) 点击上方导航,左侧导航实现变换对应的栏目. 实现过程中,遇到了点问题.左 ...

  3. java中对类中成员的排序

    要求:编写一个程序.程序中定义一个类circle,其中有数据成员radius:创建一个有5个circle型元素的数组,其radius值分别为2.10.8.4.121.调用Arrays.sort()给这 ...

  4. 更改Windows更新源(解决公司内部网络无法下载语言包或更新的问题)

    打开注册表 找到HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate 将WUServer.WUStatusServe ...

  5. 剑指Offer 63. 数据流中的中位数(其他)

    题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值.我们 ...

  6. mysql数据库的备份

    有时会遇到需要重装虚拟机的情况,这时候之前创建好的数据库就需要备份啦,等重新装好虚拟机直接导入就可以正常使用. 数据库备份大体分为两步: 第一步.导出数据库,因为是备份,会将所有的数据库导出,因此需要 ...

  7. django channle的使用

    频道在PyPI上可用 - 要安装它,只需运行:   参照:https://channels.readthedocs.io/en/latest/introduction.html pip install ...

  8. svg的使用集合

    1.效果 https://www.zhangxinxu.com/wordpress/2017/03/offset-path-css-animation/ 2.用法 https://www.cnblog ...

  9. oracle 数据库备份expdp、impdp

    跳转查看:https://blog.csdn.net/qq_26230421/article/details/79382013 或 https://www.cnblogs.com/promise-x/ ...

  10. String formate的语法解析及简单用法

    转自:https://blog.csdn.net/jiangyu1013/article/details/52607257 package cn.wuxiangbin.StringFormat; im ...