`
lenozhi
  • 浏览: 51025 次
社区版块
存档分类
最新评论

将HashMap文件化

阅读更多

   ( 只是个想法加雏形,实现的很丑陋且效率很低下)

    有这样一种场景,校验千万行文本中某一列键值(长度30以上)的唯一性(要求100%准确)。按我的水平,自然就想到用HashMap,可这样就会将所有的键值都放入内存,对内存资源需求较大。然后我就想,数据库也有一样的需求呀,人家怎么搞的呢?思前想后,能力太有限,没思路。最后只能想到,如果把HashMap的存储介质由内存转移到外存(文件中),貌似会节省相当部分的内存(此假设未经证实)。于是着手改造,HashMap实现的主要算法基本了解只是对于寻址那块要从内存转入文件,这是关键。由此做了如下设计:

 

HashMap的put方法中:

由hashcode算出在table中的位置i,然后以table[i]为链首存储元素。

 

我的思路:

建一个索引文件,每个索引的结构:数据项+后继索引位置。索引长度:数据项长度+long型的长度(8字节)

table[i]即链首的位置 = i * 数据项长度+8

当首次写入链首时,索引位置埴0,因为下一个元素未知嘛。

当table[i]第n个元素写入时,从链首开始遍历(取后继索引位置,跳转至该位置),直到遍历索引位置为0的链表元素,将要写入第n个元素的文件位置记到此后继索引位置,并将第n个元素写入文件。如果遍历时发现,当前元素数据项与要写入元素的数据项值相同,则发现重复元素。

 

 

 

目前的问题:

1. io操作过多,考虑是不是可以通过内存映像文件来提高提高效率。当然加加cache也行,就是没考虑好怎么加。

2. 还木有想到。。。

 

 

上传了我丑陋的代码,运行FileMap就好。 

 

试用了一下jdbm-2.0.jar这个包,100万行数据插入,就是从1到100万,10行一提交。共用了38秒。使用内存14M左右,太NB。严重鄙视我提交的烂代码。

分享到:
评论
32 楼 lenozhi 2011-04-25  
iamlotus 写道
lenozhi 写道
iamlotus 写道
你这行事先知道吗?
知道的话遍历一遍,把hash相同的在内存里比较不就完了?

遍历一遍得把所有的hash值都存下来是吧,不然咋知道有hash相同的?这值到是可以把value设成空,可以节省内存空间。嗯。。等下,遍历一遍貌似得两个循环吧,不然咋找?

iamlotus 写道

不知道就学数据库建B+树,用file based hash空间太大,肯定不合算。其实不用那么麻烦,建张表,建个UK,然后全部insert进去不就完了?千万而已,又不是千亿,数据库吃得消。


用数据库整到是没试过,千万的话,字符串长度32,得多长时间?比如是个8核,64G的机器。


比如你有一组值A[]={A1 A2 A1 A3}, hash后分别是 {H1,H1,H1,H2} (假设A1,A2hash相等)
你的需求究竟是 “已知A1,问A中是否有和A1相同的值” 还是 “已知A,问其中有哪些值出现了一次以上”?
前者就是事先知道这行,后者就是不知道这行。
对前者,事先由A1算出 H1,然后遍历一遍A即可,连HashSet都不用,怎么会要两个循环?
后者你自己试试就知道时间了,配置不同不一样的。我估计不出插入时间,不过select应该能在20秒搞定。

是知道A,A存在于文件中。找出A中重复的。jdbm那个还不错,我试过。
31 楼 iamlotus 2011-04-25  
lenozhi 写道
iamlotus 写道
你这行事先知道吗?
知道的话遍历一遍,把hash相同的在内存里比较不就完了?

遍历一遍得把所有的hash值都存下来是吧,不然咋知道有hash相同的?这值到是可以把value设成空,可以节省内存空间。嗯。。等下,遍历一遍貌似得两个循环吧,不然咋找?

iamlotus 写道

不知道就学数据库建B+树,用file based hash空间太大,肯定不合算。其实不用那么麻烦,建张表,建个UK,然后全部insert进去不就完了?千万而已,又不是千亿,数据库吃得消。


用数据库整到是没试过,千万的话,字符串长度32,得多长时间?比如是个8核,64G的机器。


比如你有一组值A[]={A1 A2 A1 A3}, hash后分别是 {H1,H1,H1,H2} (假设A1,A2hash相等)
你的需求究竟是 “已知A1,问A中是否有和A1相同的值” 还是 “已知A,问其中有哪些值出现了一次以上”?
前者就是事先知道这行,后者就是不知道这行。
对前者,事先由A1算出 H1,然后遍历一遍A即可,连HashSet都不用,怎么会要两个循环?
后者你自己试试就知道时间了,配置不同不一样的。我估计不出插入时间,不过select应该能在20秒搞定。
30 楼 lenozhi 2011-04-23  
iamlotus 写道
你这行事先知道吗?
知道的话遍历一遍,把hash相同的在内存里比较不就完了?

遍历一遍得把所有的hash值都存下来是吧,不然咋知道有hash相同的?这值到是可以把value设成空,可以节省内存空间。嗯。。等下,遍历一遍貌似得两个循环吧,不然咋找?

iamlotus 写道

不知道就学数据库建B+树,用file based hash空间太大,肯定不合算。其实不用那么麻烦,建张表,建个UK,然后全部insert进去不就完了?千万而已,又不是千亿,数据库吃得消。


用数据库整到是没试过,千万的话,字符串长度32,得多长时间?比如是个8核,64G的机器。
29 楼 iamlotus 2011-04-22  
你这行事先知道吗?
知道的话遍历一遍,把hash相同的在内存里比较不就完了?
不知道就学数据库建B+树,用file based hash空间太大,肯定不合算。其实不用那么麻烦,建张表,建个UK,然后全部insert进去不就完了?千万而已,又不是千亿,数据库吃得消。

28 楼 sx011966 2011-04-21  
把那个文本作为oracle 外部表,然后用sql来排除
27 楼 ray_linn 2011-04-21  
bloom过滤器
26 楼 lenozhi 2011-04-21  
试用了一下jdbm-2.0.jar这个包,100万行数据插入,就是从1到100万,10行一提交。共用了38秒。使用内存14M左右,太NB。严重鄙视我提交的烂代码。
25 楼 lenozhi 2011-04-21  
renwolang521 写道
看你这个HashMap文件化,我想是否可以遍历一遍,存到sqlite中然后利用数据库寻找重复的。
java使用sqlite 就一个jar包(http://www.zentus.com/sqlitejdbc/)就行了,最后形成的也就一个文件。用完文件直接删了就行了。


不错,我去试试。看看对大数据量的支持如何
24 楼 renwolang521 2011-04-21  
看你这个HashMap文件化,我想是否可以遍历一遍,存到sqlite中然后利用数据库寻找重复的。
java使用sqlite 就一个jar包(http://www.zentus.com/sqlitejdbc/)就行了,最后形成的也就一个文件。用完文件直接删了就行了。
23 楼 uin57 2011-04-21  
lenozhi 写道
shguan2010 写道
考虑一下 jdbm2
http://code.google.com/p/jdbm2/

不错的东东

为什么不试一下derby呢?
22 楼 lenozhi 2011-04-20  
shguan2010 写道
考虑一下 jdbm2
http://code.google.com/p/jdbm2/

不错的东东
21 楼 shguan2010 2011-04-20  
考虑一下 jdbm2
http://code.google.com/p/jdbm2/
20 楼 real_aaron 2011-04-20  
<p>如果不想重造轮子的话可以考虑使用oracle的 bdb je,其collections框架提供了map的持久化实现。 其中的 com.sleepycat.collections.StoredMap 应该能满足你的需要,要注意的是je是dual licence.</p>
<p> </p>
19 楼 ppgunjack 2011-04-20  
数据库是可以越过系统调用直接操纵磁盘,不过很多应用还是会架在OS的文件系统上访问数据
其实考虑类似bdb这样的嵌入式数据库比自己写类似应用要更容易,适用范围保护也更好,结合OS的内存虚拟磁盘使用可以很灵活构建方案
18 楼 咖啡豆子 2011-04-20  
首先看你的KEY是什么特点,设定一个规则,将HASHMAP分散到多个文件。不过我觉得这么搞还不如就放在数据库里好了
17 楼 lenozhi 2011-04-20  
ppgunjack 写道
索引大多都是B+树,可以保证分布平均,树深度不深,hash最坏的情况全落一个桶,唯一肯定是需要排序的,千万这个量不用纠结,与其考虑算法,应该优先考虑记录减肥降低磁盘io

原来是这样子,学习了。
16 楼 ppgunjack 2011-04-20  
索引大多都是B+树,可以保证分布平均,树深度不深,hash最坏的情况全落一个桶,唯一肯定是需要排序的,千万这个量不用纠结,与其考虑算法,应该优先考虑记录减肥降低磁盘io
15 楼 lenozhi 2011-04-20  
mtnt2008 写道
lenozhi 写道
kimmking 写道
直接用hashcode呗。

咋叫直接用hashcode,两个键值的hashcode相同咋办


hash冲突的处理方法:1.开放地址法 2.地址链法 3.再hash发

以前的一个思路:

1.把value通过MappedByteBuffer(java的内存文件映射)存入硬盘得到文件偏移量d;

2.对key做hash,以这个值为index,进行操作:桶数组[index] = d

3.如果发生hash冲突,选用一个处理hash冲突的方法


目前我用用RandomAccessFile整的,正要试试MappedByteBuffer。再配合加些cache,不知道能搞成啥样。
14 楼 lenozhi 2011-04-20  
JE帐号 写道
我的印象里java的io操作是比较弱的,文件操作性能很差.
所以说,新拿到一个值,虽然你可以算出来应该在什么位置,并用skip直接定位过去,可是在io内部还是给read中间哪些值. 再说,你向文件里插入一个值,我印象是不可能向链表似的前后改下索引就行了,好像给整个复制....

用RandomAccessFile可以实现我描述的(已经实现了)。

JE帐号 写道

反正,我以前用io的时候就是这个印象.
所以我一直觉得数据库应该对于文件系统的操作进行了底层的控制,比如从10000跳到20000,他是直接跳过去找到,而不是顺序读过去的.

数据库底层很可能是跳过文件系统,直接玩的。
13 楼 mtnt2008 2011-04-20  

准备实现自己的想法,写一个。到时欢迎大家拍砖 @-@

相关推荐

    java7hashmap源码-java:Java

    hashmap源码 Table Of Contents day01_JAVA语言概述与基本语法:标识符、变量也变量分类、源码_反码_补码、进制转换、编码与字符集 day02_基本语法.运算符:算术运算符、赋值运算符、比较运算符、逻辑运算符、位...

    HashMap关系数据映射技术软件jadepool-community-3.0

    JadePool3.0的主要变化是: 1、支持JTA分布式事务; 2、调整了DbCenter实例; 3、优化了键值生成器方法,并做了高并发性能测试;...JadePool3.0除了具备了简洁、高效、智能化的特性之外,还具备高并发性、高稳定性。

    java7hashmap源码-oa:办公自动化项目。进行到知识管理

    hashmap源码 oa系统 办公自动化项目。进行到知识管理。 1. 框架整合 1.1 整合主要步骤 使用java7,建立maven项目,配置pom文件。 建三个src folder src.main.java 存放源代码的 com.stillcoolme.oa.struts2.action ...

    java7hashmap源码-java-skill:JavaSkill,Java技能

    hashmap源码 JVM (1)基本概念 ​ JVM是可运行Java代码的假想计算器,包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收、堆和一个存储方法域。JVM是运行在操作系统之上,它与硬件没有直接的交互。 (2)运行...

    人工智能-项目实践-搜索引擎-java实验1-实现搜索引擎的倒排索引数据结构

    如果写文本文件,推荐使用PrintWriter,当创建好PrintWriter对象后,调用其println和print方法可以将字符串一行行的写入到文本文件,使用方法与System.out.println, System.out.print完全一样 具体使用方法,请见...

    Java编程实践:10个实用例子助您提升技能正则表达式、文件操作、日期和时间处理、数据结构、集合类、接口和多态、递归、多线程编程

    2. 读取和写入文本文件:展示了如何使用文件读取器和写入器来读取和写入文本文件的内容。 3. 使用日期和时间类:演示了Java 8中日期和时间类的用法,包括获取当前日期和格式化日期时间。 4. 实现链表数据结构:展示...

    spring集成redis,配置加代码例子

    springmvc框架加redis集成,redis直接在配置文件配置即可使用,实现了string,list,hashmap以及对象存储,将对象序列化成二进制格式存储,取出将二进制反序列化,代码有描述及例子

    银行卡系统(java控制台应用程序,给初学者参考,请先看描述)

    ),在BankBusiness文件夹中有个Account.txt文件用来存储账户信息(里头是乱码,因为是HashMap对象序列化而来)。其中包含四个类: 1、Bank(银行)。2、BankCardManage(银行管理)。3、BankMain(程序入口)。4、Card (银行卡...

    模拟实现Spring的IOC

    1、Spring主要两个作用:实例化Bean,动态装配Bean。并将所有的bean放到spring容器中,调用时从容器中取。Spring容器就是一个bean的Map:private Map, Object&gt; beans = new HashMap, Object&gt;(); 2、本工程,模拟...

    Java面试宝典(数据库篇).docx

    (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件 (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次 (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个...

    【大厂面试题总结】JavaSE面试题总结详细教程

    递归算法之输出某个目录下所有文件和子目录列表 泛型中extends和super的区别 内部类的理解 深入理解Java的反射机制 深入理解Java异常体系 谈谈NIO的理解 谈一谈对JUC的理解 ArrayList的底层原理 HashMap的底层原理 ...

    Android代码-RetrofitClient

    2 在MainApplication中初始化 HttpManager.init(this, UrlConfig.BASE_URL); HttpManager.getInstance().setOnGetHeadersListener(new HttpManager.OnGetHeadersListener() { @Override public Map getHeaders() {...

    【大厂面试题总结】JavaSE面试题合集及其答案,基本包括javaSE所有知识点和详细解释

    递归算法之输出某个目录下所有文件和子目录列表 泛型中extends和super的区别 内部类的理解 深入理解Java的反射机制 深入理解Java异常体系 谈谈NIO的理解 谈一谈对JUC的理解 ArrayList的底层原理 HashMap的底层原理 ...

    CST8130-Assignment-3:CST8130“数据结构”中的作业 #3 - Concordance Generator

    用户可以加载一个文本文件,然后程序将查看文本文件,并允许用户通过使用 HashMap 来查看哪些段落包含特定的单词,该 HashMap 包含一个包含段落的 ArrayList,其中的值为特定的段落用户输入的词。 当程序结束时,将...

    JAVA面试题最全集

    如何将数值型字符转换为数字(Integer,Double) 如何将数字转换为字符 如何取小数点前两位,并四舍五入。 4.日期和时间 如何取得年月日,小时分秒 如何取得从1970年到现在的毫秒数 如何获取某个日期是当月的...

    涵盖了90%以上的面试题

    hashmap的底层原理 hashmap产生死锁的原因 hashmap的容量为什么一定要是2的幂呢 TreeMap的底层原理 HashMap,Hashtable和ConcurrentHashMap的区别 在ArrayList和LinkedList尾部添加元素,谁的效率更高 如果HashMap或者...

    基础深化和提高-常用类

    FileInputStream、FileOutputStream、BufferedReader、BufferedWriter等:用于进行文件和流的输入输出操作,可以读取、写入文件和处理数据流。 字符串处理类: String、StringBuffer、StringBuilder等:用于处理...

    java实用工具包(新手型)

    对第2维的格式化(即列数据),通过实现PageCol接口,已经有javabean和hashmap两种的格式化 import com.miphone.newcard.source.*; import java.util.*; 1.ArrayList source=.......; //不需要转化 2....

    python-javaobj:python-javaobj是一个python库,提供了读取Java对象序列化ObjectOutputStream的函数

    自动将 Java 集合转换为 python 集合( HashMap =&gt; dict、 ArrayList =&gt; list 等) 要求 Python &gt;= 2.6,但 &lt; 3.0(正在移植到 3.0) Maven 2+(用于构建序列化对象的测试数据。如果您不打算运行tests.py,可以...

    Java图书管理系统(超级完善、功能非常齐全、代码量十足)

    方法封装和模块化设计:将不同功能的代码块封装成方法,提高了代码的可读性和可维护性。例如menu()方法用于显示主菜单,main()方法是程序的入口,各个case语句对应不同的功能。 数据封装:类中使用私有属性和公共的...

Global site tag (gtag.js) - Google Analytics