1

I am trying to implement String.endsWith() method without the use of the built-in method String.endsWith().

Here is my code:

public static boolean endsWithSuffix(String str, String suffix) {
    char[] chStr = str.toCharArray();
    char[] chSuf = suffix.toCharArray();

    if(!str.contains(suffix) {
        return false;
    }
    return true;
}

What is the best way to implement the endsWith() method without using the built-in method?

I've been trying with character arrays but no luck yet. Would strings be easier?

danksim
  • 617
  • 3
  • 9
  • 27

8 Answers8

2

One way would be like this:

  • Check if suffix <= str.
  • Get the last n characters of str where n = suffix.length(), using substring().
  • Compare that portion of string with suffix with equals() or equalsIgnoreCase().
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
  • Thanks Eng.Fouad! You solved it for me! Here is how I did it following your advice: `public static boolean endsWithSuffix(String str, String suffix) { int n = suffix.length(); int nn = str.length()-n; if(suffix.length()<=str.length() && str.substring(nn, str.length()).equals(suffix)) { return true; } else { return false; } }` – danksim Apr 16 '13 at 01:00
  • @Vitaly Well, I need a substring of str in order to check if it matches with the suffix, don't I? – danksim Apr 16 '13 at 01:11
  • @Vitaly The problem with string allocation in something like a `while(foo) s += "bar";` loop is that it's O(N^2) because each iteration has to copy all of the previous chars (which is O(N)) before appending the new ones. But creating a new substring is O(1), because the new String will use the same underlying `char[]` as the full string, just with a different offset/length. So it's not bad. – yshavit Apr 16 '13 at 01:11
  • @Dinky You don't have to create a substring, you can also just loop through each `char` using `String.charAt`. – yshavit Apr 16 '13 at 01:11
  • @yshavit Then why I do not see any new String() in any search methods of String class? – Vitaly Apr 16 '13 at 01:29
  • @Dinky In this implementation - yes. I asked about whether it is good or not. – Vitaly Apr 16 '13 at 01:30
  • @yshavit So wouldn't creating a substring be faster than using a `char[]`? – danksim Apr 16 '13 at 01:33
  • @Vitaly I see. I think creating that substring is the most efficient way that I can think of. Unless just doing a plain `return (str.lastIndexOf(suffix) == str.length() - suffix.length());`. Maybe this last return statement is the "most efficient" way. Is it? – danksim Apr 16 '13 at 01:40
  • 1
    @Dinky Creating a substring is more efficient than getting the `char[]` from the String, yes -- because `String.toCharArray` copies the `char[]`. But if you use `String.charAt(int)`, there's no copying at all. – yshavit Apr 16 '13 at 01:42
  • 1
    @yshavit Oh, I see. Thanks for clearing that up. So using `String.charAt()` would be more efficient, right? – danksim Apr 16 '13 at 01:46
  • 1
    @Dinky Comparing two int's and using built-in search method lastIndexOf() is the most efficient way. – Vitaly Apr 16 '13 at 01:48
2
    return str.length() >= suffix.length() && str.substring(str.length() - suffix.length()) == suffix;

you may use .equals but you have to add nullity check then

abumusamq
  • 780
  • 1
  • 10
  • 29
  • I did not know I could just return it like this. Thank you for the tip! – danksim Apr 16 '13 at 01:13
  • 1
    not a problem. Yes it will first check length and because of and operator it will not continue if first condition is not satisfied – abumusamq Apr 16 '13 at 02:12
2
public static boolean endsWith(String test, String suffix) {

    int start = test.length() - suffix.length();
    if (start >= 0) {
        return test.indexOf(suffix, start) >= 0;
    }
    return false;
}

public static void main(String... args) {

    System.out.println(endsWith("aaabbbccc", "aaa"));
    System.out.println(endsWith("aaabbbccc", "bbb"));
    System.out.println(endsWith("aaabbbccc", "ccc"));
    System.out.println(endsWith("Hello Java", "Java"));
}

Output

false
false
true
true
Vitaly
  • 2,760
  • 2
  • 19
  • 26
  • Thanks for your input, Vitaly. How does this check if a string ends with a certain suffix? Doesn't this only check if the last index is greater than or equal to 0? – danksim Apr 16 '13 at 01:48
  • @Dinky No, I just forgot to add the suffix parameter, fixed. – Vitaly Apr 16 '13 at 01:56
  • Perhaps, " - 1" is not needed there. This answer is just an idea, working idea, however. – Vitaly Apr 16 '13 at 02:19
  • Let's say `String str = "Hello Java";` and `String suffix = "Java";`. `return str.lastIndexOf(suffix, str.length()-suffix.length()) >= 0` should return true and does return true. Could you enlighten me on how this works? I know that `str.length()-suffix.length() = 6`. So it's basically `str.lastIndexOf("Java", 6) >= 0`. How does this mechanism prove that `"Hello Java"` ends with `"Java"`? – danksim Apr 16 '13 at 02:30
  • 1
    You are right, it was wrong.. lastIndexOf should be indexOf. Answer updated with working and tested code. – Vitaly Apr 16 '13 at 02:45
2
    public static boolean endsWith(String str, String suffix){  
        return (str.lastIndexOf(suffix) == str.length() - suffix.length()); 
    }  

    public static void main(String[] args) {
        System.out.println(endsWith("this is a test", "test")); //True
        System.out.println(endsWith("This is another test", "test2"));  //False
    }
Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
2

Since you're trying to re-invent the wheel for the sake of figuring out how a wheel works (which isn't a bad thing!), it seems like a bit of a cheat to use substring + equals, doesn't it? Why not just implement the check directly, rather than passing it off to equals?

The basic idea is to compare the last character of each string, then the second to last, then the third to last, etc. If you ever get an unequal comparison, you can return false. Otherwise, you can return true. In other words, you pair off the two strings, character-by-character; and rather than asking if those pairs are all equal, you ask whether any of them are un-equal.


Given an int i, you can get the "i-ith index from the right" via stringLength - 1 - i. For instance, the last digit is stringLength - 1, the second to last is stringLength - 2, etc. So:

  1. check whether the suffix is longer than str. If it is, you can return false
  2. let i represent how many chars from the right we want to look at
  3. Create a loop that will look at all the i-ith chars from the right within the suffix: for(int i = 0; i < suffix.length(); ++i)
  4. within each iteration, get the i-ith char from the right for both strings, as described above
  5. if they're unequal, return false. If they're equal, go on to the next iteration
  6. If you've exhausted all of the chars in suffix (ie, if the loop is finished), then return true.

Putting it all together:

public static boolean endsWithSuffix(String str, String suffix) {
    int strLen = str.length();
    int suffixLen = suffix.length();

    if (suffixLen > strLen)
        return false;
    for (int i = 0; i < suffixLen; ++i) {
        char strChar = str.charAt(strLen - 1 - i);
        char suffixChar = suffix.charAt(suffixLen - 1 - i);
        if (strChar != suffixChar)
            return false
    }
    return true
}

The initial check of suffixLen > strLen isn't just an optimization -- it's required for correctness. Otherwise, if the suffix is longer than the str, then the loop will go far enough that you'll be asking for str.charAt(-1) or even lower, which will raise an exception! There are other ways around solving this problem, but I'll leave it to you to find them. :)

yshavit
  • 42,327
  • 7
  • 87
  • 124
1

Here's what I'd do:

  1. reverse the input String
  2. reverse the suffix String
  3. Check if the output of 1. String.startsWith the output of 2.
Daniel Kaplan
  • 62,768
  • 50
  • 234
  • 356
  • Thanks, tieTYT! Great answer but I wanted to stay away from startsWith() as well. – danksim Apr 16 '13 at 00:53
  • I figured you'd say that, but `startsWith` is straight forward to write on your own. Simply compare the output of 1. and 2. character by character. – Daniel Kaplan Apr 16 '13 at 01:05
  • 1
    @tieTYT Once you've got that insight, why not just do the same thing to write an `endsWith`? It's the same idea, just that instead of starting at 0 and incrementing, you start at `s.length() - 1` and decrement. – yshavit Apr 16 '13 at 01:15
1

you can try the Substring method for string

public static boolean endsWithSuffix(String str, String suffix) 
{
int a,b;
a=str.length();
b=suffix.length();
if (str.subString(b-a,a).equals(suffix))
   return true;
else 
   return false;

}

Mfali11
  • 353
  • 2
  • 3
  • 8
1

Try the following.

public static boolean endsWithSuffix(String str, String suffix)     
    int offset = str.length - suffix.length();
    if (offset >= 0) {
        String temp = str.substring(offset, str.length() - 1);
        if (suffix.equals(temp)) {
            return true;
        }
    }
    return false;
}
Stephen Donecker
  • 2,361
  • 18
  • 8