我正在学习Java,我有兴趣学习如何使用list foreach方法,而不是使用手动构造的for循环。我怀疑他们可以表现相同。
我目前的代码如下:
while(!this.cards.isEmpty()) {
for(int i = 0; i < this.table.GetPlayerCount() && !this.cards.isEmpty(); i++) {
DealOneCardToPlayer(this.table.players.get(i) ,this.cards.get(0));
this.cards.remove(0);
}
}
我怀疑有一种方法可以使用这样的东西:
this.cards.foreach() { do suff }
但是我还没能完全掌握语法......有人可以快点给我一个吗?
答案 0 :(得分:2)
我认为你可以通过迭代卡的索引来做到这一点:
IntStream.range(0, this.cards.size()).forEach(idx -> {
DealOneCardToPlayer(
this.table.players.get(idx % this.table.GetPlayerCount()),
this.cards.get(idx));
});
虽然这不会随着你去掉卡片;如果您确实需要this.cards
之后为空:
this.cards.clear();
如果你想限制发出的牌数(例如你想向每个玩家交易N卡),最简单的方法是提取一个子列表,然后只应用上面相同的方法:
List<Card> cardsToDeal = this.cards.subList(0, numCardsToDeal);
IntStream.range(0, cardsToDeal.size()).forEach(idx -> {
DealOneCardToPlayer(
this.table.players.get(idx % this.table.GetPlayerCount()),
cardsToDeal.get(idx));
});
cardsToDeal.clear();
答案 1 :(得分:1)
你在谈论Java 8的Function API(和lambdas)。
基本上,lambdas是函数/方法的速记兄弟,它们具有输入和潜在的返回值。对于#forEach
,它要求您提供一个接受T
(您的列表类型)的函数,并且不返回任何内容。这被称为Consumer
。然后,该方法将获取您提供的Consumer
,并为列表中的每个元素调用它。
对于等效性,就开发时而言,这些基本上是相同的:
void someConsumerMethod(Card c) {
//lambda code block
}
(Card c) -> //lambda code block
this::someConsumerMethod //direct reference to the first method
一个例子是:
this.cards.forEach(c -> {
System.out.println(c); //fully expanded
});
this.cards.forEach(c -> System.out.println(c)); //shorthand / one-liner
//or, since println already matches a Consumer<Object>, we can method reference it!
this.cards.forEach(System.out::println);
至于调整你的例子,我不建议你在迭代时修改一个集合(至少,不是没有使用Iterator#remove
)。 Andy Turner的回答已经向您展示了如何使用IntStream
的应用程序来迭代您想要的索引。
答案 2 :(得分:0)
您正在寻找的是lambda表达式。 forEach方法采用功能接口(具有一个抽象方法的接口),这意味着它可以按如下方式使用:
List<String> myList;
myList.forEach((String s) -> System.out.println(s));
来源:http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html
答案 3 :(得分:0)
您的意思是您希望在列表中使用新的Java 8流。
所以语法如下:
this.cards.stream().forEach(card -> {// do something here});
您可以调用 stream()来访问方法 forEach()。
或直接使用您的列表:
this.cards.forEach(...);
在我的例子中,我使用新的Java 8箭头函数,这是避免匿名类的锅炉板的一种方便的方法(很多进化)。
您可以将方法传递给 forEach():
this.cards.stream().forEach(doSomethingWithMyCard);
答案 4 :(得分:0)
您可以跟踪当前的玩家索引,并迭代卡片包,完全分发它:
int playerIndex = 0;
for(Card card : cards){
DealOneCardToPlayer(this.table.players.get(playerIndex) , card);
if(playerIndex == this.table.GetPlayerCount()-1)
playerIndex = 0;
else
playerIndex = playerIndex + 1;
}
如果您只想为每位玩家分发一张卡,请替换
if(playerIndex == this.table.GetPlayerCount()-1)
playerIndex = 0;
else
playerIndex = playerIndex + 1;
使用:
if(playerIndex == this.table.GetPlayerCount()-1)
break;
答案 5 :(得分:0)
您的示例并不适合转换为forEach
调用,因为您拥有所有这些额外条件和内容。您还在修改for循环中的列表。由于这些原因,你最好坚持使用for循环。
如果要改变列表中的对象,或者只想访问列表中的每个项目,可以使用forEach
调用。
语法如下:
list.forEach(item -> <insert the stuff you want to do to the item here>);
以下是一些展示如何使用forEach
的示例。我还提供了等效的循环:
// forEach
list.forEach(item -> item.setSomeProperty(1));
// for loop
for (int i = 0 ; i < list.size() ; i++) {
list.get(i).setSomeProperty(1);
}
// forEach
list.forEach(item -> item.doStuff());
// for loop
for (int i = 0 ; i < list.size() ; i++) {
list.get(i).doStuff()
}
// forEach
list.forEach(item -> System.out.println(item));
// for loop
for (int i = 0 ; i < list.size() ; i++) {
System.out.println(list.get(i));
}
希望您可以通过查看上面的示例来理解语法。
请注意,最后一个示例可以简化为:
list.forEach(System.out::println);
我们基本上告诉它在每个项目上致电System.out::println
。