-5

Why when I use following code I get IndexOutOfBoundsException

Code:

    List<Integer> ints = Stream.of(21,22,32,42,52).collect(Collectors.toList());
    System.out.print("the list: ");
    ints.forEach((i) -> {
        System.out.print(ints.get(i-1) + " ");
    });

My error stack:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 11, Size: 5
    at java.util.ArrayList.rangeCheck(ArrayList.java:638)
    at java.util.ArrayList.get(ArrayList.java:414)
    at Agent.lambda$main$1(Agent.java:33)
    at Agent$$Lambda$8/980546781.accept(Unknown Source)
    at java.util.ArrayList.forEach(ArrayList.java:1234)
    at Agent.main(Agent.java:32)
the list: Java Result: 1

but When I change my list to one digit numbers everything is fine

Code:

    List<Integer> ints = Stream.of(2,8,7,4,3).collect(Collectors.toList());
    System.out.print("the list: ");
    ints.forEach((i) -> {
        System.out.print(ints.get(i-1) + " ");
    });

output:

2 8 7 4 3 
10
  • 5
    Something's wrong, because both of those snippets cause IndexOutOfBoundsException on my computer. Commented Jun 26, 2014 at 18:49
  • 5
    What is i in the lambda? What does ints.get(..) do? Commented Jun 26, 2014 at 18:49
  • @SotiriosDelimanolis i am not sure cuz I am playing to figure it out them, but as far as I know i is function and return is ints.get() function Commented Jun 26, 2014 at 18:52
  • @KickButtowski Translate the lambda to a "regular" loop and you'll see why Commented Jun 26, 2014 at 18:52
  • @user3580294 how I gonna see it? why? Commented Jun 26, 2014 at 18:53

4 Answers 4

7

I think the reason is pretty clear.

ints.forEach((i) -> {
    System.out.print(ints.get(i-1) + " ");
});

Translates approximately to:

for (Integer i : ints) {
    System.out.println(ints.get(i - 1) + " ");
}

Which will cause IndexOutOfBoundsExceptions because i refers to the elements of each list, and each of those elements - 1 will give an index that is clearly out of bounds. For your first example, i will be 21, which gives an index of 21 - 1 == 20, which is out of bounds for the list you created.

Example:

List<Integer> ints = Stream.of(21,22,32,42,52).collect(Collectors.toList());

will end up so that

ints == [21, 22, 32, 42, 52]

So when you run this:

ints.forEach((i) -> {
    System.out.print(ints.get(i-1) + " ");
});

The computer takes the first element and tries to execute the body of the lambda:

Execute System.out.print(ints.get(i-1) + " ");:
    First element is 21
    21 - 1 == 20
    ints.get(20) --> IndexOutOfBoundsException

And for your second example:

List<Integer> ints = Stream.of(2,8,7,4,3).collect(Collectors.toList());

becomes

ints == [2, 8, 7, 4, 3]

So when you run this:

ints.forEach((i) -> {
    System.out.print(ints.get(i-1) + " ");
});

The computer goes through the elements and tries to execute the body of the lambda:

Execute System.out.print(ints.get(i-1) + " ");:
    First element is 2
    2 - 1 == 1
    ints.get(1) --> 8
    Print 8
Execute System.out.print(ints.get(i-1) + " ");:
    Second element is 8
    8 - 1 == 7
    ints.get(7) --> IndexOutOfBoundsException

So evidently the code in your second example is not what you actually have. I suspect that the code you actually have is:

List<Integer> ints = Stream.of(2,8,7,4,3).collect(Collectors.toList());
System.out.print("the list: ");
ints.forEach((i) -> {
    System.out.print(i + " ");
                     ^^^^^^^ <-- this is different
});

Which is entirely different than what you posted.

Sign up to request clarification or add additional context in comments.

16 Comments

@KickButtowski That's just a coincidence because of the value of elements in your list...
@KickButtowski You're not understanding what I'm saying. You're taking the elements of the list and using them as indices. It's just coincidence that the elements of that particular list happened to be valid indices, and as the accepted answer pointed out, as soon as you have elements which are too large you'll get out of bounds exceptions.
@KickButtowski Did you try both pieces of code in your question? Because both of those will throw exceptions. The code in your last question happens to be OK, but as the accepted answer pointed out, wrong values will throw exceptions
@kick If you have a list of [1, 2, 3, 4] and you subtract one from each you get [0, 1, 2, 3]. If you then use these as indices to the first list, you get the values [1, 2, 3, 4]. But if you have a list [7, 8, 9, 10], and you subtract one from each, so [6, 7, 8, 9] and then uses those as indices, you get an index out of bounds since there is no element at index 7 in [7, 8, 9, 10].
@KickButtowski Yes, and you should've understood what we just explained already in the answer there. The i in your lambda is each consecutive element in the underlying List.
|
7

Even simpler:

String s = Stream.of(21,22,32,42,52)
                 .collect(Collectors.joining(" "));

3 Comments

throw this exception when I run it Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: java.util.stream.Stream.collect at addnewlinetotxtfile.AddNewLinetoTxtFile.main(AddNewLinetoTxtFile.java:30) Java Result: 1
could you lemme know why?
This is a NetBeans-related problem, clean and rebuild your project. Also google for Uncompilable source code - Erroneous sym type---you'll get further advice on workarounds.
5

forEach javadoc states

Performs the given action for each element of the Iterable until all elements have been processed or the action throws an exception.

So the i in

(i) -> {System.out.print(ints.get(i-1) + " ");}

is each element in the List. If any of those elements minus 1 is bigger or equal to 5 (the size of the List), you try to get an element that is out of bounds.

Comments

3

You are overdoing it. What you want is

List<Integer> ints = Stream.of(2,8,7,4,3).collect(Collectors.toList());
System.out.print("the list: ");
ints.forEach((i) -> {
    System.out.print(i + " ");
});

i in the forEach is not a loop counter, it's the items themselves. So i will take on the values 2,8,7,4,3 and for the second iteration ints.get (8-1) will be out of bounds.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.