Java for循环

时间:2020-02-23 14:36:35  来源:igfitidea点击:

迭代是所有编程语言中最基本的要求之一,而" for"是Java中用于迭代的最广泛使用的循环。
我们将看到Java for循环迭代技术的发展。

Java for循环

我们将通过一个示例来显示一个Collection中的演员姓名。
为了简单起见,让我们列出一个列表并进行设置:

List<String> actors = Arrays.asList("Hyman Nicholson", "Marlon Brando", "Robert De Niro", "Al Pacino", "Tom Hanks");

让我们开始研究不同Java版本上的for循环演变。

基本的循环

" for"循环的主要元素是初始化,终止条件和循环增量逻辑。
让我们在这里看到一个示例:

for (int i = 0; i < actors.size(); i++) {
System.out.println(actors.get(i));
}

如果我们要遍历不是List类型的集合,则将没有get(int index)方法,该方法将为我们提供该集合的索引值。
因此,在Java 1.2中引入了迭代器。
让我们看看我们如何使用迭代器解决相同的问题:

for (Iterator<String> iterator = actors.iterator(); iterator.hasNext();) {
 System.out.println(iterator.next());
}

for-each(增强了循环)

此循环是Java 5中引入的,它通过完全隐藏迭代器或者索引变量来消除混乱,仪式和出错的机会。
让我们看看实际情况:

for (String actor : actors) {
 System.out.println(actor);
}

以上示例是外部迭代器的类型,此处的控制和终止逻辑驻留在外部迭代器中。
这会导致整体复杂性,并且容易出错。

内部forEach循环

在Java 8中,随着功能接口和Lambda的引入,Java架构师为我们提供了一个由Collection框架支持的内部迭代器(forEach循环),并且可以与collections对象一起使用。
此方法对集合的每个元素执行给定的操作。
让我们更详细地了解一下:

方法签名:public void forEach(Consumer action)

forEach采用了"消费者"(功能接口)的实现,该实现具有一种" accept(T t)"方法来执行循环内的逻辑。
让我们看一下实现:

actors.forEach(new Consumer<String>() {
	public void accept(String actor) {
		System.out.println(actor);
	}
});

这里为forEach方法提供了一个消费者内部匿名类接口。
此类具有accept(T t)方法,该方法将为集合的所有值调用。
该代码存在设计缺陷,每次使用forEach时,都会通过传递匿名内部类来创建一个新类。

ForLoopEvolution.class
ForLoopEvolution.class

与以前的循环相比,此解决方案看起来更加冗长和复杂。
让我们尝试以简化的方式重构它。
整个功能接口的实现可以编写为更直观的Lambda函数。
让我们看看实际情况:

actors.forEach((e) -> {
 System.out.println(e);
 });

对于每个元素e,参与者都显示在控制台中。
可以通过删除不必要的花括号和方括号来进一步简化此代码。

actors.forEach(e -> System.out.println(e));

使用lambda代替匿名内部类的主要优点是,不会污染字节码,也不会创建类,而是将对lambda的调用推迟到运行时。
让我们看一下字节码以获取更多详细信息:

动态调用可以帮助JVM从lambda表达式创建字节码,并将执行延迟到运行时。

方法推论

方法推论进一步消除了更多的仪式和冗长。
让我们重构以传递方法推断而不是lambda:

actors.forEach(System.out::println);

使用内部迭代器的另一个好处是,代码几乎可以并行处理了。
在Java 8中引入了流api之后,我们可以并行运行代码,而无需同步。
可以从集合中创建并行流以处理我们的功能。

actors.parallelStream().forEach(System.out::println);