Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中快速搜索特定字符_Java_Performance_Search_Character - Fatal编程技术网

在Java中快速搜索特定字符

在Java中快速搜索特定字符,java,performance,search,character,Java,Performance,Search,Character,这似乎是个有点傻的问题。。也许是的。但是我有一个我经常使用的函数,我想知道这是否是完成这项工作的最快方法。该功能被使用了很多次,因此任何速度的提高实际上都是显而易见的。它所做的只是检查一个字符是否是核苷酸(即:如果一个字符是‘a’、‘T’、‘C’或‘G’) private static boolean isValidNucleotide(char nucleotide) { nucleotide = Character.toUpperCase(nucleotide); if(nu

这似乎是个有点傻的问题。。也许是的。但是我有一个我经常使用的函数,我想知道这是否是完成这项工作的最快方法。该功能被使用了很多次,因此任何速度的提高实际上都是显而易见的。它所做的只是检查一个字符是否是核苷酸(即:如果一个字符是‘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中,我真的不是这方面的专家。

您可以尝试一个
开关案例,它通常作为小型开关的表查找来实现:

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

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

去掉
字符。toUpperCase
并检查大写和小写情况,它将显著加快您的功能

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

    return false;
}
我对您的原始函数进行了一个小测试,执行
10000000次
平均需要
80ms
,但当我删除
Character.toUpperCase()
并明确检查这两种情况时,只需要
40ms
,这是显著的改进

编辑:


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

我还没有尝试过,但您可以尝试使用Regex查看性能,最快的(但内存效率最低的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中,字符是2个字节而不是1个字节,但您的字符在这个范围内。只需将
返回映射[nucleotide];
更改为
返回映射[0x00ff&nucleotide];
就可以了


为了安全起见,您还可以将映射的大小更改为
65536
,以避免任何类型的错误。
boolean map=new boolean[65536]

很有趣,是的,我想知道JVM是否会自行进行此类优化。不过这看起来很可靠。我将尝试一个测试,看看它对运行时有何影响。您还可以尝试通过向
开关添加小写字母来替换
toUpperCase
调用。检查后,接受的答案很快这个答案也很好,因为它也很快,目的也更明确,这意味着它可能会从JRE的未来优化中获得更多好处。如果字符超过255会发生什么?Java不是天生的Unicode吗?似乎就是这样。我做了一个类似于iTech的测试。令人印象深刻!你应该这样做顺便说一句,也可以将其改为256,索引为0..255。因此,事实上,如果核苷酸高于255,则会出现异常!或者如果您将其屏蔽,则可能会得到错误的答案…这更糟。@paxdiablo谢谢!是的,这很有意义。请后退一步,重新检查实际问题,而不是您的解决方案。它实际上可能是错误的以完全不同的方式更快地完成这项工作,例如,提前限制用户输入,或提前检查整个核苷酸序列,以便以后不再重复检查。甚至可能有理由这样做(如果你更关心速度而不是有效性)根本不检查。@paxdiablo谢谢你的建议。我确实接受了答案,但这些评论确实值得考虑。我确实需要验证,但可能有一种方法可以限制链中早期的输入。尝试将
开关(核苷酸)
更改为
开关((字节)核苷酸)
我试过了,但没有影响性能,也花了
40 ms
地图解决方案更快,因为它略过了一些范围检查。它只在假设输入字符都小于256时起作用。(我的想法是,也许可以说服JIT编译器使用更大的开关表并避免一些错误。)“不必要的”范围测试。这会使测试速度更快。)