当 Consumer 只接受一个参数时,为什么 forEach 方法接受调用具有多个参数的方法的 lambda?
Why does forEach method accept lambda that invokes method with multiple arguments when Consumer only takes one argument?
我正在 List<String>
上玩 forEach
,但我对为什么可以接受以下行感到困惑:
policies.forEach(policy -> test.addToDatabase(policy, stats));
由于forEach
需要一个Consumer
,而Consumer
accept方法只有一个参数,我不明白为什么调用addtoDatabase
是可以接受的,因为它需要两个参数。请参阅下面的完整测试代码。请注意,我只是在这里玩来学去,所以这段代码并不意味着完美或优雅。
public class ConsumerTest {
private Random random = new Random();
public static void main(String[] args) {
ConsumerTest test = new ConsumerTest();
List<String> policies = new ArrayList<>();
policies.add("11111");
policies.add("22222");
policies.add("33333");
policies.add("44444");
policies.add("55555");
Stats stats = test.new Stats();
policies.forEach(policy -> test.addToDatabase(policy, stats));
System.out.println("Success count: " + stats.getSuccessCount() + "\nFailure count: " + stats.getFailureCount());
}
private void addToDatabase(String policy, Stats stats) {
// simulate success/failure adding to DB with Random
if (random.nextBoolean()) {
stats.incrementSuccessCount();
System.out.println("Success for Policy " + policy);
} else {
stats.incrementFailureCount();
System.out.println("Failure for Policy " + policy);
}
}
class Stats {
private int successCount;
private int failureCount;
public void incrementSuccessCount() {
successCount++;
}
public void incrementFailureCount() {
failureCount++;
}
public int getSuccessCount() {
return successCount;
}
public int getFailureCount() {
return failureCount;
}
}
}
I am playing with forEach on a List of Strings, and I'm confused about why the following line is acceptable:
policies.forEach(policy -> test.addToDatabase(policy, stats));
是的。您将 Iterable::forEach
的参数与 lambda 表达式中语句的参数混淆了。由于 Iterable::forEach
is Consumer<T>
中唯一的参数只不过是完全相同的匿名 class:
的实现
Consumer<String> consumer = new Consumer<>() {
@Override
public void accept(final String policy) {
test.addToDatabase(policy, stats)
}
};
policies.forEach(consumer);
等同于:
Consumer<String> consumer = policy -> test.addToDatabase(policy, stats);
policies.forEach(consumer);
里面的内容无关紧要 - 传入 Iterable::forEach
的参数数量仍然只有一个:
policies.forEach(policy -> {
log.info("adding to database");
test.addToDatabase(policy, stats);
log.info("added to database");
});
理论上,您可以使用无限数量的语句和变量。在 lambda 表达式中使用的唯一条件必须是 effectively final.
我正在 List<String>
上玩 forEach
,但我对为什么可以接受以下行感到困惑:
policies.forEach(policy -> test.addToDatabase(policy, stats));
由于forEach
需要一个Consumer
,而Consumer
accept方法只有一个参数,我不明白为什么调用addtoDatabase
是可以接受的,因为它需要两个参数。请参阅下面的完整测试代码。请注意,我只是在这里玩来学去,所以这段代码并不意味着完美或优雅。
public class ConsumerTest {
private Random random = new Random();
public static void main(String[] args) {
ConsumerTest test = new ConsumerTest();
List<String> policies = new ArrayList<>();
policies.add("11111");
policies.add("22222");
policies.add("33333");
policies.add("44444");
policies.add("55555");
Stats stats = test.new Stats();
policies.forEach(policy -> test.addToDatabase(policy, stats));
System.out.println("Success count: " + stats.getSuccessCount() + "\nFailure count: " + stats.getFailureCount());
}
private void addToDatabase(String policy, Stats stats) {
// simulate success/failure adding to DB with Random
if (random.nextBoolean()) {
stats.incrementSuccessCount();
System.out.println("Success for Policy " + policy);
} else {
stats.incrementFailureCount();
System.out.println("Failure for Policy " + policy);
}
}
class Stats {
private int successCount;
private int failureCount;
public void incrementSuccessCount() {
successCount++;
}
public void incrementFailureCount() {
failureCount++;
}
public int getSuccessCount() {
return successCount;
}
public int getFailureCount() {
return failureCount;
}
}
}
I am playing with forEach on a List of Strings, and I'm confused about why the following line is acceptable:
policies.forEach(policy -> test.addToDatabase(policy, stats));
是的。您将 Iterable::forEach
的参数与 lambda 表达式中语句的参数混淆了。由于 Iterable::forEach
is Consumer<T>
中唯一的参数只不过是完全相同的匿名 class:
Consumer<String> consumer = new Consumer<>() {
@Override
public void accept(final String policy) {
test.addToDatabase(policy, stats)
}
};
policies.forEach(consumer);
等同于:
Consumer<String> consumer = policy -> test.addToDatabase(policy, stats);
policies.forEach(consumer);
里面的内容无关紧要 - 传入 Iterable::forEach
的参数数量仍然只有一个:
policies.forEach(policy -> {
log.info("adding to database");
test.addToDatabase(policy, stats);
log.info("added to database");
});
理论上,您可以使用无限数量的语句和变量。在 lambda 表达式中使用的唯一条件必须是 effectively final.