Java 8 forEach 가이드

1. 개요

Java 8에 도입 된 forEach 루프는 프로그래머 에게 컬렉션을 반복하는 새롭고 간결하며 흥미로운 방법을 제공 합니다.

이 기사에서는 컬렉션과 함께 forEach 를 사용하는 방법 , 어떤 종류의 인수 를 사용 하는지,이 루프가 향상된 for-loop 와 어떻게 다른지 살펴볼 것 입니다.

Java 8의 몇 가지 개념을 다듬어야하는 경우 도움이 될 수있는 기사 모음이 있습니다.

2. forEach의 기초

Java에서 Collection 인터페이스는 Iterable 을 수퍼 인터페이스로 가지고 있으며 Java 8 부터이 인터페이스에는 새로운 API가 있습니다.

void forEach(Consumer action)

간단히 말해서,의 자바 독 대해 forEach는 그것이 그 통계 "가 수행의 Iterable의 각 요소에 대한 소정의 동작이 모든 요소가 처리 될 때까지 또는 작업이 예외가 발생합니다."

따라서 forEach 를 사용하면 컬렉션을 반복하고 다른 Iterator 와 마찬가지로 각 요소에 대해 지정된 작업을 수행 할 수 있습니다 .

예를 들어 문자열 컬렉션 을 반복하고 인쇄 하는 for 루프 버전 :

for (String name : names) { System.out.println(name); }

forEach 를 사용하여 다음 과 같이 작성할 수 있습니다 .

names.forEach(name -> { System.out.println(name); });

3. forEach 메소드 사용

우리는 사용 대해 forEach를 콜렉션을 반복하고 각 요소에 대해 특정 작업을 수행. 수행 할 작업은 Consumer 인터페이스 를 구현하는 클래스에 포함되어 있으며 forEach 에 인수로 전달됩니다 .

소비자 인터페이스 기능 인터페이스 (하나의 추상적 인 방법으로 인터페이스)입니다. 입력을 받아들이고 결과를 반환하지 않습니다.

정의는 다음과 같습니다.

@FunctionalInterface public interface Consumer { void accept(T t); }

따라서 모든 구현, 예를 들어 단순히 String을 인쇄하는 소비자 :

Consumer printConsumer = new Consumer() { public void accept(String name) { System.out.println(name); }; };

forEach 에 인수로 전달할 수 있습니다 .

names.forEach(printConsumer);

그러나 이것이 소비자를 통해 액션을 생성하고 forEach API를 사용하는 유일한 방법은 아닙니다 .

forEach 메서드를 사용할 때 가장 많이 사용되는 3 가지 방법을 살펴 보겠습니다 .

3.1. 익명 소비자 구현

익명 클래스를 사용하여 Consumer 인터페이스 의 구현을 인스턴스화 한 다음 forEach 메서드에 대한 인수로 적용 할 수 있습니다 .

Consumer printConsumer= new Consumer() { public void accept(String name) { System.out.println(name); } }; names.forEach(printConsumer);

이것은 잘 작동하지만 위의 예제에서 분석하면 실제 사용되는 부분이 accept () 메서드 내부의 코드임을 알 수 있습니다 .

Lambda 표현식이 이제이를 수행하는 일반적인 방법이며 더 쉬운 방법이지만 소비자 인터페이스 를 구현하는 방법을 아는 것은 여전히 ​​가치가 있습니다.

3.2. 람다 식

Java 8 기능 인터페이스의 주요 이점은 Lambda 표현식을 사용하여 인스턴스화하고 부피가 큰 익명 클래스 구현 사용을 피할 수 있다는 것입니다.

으로 소비자 인터페이스 기능 인터페이스, 우리는의 형태로 람다 그것을 표현할 수있다 :

(argument) -> { //body }

따라서 printConsumer 는 다음을 단순화합니다.

name -> System.out.println(name)

그리고 다음과 같이 forEach에 전달할 수 있습니다 .

names.forEach(name -> System.out.println(name));

Java 8에 Lambda 표현식이 도입 된 이후로 이것은 아마도 forEach 메서드 를 사용하는 가장 일반적인 방법 일 것입니다 .

Lambda는 매우 실제적인 학습 곡선을 가지고 있으므로 시작하는 경우이 글에서는 새로운 언어 기능을 작동하는 몇 가지 모범 사례를 살펴 봅니다.

3.3. 방법 참조

클래스에서 작업을 수행하기 위해 메서드가 이미 존재하는 일반 Lambda 구문 대신 메서드 참조 구문을 사용할 수 있습니다.

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

4. forEach 작업

4.1. 컬렉션 반복

컬렉션 유형의 모든 이터 러블 – 목록, 집합, 대기열 등은 forEach 를 사용하기위한 동일한 구문을 갖습니다 .

따라서 이미 살펴본 것처럼 목록의 요소를 반복하려면 :

List names = Arrays.asList("Larry", "Steve", "James"); names.forEach(System.out::println);

세트의 경우 :

Set uniqueNames = new HashSet(Arrays.asList("Larry", "Steve", "James")); uniqueNames.forEach(System.out::println);

또는 컬렉션 이기도 한 큐에 대해 가정 해 봅시다 .

Queue namesQueue = new ArrayDeque(Arrays.asList("Larry", "Steve", "James")); namesQueue.forEach(System.out::println);

4.2. 맵 반복 – Map의 forEach 사용

맵은 Iterable 이 아니지만 BiConsumer 를 허용하는 자체 변형 forEach 를 제공합니다 .

BiConsumer는 대신 도입 된 소비자 의 Iterable의에 대해 forEach 액션이의 키와 값을 모두 수행 할 수 있도록 지도 를 동시에.

항목이 있는 을 만들어 보겠습니다 .

Map namesMap = new HashMap(); namesMap.put(1, "Larry"); namesMap.put(2, "Steve"); namesMap.put(3, "James");

다음으로 Map의 forEach를 사용하여 namesMap 을 반복 해 보겠습니다 .

namesMap.forEach((key, value) -> System.out.println(key + " " + value));

여기에서 볼 수 있듯이 BiConsumer를 사용했습니다 .

(key, value) -> System.out.println(key + " " + value)

Map 의 항목을 반복합니다 .

4.3. 이상 반복 지도 - 순회에 의해 entrySet

Iterable의 forEach를 사용하여 MapEntrySet 을 반복 할 수도 있습니다 .

때문에 a의 항목 지도가 A의 저장되어있는 세트 라는 EntrySet을, 우리는 사용하는 것을 반복 할 수 대해 forEach를 :

namesMap.entrySet().forEach(entry -> System.out.println( entry.getKey() + " " + entry.getValue()));

5. Foreach 대 For-Loop

단순한 관점에서 두 루프는 컬렉션의 요소를 반복하는 동일한 기능을 제공합니다.

둘 사이의 주요 차이점은 서로 다른 반복 자라는 것입니다. 향상된 for-loop 는 외부 반복기이고 새로운 forEach 메소드는 내부 반복기 입니다.

5.1. 내부 반복기 – forEach

이 유형의 반복기는 백그라운드에서 반복을 관리하고 프로그래머는 컬렉션의 요소로 수행 할 작업을 코딩 할 수만 있습니다.

대신 반복기는 반복을 관리하고 요소를 하나씩 처리합니다.

내부 반복기의 예를 살펴 보겠습니다.

names.forEach(name -> System.out.println(name));

위의 forEach 메서드에서 제공된 인수가 람다 식임을 알 수 있습니다. 즉, 메서드 는 수행 할 작업 만 알면 되고 모든 반복 작업은 내부적으로 처리됩니다.

5.2. 외부 반복기 – for-loop

외부 반복기 는 루프가 수행 되는 내용방법을 혼합합니다 .

Enumerations , Iterators 및 향상된 for-loop 는 모두 외부 반복자입니다 ( iterator (), next () 또는 hasNext () ? 메서드를 기억하십시오 ). 이 모든 반복기에서 반복을 수행하는 방법을 지정하는 것이 우리의 임무입니다.

이 익숙한 루프를 고려하십시오.

for (String name : names) { System.out.println(name); }

목록을 반복하는 동안 명시 적으로 hasNext () 또는 next () 메서드를 호출하지는 않지만 이 반복 작업을 수행하는 기본 코드는 이러한 메서드를 사용합니다. 이것은 이러한 작업의 복잡성이 프로그래머에게 숨겨져 있지만 여전히 존재한다는 것을 의미합니다.

컬렉션이 자체적으로 반복을 수행하는 내부 반복기와 달리, 여기에서는 컬렉션에서 모든 요소를 ​​가져 오는 외부 코드가 필요합니다.

6. 결론

이 기사에서 우리는 forEach 루프가 일반 for 루프 보다 더 편리 하다는 것을 보여주었습니다 .

또한 forEach 메서드가 작동하는 방식과 컬렉션의 각 요소에 대해 작업을 수행하기 위해 인수로받을 수있는 구현 유형 도 살펴 보았습니다 .

마지막으로이 기사에 사용 된 모든 스 니펫은 Github 저장소에서 사용할 수 있습니다.