0

I was wondering why Java and other programming languages implement (seemingly) redundant functions such as:

"foobar".startsWith("bar", 3);
// same as
"foobar".substring(3).startsWith("bar");

// or even indexOf(str, offset), regionMatches(...)

Is there a reason behind this?

4
  • 4
    Your "same as" isn't correct, the two expressions don't have the same contract. Generally: convenience.
    – Mat
    Commented Apr 11, 2015 at 7:38
  • 1
    @Mat Could you explain what some of those little differences in contract are?
    – Ixrec
    Commented Apr 11, 2015 at 15:13
  • 1
    @lxrec: substring throws if the index is out of range. startsWith just returns false.
    – Mat
    Commented Apr 11, 2015 at 15:15
  • As a related point; 99% of methods are redundant and could each be replaced by several other methods Commented Apr 11, 2015 at 15:32

2 Answers 2

6

There are few possible reasons for this sort of thing:

  1. As in JacquesB's answer it may simply be convenience for the library user to call a single method rather than two methods and keep their code more succinct.

  2. Performance may be a consideration. Calling .substring(3) will result in a new string being created, and therefore you are looping over the string twice, it is possible 1 for .startsWith("bar", 3) to be implemented without creating a temporary substring and to just loop through the string once. .startsWith has another tiny optimization point: it can bail out early if the first character does not match, .indexOf will need to keep checking the rest of the string.

  3. Expressing intent: while its fairly obvious what you are doing with either of your two variants it does take the reader a little while to consider the purpose compared to a single method call that will tell you exactly what you are doing.

  4. As Phillipp points out, history can be a factor, adding new methods to an API is fairly easy, changing or removing existing methods is much harder as it will break existing code, so sometimes you may just be seing an artefact of the history of the development of the API 2.

1 I have no idea if this is actually the case here but I'd be surprised if it does.
2 Probably not in this case though.

7
  • A 4th reason might be historical. They added startsWith first, realized that it doesn't cover all use-cases, and then added substring in a later version which can do the same and more, but they couldn't remove startsWith because it would break backward compatibility.
    – Philipp
    Commented Apr 11, 2015 at 9:26
  • @Philipp good call, added to answer
    – jk.
    Commented Apr 11, 2015 at 9:29
  • 3
    an example for a class in the Java standard library which was made redundant by a later addition is Hashtable vs. Collections.synchronizedMap.
    – Philipp
    Commented Apr 11, 2015 at 9:37
  • @Philipp: Hashtable is still routinely used when thread safety is not required. Commented Apr 11, 2015 at 15:28
  • @RobertHarvey No, Hashtable is used when thread safety is required. When you don't need thread safety, you use a HashMap.
    – Philipp
    Commented Apr 11, 2015 at 21:19
5

These are called convenience functions. They are included so users can write shorter and simpler code.

Note that almost every library is "redundant" in the sense that users could write the same code themselves outside of the library. However the point of using libraries is that you save time and code, and you can reuses the knowledge of the library in different projects.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.