我有一个约5000万字符串的文件,我需要在启动时添加到某种符号表中,然后以合理的速度搜索几次.

我尝试使用DLB trie,因为查找会相对较快,因为所有字符串都是< 10个字符,但在填充DLB时,我会得到超出GC开销限制或outofmemory - 堆空间错误.使用HashMap发现了相同的错误.这是一个由分级器编译和运行的赋值,所以我宁愿不只是分配更多的堆空间.是否有不同的数据结构可以减少内存使用,同时仍然有合理的查找时间?

解决方法:

如果您期望低前缀共享,那么trie可能不是您的最佳选择.

由于您只在启动时加载查找表一次,并且您的目标是内存占用率低且查找速度“合理”,因此最佳选择可能是排序数组和二进制搜索查找.

首先,将数据加载到数组中.由于您可能不知道前面的大小,因此您将加载到ArrayList中.然后从列表中提取最终数组.

假设您加载了5000万个10个字符的字符串,内存将是:

10 character string:

String: 12 byte header + 4 byte 'hash' + 4 byte 'value' ref = 24 bytes (aligned)

char[]: 12 byte header + 4 byte 'length' + 10 * 2 byte 'char' = 40 bytes (aligned)

Total: 24 + 40 = 64 bytes

Array of 50 million 10 character strings:

String[]: 12 byte header + 4 byte 'length' + 50,000,000 * 4 byte 'String' ref = 200,000,016 bytes

Values: 50,000,000 * 64 bytes = 3,200,000,000 bytes

Total: 200,000,016 + 3,200,000,000 = 3,400,000,016 bytes = 3.2 GB

当您转换ArrayList< String>时,您将需要另一个String []副本. to String []. Arrays.sort()操作可能需要50%的数组大小(~100,000,000字节)用于临时存储,但如果在排序之前为GC发布了ArrayList,则可以重用该空间.

因此,总需求约为3.5 GB,仅适用于符号表.

现在,如果空间确实非常珍贵,你可以挤压它.如您所见,String本身在64字节中增加了24字节的开销.您可以使符号表直接使用char [].

此外,如果您的字符串都是US-ASCII或ISO-8859-1,则可以将char []转换为byte [],从而节省一半的字节.

组合在一起,将值大小从64字节减少到32字节,总符号表大小从3.2 GB减少到1.8 GB,或在加载期间大约2 GB.

UPDATE

假设输入的字符串列表已经排序,下面是如何执行此操作的示例.作为MCVE,它只使用一个小的静态数组作为输入,但您可以轻松地从文件中读取它们.

public class Test {

public static void main(String[] args) {

String[] wordsFromFile = { "appear", "attack", "cellar", "copper",

"erratic", "grotesque", "guitar", "guttural",

"kittens", "mean", "suit", "trick" };

List wordList = new ArrayList<>();

for (String word : wordsFromFile) // Simulating read from file

wordList.add(word.getBytes(StandardCharsets.US_ASCII));

byte[][] symbolTable = wordList.toArray(new byte[wordList.size()][]);

test(symbolTable, "abc");

test(symbolTable, "attack");

test(symbolTable, "car");

test(symbolTable, "kittens");

test(symbolTable, "xyz");

}

private static void test(byte[][] symbolTable, String word) {

int idx = Arrays.binarySearch(symbolTable,

word.getBytes(StandardCharsets.US_ASCII),

Test::compare);

if (idx < 0)

System.out.println("Not found: " + word);

else

System.out.println("Found : " + word);

}

private static int compare(byte[] w1, byte[] w2) {

for (int i = 0, cmp; i < w1.length && i < w2.length; i++)

if ((cmp = Byte.compare(w1[i], w2[i])) != 0)

return cmp;

return Integer.compare(w1.length, w2.length);

}

}

产量

Not found: abc

Found : attack

Not found: car

Found : kittens

Not found: xyz

标签:java,memory

来源: https://codeday.me/bug/20190608/1199027.html

java字符串表表容量_java – 我可以使用什么符号表来存储~50 mil的字符串,快速查找而不会耗尽堆空间?...相关推荐

  1. java arraylist指定容量_Java中的ArrayList的容量

    List接口的大小可变数组的实现.实现了全部可选列表操做,并容许包括 null 在内的全部元素. ArrayList继承于List接口,除继承过来的方法外,还提供一些方法来操做内部用来存储列表的数组的 ...

  2. java 正则切分句子_Java开发笔记(三十七)利用正则串分割字符串

    前面介绍了处理字符串的常用方法,还有一种分割字符串的场景也很常见,也就是按照某个规则将字符串切割为若干子串.分割规则通常是指定某个分隔符,根据字符串内部的分隔符将字符串进行分割,例如逗号.空格等等都可 ...

  3. java list初始容量_java中快速创建带初始值的List和Map实例

    java中快速创建带初始值的List和Map实例 初始化一个List和Map对象并为期加入值的写法如下: List sList = new ArrayList(); sList.add("s ...

  4. java怎么设置序号_Java 添加Word项目符号、编号列表

    import com.spire.doc.*; import com.spire.doc.documents.ListPatternType; import com.spire.doc.documen ...

  5. java 二维矩阵_Java如何输入二维矩阵并存储到二维数组中

    展开全部 最不严谨的写法(但是可62616964757a686964616fe59b9ee7ad9431333335326163用)下列方法可以不需知道二维数组的宽度和长度,但是不能直接保存,而是输入 ...

  6. 基础-符号表(一)-数据结构和算法(Java)

    文章目录 1 概述 2 API 2.1 泛型 2.2 重复的键 2.3 空(null)键 2.4 空(null)值 2.5 删除操作 2.6 便捷方法 2.7 迭代 2.8 键的等价性 3 有序符号表 ...

  7. plsql 无法解析指定的连接标识符_Java方法加载、解析、存储、调用

    方法调用在项目中是数不胜数,除了一些常量类其他的类都会定义方法并调用,那你有想过他是怎么从一个java语言写的方法到计算机执行的吗,下面我们就来学习Class字节码文件中保存java中的方法.方法加载 ...

  8. java字符串拼接例子_Java详解【String】+【StringBuilder vs StringBuffer】+【字符串拼接】...

    String详解 注意区分对象和对象的引用 首先来看一下我在jdk中找到的String源代码,这里只截取开头的小小一部分 public final class String implements ja ...

  9. java 字符串 面试题_Java常用类String的面试题汇总(java面试题)

    1.比较两个字符串时使用"=="还是equals()方法? 当然是equals方法."=="测试的是两个对象的引用是否相同,而equals()比较的是两个字符串 ...

最新文章

  1. 如何定时备份数据库并上传七牛云
  2. 推荐几款vs2005的插件
  3. TRIZ系列-创新原理-23-反馈原理
  4. 还不起9亿?有人建议为范冰冰发行一款私募ABS产品融资!
  5. python 3.8.2_python-3.8.2-docs-html
  6. 新零售时代,美妆行业如何打造新主场?
  7. 许晴×××汤的营养价值
  8. C++函数模板(模板函数)详解
  9. 使用数位板或数位屏的压感笔时常见的问题及解决方法
  10. 软件测试---组织架构图和范围测试列表
  11. 163免费企业邮箱服务地址
  12. ProxySQL+MGR实现读写分离和主节点故障无感知切换 - 完整操作记录
  13. ThinkPHP实现定时执行任务的两种方法
  14. 【翻译论文】Understanding Reuse, Performance, and Hardware Cost of DNN......
  15. POS机刷卡跨行交易的清算方式
  16. iOS企业版app部署到自己的服务器
  17. JavaScript中的设计模式
  18. NAT与NAT穿透(一)
  19. 默认网络设备流量控制
  20. 四、V4L2 control结构框架图

热门文章

  1. Technical attribute VS Read only attribute
  2. SAP ABAP实用技巧介绍系列之 ABAP XSLT select keyword
  3. why my pricing procedure is not determined in QHD 504
  4. Java源码研究之object to json string debug
  5. add to -append Backend implementation
  6. 使用Cordova将您的前端JavaScript应用打包成手机原生应用
  7. One Order行项目里Item Category是怎么计算出来的
  8. ionic2 html 转义,ionic2 基于ngx-translate实现多语言切换,翻译
  9. high severity error mysql_pg将运行日志导入表中的方法及时区问题解决
  10. java 委托_面试官:java双亲委派机制及作用