Java:查找字符串之间的匹配

时间:2009-10-16 06:01:53

标签: java string

给定2个字符串,我想找到至少四个字符的第一个匹配。

这是我目前要做的代码。它工作正常,但我认为可能有更好的方法来做到这一点。在我正在做的事情中,是否有任何尖叫的低效率或不良做法?有没有公​​共图书馆,比如Apache Commons,我应该利用它,但我不是吗?

不要担心Gene类 - 它只包含有问题的字符串。另外 - GeneMatch()表示不存在匹配,而带参数的GeneMatch构造函数表示已找到匹配。

Constants.MIN_MATCH == 4,在这种情况下。

public static GeneMatch findMatch(Gene g0, Gene g1) {

    String g0DNA = g0.getDNA();
    String g1DNA = g1.getDNA();

    if (g0DNA.equals("") || g1DNA.equals("")) { //there won't be a match if one is empty
        return new GeneMatch();
    }

    int g0Left = -1;
    int g0Right = -1;
    int g1Left = -1;
    int g1Right = -1;

    String window;

    for (int inx = 0; inx <= g0DNA.length() - Constants.MIN_MATCH; inx++) {
        window = g0DNA.substring(inx, inx + Constants.MIN_MATCH);

        if (g1DNA.indexOf(window) != -1) {

            g0Left = inx;
            g0Right = inx + Constants.MIN_MATCH;

            g1Left = g1DNA.indexOf(window);
            g1Right = g1Left + Constants.MIN_MATCH;

            /* grow the match to the right
             * while the two right indices are less than the lengths of their respective strings, and the 
             * characters at the indices match, increment each index
             */
            while (g0Right < g0DNA.length() && g1Right < g1DNA.length() && g0DNA.charAt(g0Right) == g1DNA.charAt(g1Right)) {
                g0Right++;
                g1Right++;
            }
            break; //we've already found a match, no need to continue sliding the window
        }
    }

    //now that the indices are found, convert to Genes
    if (g0Left == -1 || g0Right == -1 || g1Left == -1 || g1Right == -1) { //no match found
        return new GeneMatch();
    }

    Gene gL0 = new Gene(g0DNA.substring(0, g0Left));
    Gene gL1 = new Gene(g1DNA.substring(0, g1Left));

    Gene g0match = new Gene(g0DNA.substring(g0Left, g0Right));
    Gene g1match = new Gene(g1DNA.substring(g1Left, g1Right));

    Gene gR0 = new Gene(g0DNA.substring(g0Right));
    Gene gR1 = new Gene(g1DNA.substring(g1Right));

    //sanity check
    assert g0DNA.equals(gL0.getDNA() + g0match.getDNA() + gR0.getDNA()) : "g0 didn't add up";
    assert g1DNA.equals(gL1.getDNA() + g1match.getDNA() + gR1.getDNA()) : "g1 didn't add up";

    return new GeneMatch(gL0, gR0, g0match, g1match, gL1, gR1);

}

3 个答案:

答案 0 :(得分:2)

当前方法

  1. g1DNA.indexOf(窗口)调用 - 第一个调用结果可以存储并稍后重用;
  2. 不必要的字符串对象 window =期间的构造 g0DNA.substring(inx,inx + Constants.MIN_MATCH);
  3. 不必要的gL0,gL1,gR0,gR1 如果断言是建设 关;
  4. if(g0DNA.equals(“”)|| g1DNA.equals(“”))检查可以 改进,以检查 字符串至少有四个符号 每个;
  5. 最好调用 equals() 常数,即使用 “”。等于(ARG)。如果 arg null ,它允许避免可能的NPE。它 这里没什么影响,只是 适用的良好编码政策;
  6. String.isEmpty()方法 可以用来代替 “” 等于(ARG);
  7. 没有执行空检查 DNA字符串;
  8. <强>改进

    1. 最好循环最短的时间 字符串,即你应该检查dna1 和dna2长度并执行外部 循环对着较短的那个 长度。这允许最小化 迭代次数;
    2. 您可以避免创建新的字符串对象 并按字符操作。 而且,你可以修改 算法以便与任何人一起工作 java.lang.CharSequence 实现;
    3. 你记得无与伦比 序列,即保持一组char 被检查的序列和 事实证明是无与伦比的 最小化外循环的时间 迭代。例如,你迭代 在包含许多的字符串上 'b'字符。您检查第二个字符串是否包含该字符串 在第一次'b'处理期间使用char。 你可以记住并停止 后续'b'处理 热切;
    4. 使用 String.indexOf()时 从一开始就进行搜索 字符串。如果这可能是问题 相当于要搜索的字符串 长。创建一个可能是值得的 它的字符索引。即之前 找到你可以迭代的匹配 所有目标字符串字符和 构建像'character' - &gt;这样的映射 '它们发生的索引集 在字符串'中。这允许 执行循环体检查很多 在长字符串的情况下更快;
    5. 一般考虑 没有'最佳算法',因为“最佳”选择取决于输入数据配置文件和算法使用策略。即如果算法很少执行并且其性能影响微不足道,那么花费大量时间进行优化并没有必要编写一个易于维护的简单代码。如果输入字符串相当短,那么构建字符索引就没有意义。一般情况下,只要尽可能避免初步优化,并在选择结果算法时仔细考虑所有输入数据,如果你确实存在瓶颈。

答案 1 :(得分:1)

对我来说很好看。只是两件小事:

  1. 重复使用g1DNA.indexOf(window)的结果,而不是两次调用(g1Left = g1DNA.indexOf(window);

  2. 你不必检查所有4个变量是否为== -1,因为你们都要立即设置它们。

答案 2 :(得分:0)

对我来说很好看。有人可能会在分配方面进行微优化,但这是JIT编译器的工作。如果您觉得算法太慢,请尝试对其进行分析。