开发者

why from index is inclusive but end index is exclusive?

开发者 https://www.devze.com 2023-03-12 12:21 出处:网络
In Java API methods like: String.substring(int be开发者_开发百科ginIndex, int endIndex) String.subSequence(int beginIndex, int endIndex)

In Java API methods like:

  • String.substring(int be开发者_开发百科ginIndex, int endIndex)
  • String.subSequence(int beginIndex, int endIndex)
  • List.subList(int fromIndex, int toIndex)

Why is the beginning index inclusive but the end index exclusive? Why shouldn't they have been designed both inclusive?


Because:

  • Java is based on C, and C does it this way
  • It makes the code cleaner: If you want to capture to end of object, pass object.length (however the object implements this, eg size() etc) into the toIndex parameter - no need to add/subtract 1

For example:

String lastThree = str.substring(str.length() - 3, str.length());

This way, it is very obvious what is happening in the code (a good thing).

EDIT An example of a C function that behaves like this is strncat from string.h:

char *strncat(char *dest, const char *src, size_t n);

The size_t parameter's value corresponds to the java endPosition parameter in that they are both the length of the object, but counting from 0 if they are the index, it would be one byte beyond the end of the object.


It is called the Dijkstra convention of ranges [i, j> (or in other math notation [i, j). In this way you can deal with ranges [a, b>, [b, c>, [c, d].

It was argued that it is somewhat more efficient, and in fact we programmers use it in:

for (int i = 0; i < n; ++i) { ... }

In such ranges the number of elements is j - i, so yes a -1/+1 is saved.

It also is used in BitSet.set(from, to)


Th problem is that they didn't use the C/C++ syntax. I think the C syntax is more readable. Example if you want to take a substring with lenght 2 starting from the 3rd element of a List X, you write

X.subList(2,3).

In Java, if you want to take a sublist with ONLY the 3rd element of a List X, you need to write X.subList(2,3). That is really ugly, it seems that you are taking a sublist of 2 elements. On the other hand, X.subList(2,2) is an empty list - quite confusing.

int startIndex = calculateStartIndex();
int endIndex = calculateEndIndex();
X.subList(startIndex, endIndex);

Actually, if (startIndex == endIndex) → empty list.

Your question was: why, so here is my answer. What would happen if both parameters in Java were inclusive? you would have a problem when you need to take an empty list in case you calculate the second index. Because in most of cases the indexes are calculated and we don't write directly numbers in functions.

In order to have an empty list, unless you use a convenction (example: in case of negative or lower endIndex return empty list) - but such convenction could hide errors in coding (there is no difference if the second parameter is -1 or -100!):

int startIndex = calculateStartIndex(); // return 0
int endIndex = calculateEndIndex();     // return 0
X.subList(startIndex, endIndex);        // this would return the 1st element of the list; how to get an empty list? Convenction needed!
                                        // use a negative number to get empty list? And what if endIndex is negative because of a bug?

I this case, C wins; more readable in any case, it's a pity they changed that. But this is just an additional comment you can ingore.


In addition to what Bohemian said:

If it were exclusive, to get the first 4 characters in a String, you'd have to:

String firstFour = String.substring(0, 3);

That's rather ugly.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号