平安夜快乐。。。今天在写词分析的器的时候,发现了一个问题。由于要计算两个词之间的cos距离,需要保存向量,于是将数据结构设计成Map<Stirng, Set<Integer>>
。数据结构问题解决了,但是数据文本有2G多,程序加载数据到一半就GC了。
刚开始还以为是数据太大的原因,之后去StackOverflow上稍微搜索了一下,有人提到了一种答案,感觉比较靠谱,尝试了一下果然可以。
根据上面回答中提到的内容,按图索骥找到了这个库。trove4j支持原生类型,这与Java的Collections只能使用包装类型不同。原生类型比包装类型更节省空间。这在大数据环境下是很必要的。
例如,上面的Map<Stirng, Set<Integer>>
就可以写成
基本的操作方法与Java原生Collections中的方法大体相同。 在使用中发现的一点不同就是迭代器的不同,trove4j为每种类型单独定义了迭代器。
这样可以让迭代器更好的返回原生类型。
Java默认的Collections为什么消耗内存,这就需要从Java的Class结构开始说起。 这里简单说一下Class各部分的内存占用大小(以32位为例):
Object Header 普通的类需要8个字节,数组需要12个字节(8个字节的类+4个字节的数组长度)。 Primitive Fields 的占用如下表
Java type | Bytes required |
---|---|
boolean | 1 |
byte | 1 |
char | 2 |
short | 2 |
int | 4 |
float | 4 |
long | 8 |
double | 8 |
那么一个普通的Double类在32位上占用的空间为:
8字节头部 8字节double 0字节对齐 总共占用16字节的长度。
这里只是大体看了一下,具体计算方法还要继续研究。
在文章中还提到了一个叫Fastutil的库,似乎比trove4j更好,但是trove4j更轻量级,有空再看看。