3

这可能看起来有点像一个愚蠢的问题。也许它是。但是我有一个我经常使用的功能,想知道这是否是完成这项工作的最快方法。该功能被使用了很多次,以至于任何速度的增加实际上都是显而易见的。它所做的只是检查一个字符是否是一个核苷酸(即:如果一个字符是“A”、“T”、“C”或“G”。

private static boolean isValidNucleotide(char nucleotide) {
    nucleotide = Character.toUpperCase(nucleotide);
    if(nucleotide == 'A') return true; 
    if(nucleotide == 'T') return true;
    if(nucleotide == 'C') return true;
    if(nucleotide == 'G') return true;
    return false;
}

这是完成工作的最快方法吗?还是您认为值得实现某种索引/映射/其他东西(可能在函数之外执行比较,然后将此文本复制到代码中的几个位置)?我真的不是Java中这种事情的专家。

4

4 回答 4

5

最快的(但内存效率最低的仍然是 255 字节还不错!)将是这样的:

/* this is static member of class */
static boolean map[] = new boolean[256];
static {
    for(int j = 0; j < map.length; j++)
        map[j] = false;
    /* map your required values true here */ 
    map['A'] = true;
    map['T'] = true;
    map['C'] = true;
    map['G'] = true;
    /* make small letter here too */
    map['a'] = true;
    map['t'] = true;
    map['c'] = true;
    map['g'] = true;
}

然后做一个这样的函数:

private static boolean isValidNucleotide(char nucleotide) {
    /* complexity is just one access to array */
    return map[nucleotide];
}

正如@paxdiablo 所说,java char 是 2 个字节而不是 1 个字节,但你的字符在这个范围内。通过简单地更改return map[nucleotide];return map[0x00ff & nucleotide];应该工作。

您还可以更改地图的大小以65536确保安全并避免任何类型的错误。boolean map = new boolean[65536]

于 2013-02-20T02:42:03.630 回答
3

您可以尝试 a switch-case,它通常实现为小型开关的表查找:

switch(nucleotide) {
case 'A':
case 'T':
case 'C':
case 'G':
    return true;
}
return false;

if请注意,如果调用足够频繁,JVM 的 JIT 可能会使基于 - 的代码非常快。

于 2013-02-20T02:30:04.380 回答
1

摆脱Character.toUpperCase并检查大写和小写的情况,它将显着加快您的功能。

private static boolean isValidNucleotide(char nucleotide) {       
    if(nucleotide == 'A' || nucleotide == 'a') return true; 
    // Rest of your conditions

    return false;
}

我用你的原始函数做了一个小测试,它平均80 ms需要执行10000000 times,但是当我删除Character.toUpperCase()并明确检查这两种情况时,它只需要40 ms,这是显着的改进。

编辑:

使用Map@Shivam Kalra 建议的解决方案只需要11 ms平均!

于 2013-02-20T02:37:32.757 回答
-1

我没试过,但你可以试试用正则表达式看看性能

于 2013-02-20T02:37:51.987 回答