我的代码:
List<Integer> ints = Stream.of(1,2,4,3,5).collect(Collectors.toList());
ints.forEach((i)-> System.out.print(ints.get(i-1)+ " "));
out put:
1 2 3 4 5
我的问题是为什么我必须在get方法中使用i-1? i-1会阻止边界问题吗?
下面的代码是否像for循环迭代一样?
(i)-> System.out.print(ints.get(i-1))
以上代码等于此
for(Ineger i:ints)
System.out.print(ints.get(i));
答案 0 :(得分:13)
lambda参数i
获取集合中项目的值,而不是索引。您正在减去1
,因为这些值恰好是一个大于其索引的值。
如果您尝试使用
List<Integer> ints = Stream.of(10,20,40,30,50).collect(Collectors.toList());
ints.forEach((i)-> System.out.print(ints.get(i-1)+ " "));
您会发现代码效果不佳。
你应该能够做到(不需要进行get
通话)
ints.forEach((i)-> System.out.print(i + " "));
你的lambda和你提出的for循环不是等价的。
ints.forEach((i)-> System.out.print(ints.get(i-1)))
等同于
for(Integer i:ints)
System.out.print(ints.get(i-1));
请注意保留-1。
回应评论:
Lambda不是循环,它们是函数(无论如何都是有效的)。在第一个示例中,forEach
方法提供了循环功能。参数lambda是每次迭代时应该做的参数。这相当于for循环的 body
在注释的示例中,max
是提供循环行为的函数。它将迭代(执行循环)项目以找到最大值)。您提供的lambda i -> i
将是身份函数。它需要一个参数并返回该对象未修改。
假设您有一个更复杂的对象,并且想要在特定成员(例如GetHighScore()
)上对它们进行比较。然后,您可以使用i -> i.GetHighScore()
来获得得分最高的对象。
答案 1 :(得分:1)
Java中的列表索引是从0开始的。
因此:
ints.get(0) == 1;
ints.get(1) == 2;
ints.get(2) == 3;
//etc...
您为每个&#34; i&#34;调用ints.get(i-1)在哪里&#34;我&#34;等于列表中每个元素的值&#34; ints&#34;。
如果你打电话给ints.get(i)
,那么您将获取 index 等于1,2,3,4和5的元素,并且5不会是有效索引到包含5个元素的列表中。
此代码:
ints.forEach((i)-> System.out.print(ints.get(i-1)+ " "));
相当于:
for(int i : ints ) {
System.out.print(ints.get(i-1) + " ");
}
你的例子并不等同。
答案 2 :(得分:0)
这是一个愿望,而不是解决方案!其他语言(例如NodeJS / JavaScript)具有类似的循环,该循环将两个参数传递给lambda。参数i是索引,参数j是容器中的项目(与容器类型无关)。
ints.forEach((i,j)-> System.out.print(“索引为$ {i},项目为$ {j}”,i,j));