2015-09-26 3 views
9

Я пишу метод, который вернет true, если какая-либо из строк появится в самом конце другой строки, а строки - разные. Мы не можем использовать EndsWith()Сравнение подстрок в Java

Например:

  • если = "все" и б = "мяч", метод будет возвращать верно.

  • если a = "yes" и b = "yes", метод вернет false.

Вот что я до сих пор, но он продолжает говорить, что индекс строки из диапазона = -1

public static boolean startOther(String a, String b){ 
    if(a.equals(b)) 
     return false; 
    int pos=a.indexOf(b); 
    int pos1=b.indexOf(a); 
    int len=a.length(); 
    int len1=b.length(); 
    if(pos>-1 && a.substring(len-pos).equals(b)|| pos1>-1 && b.substring(len1-pos1).equals(a)) 
     return true; 
    return false; 
} 
+3

Подсказка: http://docs.oracle.com/javase/7/docs/api/java/lang/String. html # endsWith% 28java.lang.String% 29 –

+1

Что касается ошибки: если a не содержит b, pos равно -1, и тогда вы делаете a.substring (len + 1), который, таким образом, запрашивает индекс из границ строки. Отладчик немедленно показал бы это. Вы должны научиться его использовать. –

ответ

2

Это немного «семь раз отмерь», но то, что вы хотите сделать, это:

  • Проверить индекс местоположения каждой строки в другую.
  • Если (и только если) существует указатель, проверьте, соответствует ли подстрока от этого индексного пятна до конца.
  • В противном случае верните значение false.

Если вы делаете какие-либо вычитания, вы не получите правильный размер подстроки; то есть, если вы вычтите длину строки, которую вы проверяете, вы получите только один символ.

public static boolean startOther(String left, String right) { 
    if (left == null || right == null || left.equals(right)) { 
     return false; 
    } 
    int rightSubstringInLeft = left.indexOf(right); 
    int leftSubstringInRight = right.indexOf(left); 

    if(rightSubstringInLeft != -1) { 
     return left.substring(rightSubstringInLeft).equals(right); 
    } else if(leftSubstringInRight != -1) { 
     return right.substring(leftSubstringInRight).equals(left); 
    } else { 
     return false; 
    } 
} 

Вот более оптимизированная форма того же кода, что указана в комментариях. По сути, это одно и то же, но вам не нужно выполнять другую проверку равенства подстроки, так как lastIndexOf только когда-либо даст вам последний индекс всей подстроки.

public static boolean startOther(String left, String right) { 
    if (left == null || right == null || left.equals(right)) { 
     return false; 
    } 
    int rightSubstringInLeft = left.lastIndexOf(right); 
    int leftSubstringInRight = right.lastIndexOf(left); 

    if(rightSubstringInLeft != -1) { 
     return rightSubstringInLeft == left.length() - right.length(); 
    } else if(leftSubstringInRight != -1) { 
     return leftSubstringInRight == right.length() - left.length(); 
    } else { 
     return false; 
    } 
} 
+0

Это довольно неэффективно. Почему бы не использовать a.lastIndexOf (b) и проверить, что возвращаемый индекс равен a.length() - b.length()? Или используя a.lastIndexOf (b, a.length() - b.length()) и проверьте, что возвращаемое значение равно 0? Проверка равенства подстроки является избыточной, поскольку lastIndexOf() уже делает это. –

+0

[String # lastIndexOf] (http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#lastIndexOf (int)) не делает то, что, по вашему мнению, должно делать в этом сценарий. Ожидается, что вы перейдете в точку Unicode к этому методу, а не к целому числу. – Makoto

+0

Существует несколько методов lastIndexOf(): http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#lastIndexOf%28java.lang.String%29 и http: // docs .oracle.com/javase/7/docs/api/java/lang/String.html # lastIndexOf% 28java.lang.String,% 20int% 29 - это те, что я говорю о –

1

Поскольку вы не можете использовать endsWith, первый тест для null. Затем получим длины. Проверьте, что они не совпадают. Проверьте, что значение indexOf + равно для true. Что-то вроде

public static boolean startOther(String a, String b) { 
    if (a == null || b == null) return false; 
    int aLen = a.length(); 
    int bLen = b.length(); 
    if (aLen != bLen) { 
     if (aLen < bLen) { 
      int p = b.indexOf(a); 
      return p != -1 && p + aLen == bLen; 
     } else { 
      int p = a.indexOf(b); 
      return p != -1 && p + bLen == aLen; 
     } 
    } 
    return false; 
} 

, которые я испытал, как

public static void main(String[] args) { 
    System.out.println(startOther("all", "ball")); 
    System.out.println(startOther("yes", "yes")); 
} 

и получил (требуемый) выходной сигнал

true 
false 
+1

Или просто: 'return (a.length()! = B.length()) && (a.endsWith (b) || b.endsWith (a))', который должен быть быстрее, поскольку он не должен проверьте равенство. –

1
indexOf(String s) 

Возвращает: индекс первого вхождения указанная подстрока, или -1, если такого вхождения нет.

Если indexOf() возвращено -1, и вы вызываете a.substring(len-pos), параметр будет len - (-1) = len + 1. Это причина out of range.

Этот случай происходит всегда в вашем коде, из-за двух зеркальных линий:

int pos=a.indexOf(b); 
int pos1=b.indexOf(a); 

Если вы проверили равны перед вызовом метода, один из pos всегда становится -1. Очевидно: если одна строка содержит другую, и они не равны, то вторая строка не содержит первых.

1

Сочетание length() и regionMatches(int toffset, String other, int ooffset, int len) должны быть весьма эффективным:

public static boolean startOther(final String a, final String b) { 
    final int aLength = a.length(); 
    final int bLength = b.length(); 
    return aLength != bLength && (aLength > bLength ? a.regionMatches(aLength - bLength, b, 0, bLength) 
                : b.regionMatches(bLength - aLength, a, 0, aLength)); 
} 
Смежные вопросы