使用List Foreach代替for()Java

时间:2016-11-04 10:54:29

标签: java list foreach

我正在学习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 }

但是我还没能完全掌握语法......有人可以快点给我一个吗?

6 个答案:

答案 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