Kic*_*ski -5 java foreach lambda java-8
为什么我使用下面的代码 IndexOutOfBoundsException
码:
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) + " ");
});
Run Code Online (Sandbox Code Playgroud)
我的错误堆栈:
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
Run Code Online (Sandbox Code Playgroud)
但是当我将列表更改为一位数时,一切都很好
码:
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) + " ");
});
Run Code Online (Sandbox Code Playgroud)
输出:
2 8 7 4 3
Run Code Online (Sandbox Code Playgroud)
更简单:
String s = Stream.of(21,22,32,42,52)
.collect(Collectors.joining(" "));
Run Code Online (Sandbox Code Playgroud)
我认为原因很清楚.
ints.forEach((i) -> {
System.out.print(ints.get(i-1) + " ");
});
Run Code Online (Sandbox Code Playgroud)
翻译大致到:
for (Integer i : ints) {
System.out.println(ints.get(i - 1) + " ");
}
Run Code Online (Sandbox Code Playgroud)
这将导致IndexOutOfBoundsExceptions因为i引用每个列表的元素,并且每个元素 - 1将给出明显超出范围的索引.对于您的第一个示例,i将21提供索引21 - 1 == 20,该索引超出您创建的列表的范围.
例:
List<Integer> ints = Stream.of(21,22,32,42,52).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
最终会这样结束
ints == [21, 22, 32, 42, 52]
Run Code Online (Sandbox Code Playgroud)
所以当你运行这个:
ints.forEach((i) -> {
System.out.print(ints.get(i-1) + " ");
});
Run Code Online (Sandbox Code Playgroud)
计算机获取第一个元素并尝试执行lambda的主体:
Execute System.out.print(ints.get(i-1) + " ");:
First element is 21
21 - 1 == 20
ints.get(20) --> IndexOutOfBoundsException
Run Code Online (Sandbox Code Playgroud)
而对于你的第二个例子:
List<Integer> ints = Stream.of(2,8,7,4,3).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
变
ints == [2, 8, 7, 4, 3]
Run Code Online (Sandbox Code Playgroud)
所以当你运行这个:
ints.forEach((i) -> {
System.out.print(ints.get(i-1) + " ");
});
Run Code Online (Sandbox Code Playgroud)
计算机遍历元素并尝试执行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
Run Code Online (Sandbox Code Playgroud)
显然,你的第二个例子中的代码并不是你实际拥有的代码.我怀疑你实际拥有的代码是:
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
});
Run Code Online (Sandbox Code Playgroud)
这与你发布的完全不同.
对Iterable的每个元素执行给定操作,直到处理完所有元素或操作抛出异常为止.
所以i在
(i) -> {System.out.print(ints.get(i-1) + " ");}
Run Code Online (Sandbox Code Playgroud)
是每个元素List.如果减去1的任何元素大于或等于5(大小List),则尝试获取超出范围的元素.