java - 数据结构中数据的有效表示

标签 java optimization data-structures

我有以下格式:

SOLEXA3_1:3:5:1473:616/1    gi|7367913151|ref|NC_007367.1|  100.00  23  0   0   27  49  3404561 3404539 1e-5    46.1
SOLEXA3_1:3:5:1473:616/1    gi|73921565|ref|NC_007367.1|    100.00  23  0   0   27  49  3404561 3404539 1e-5    46.1
SOLEXA3_1:3:5:1474:616/1    gi|32140171|ref|NC_007367.1|    100.00  23  0   0   27  49  3404561 3404539 1e-2    46.1
SOLEXA3_1:3:5:1474:616/1    gi|7354921565|ref|NC_007367.1|  100.00  23  0   0   27  49  3404561 3404539 1e-5    46.1
SOLEXA3_1:3:5:1475:616/1    gi|73921565|ref|NC_007367.1|    100.00  23  0   0   27  49  3404561 3404539 1e-5    46.1
SOLEXA3_1:3:5:1475:616/1    gi|73921565|ref|NC_007367.1|    100.00  23  0   0   27  49  3404561 3404539 1e-5    46.1

基本上,它是一个制表符分隔的文件,我将多次点击输入(第一个字段:SOLEXA3_1:3:5:1474:616/1 作为示例)并多次点击特定输入: 321401717354921565 用于上述示例输入)。我想要做的是为特定读取的所有命中以及与每个命中相关的质量构建某种内存中表示 - 这是倒数第二个字段 - 1e-51e-2 对于上述 2 个命中。所以我所做的如下:

我有一个 Map<String, ArrayList<TObjectDoubleMap<String>>> 。其中每个字符串基本上都是输入 ID,ArrayList 由 Trove 库中的一个映射组成,该映射包含一对字符串, double 字符串 - 字符串是命中的 ID 和分数。我的输入文件大约有 1800 万行,并且有一堆 -Xmx12g 我的内存不足。有什么想法可以优化内存使用吗?请记住,实际分数可能会有所不同,因此我认为分享它们是不可行的。

最佳答案

我会使用:

Map<String, ByteArrayOutputStream> map = new HashMap<String, ByteArrayOutputStream>();

其中 Key 只是 2 个字段的串联,您将质量和分数写入 ByteArrayOutputStream。

生成的数据结构将类似于:

Key:    "SOLEXA3_1:3:5:1474:616/1_32140171"
Value:  |5|46.1|2|46.1|  //where this is actually just a byte[]

然后,在读取质量和分数时,您只需使用 readByte() 和 readDouble() 直到到达流的末尾。

当然,这样做会使查询内容变得有点棘手,但你会节省大量的内存分配。

例如:

for ( String[] fields : rows ) {
    Map<String, ByteArrayOutputStream> map = new HashMap<String, ByteArrayOutputStream>();
    String key = fields[0] + "_" + fields[1];
    byte quality = Byte.parseByte(fields[10].substring(3));
    double score = Double.parseDouble(fields[11]);

    if ( !map.containsKey(key) ) {
        map.put(key, new ByteArrayOutputStream());
    }
    DataOutputStream dos = new DataOutputStream(map.get(key));
    dos.writeByte(quality);
    dos.writeDouble(score);
}


//reading
for ( String key : map.keySet() ) {
    ByteArrayOutputStream baos = map.get(key);
    int numHits = baos.size()/9; //1 byte for quality, 8 for score
    DataInputStream din = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()));
    System.out.print( key + " - " + numHits);
    while ( din.available() > 0 ) {
        byte quality = din.readByte();
        double score = din.readDouble();
        System.out.print(" (" + quality + ", " + score + ")");
    }
    System.out.print("\n");
}

使用这种方法,我可以在 <1GB 内存中读取和存储约 2000 万条记录。 (在 MacBook Pro 上大约需要 10 秒)。

关于java - 数据结构中数据的有效表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9002255/

相关文章:

C# 字节数组到结构

java - setSupportProgressBarInminatedVisibility 抛出 NPE(支持 V7 修订版 21.0.1)

java - 将 Postgresql 查询转换为 Hibernate

javascript - 找出一个数的最大因数(除了它本身)

c# - 优化.NET中大系列数据的存储和处理

c - 是否有检测硬件位宽的标准方法?

algorithm - 惰性传播线段树实现难点

java - 在 LibGDX 游戏中重用 Box2D 对象(池化)

java - 如何将未转义的 XML 写入 XMLStreamWriter?

arrays - Haskell 中惰性数组的适当表示