1. 개요
Java 8에서 도입 된 forEach 루프는 프로그래머 에게 컬렉션을 반복하는 새롭고 간결하며 흥미로운 방법을 제공합니다.
이 튜토리얼에서는 컬렉션과 함께 forEach 를 사용하는 방법 , 인수의 종류,이 루프가 향상된 for-loop 와 어떻게 다른지 살펴볼 것 입니다.
일부 Java 8 개념을 다듬어야하는 경우 기사 모음이 도움이 될 수 있습니다.
2. forEach의 기초
Java에서 Collection 인터페이스에는 Iterable 이 수퍼 인터페이스로 있습니다. 이 인터페이스에는 Java 8로 시작하는 새로운 API가 있습니다.
void forEach(Consumer<? super T> action)
간단히 말해 forEach 의 Javadoc 은 " 모든 요소가 처리되거나 작업이 예외를 throw 할 때까지 Iterable 의 각 요소에 대해 지정된 작업을 수행합니다"라고 말합니다 .
따라서 forEach 를 사용하면 다른 Iterator 처럼 컬렉션을 반복하고 각 요소에 대해 주어진 작업을 수행 할 수 있습니다 .
예를 들어, 문자열 컬렉션 을 반복하고 인쇄하는 for-loop 버전을 고려하십시오 .
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<String> printConsumer = new Consumer<String>() {
public void accept(String name) {
System.out.println(name);
};
};
forEach 에 인수로 전달할 수 있습니다 .
names.forEach(printConsumer);
그러나 이것이 소비자를 통해 작업을 생성하고 forEach API를 사용하는 유일한 방법은 아닙니다 .
forEach 메서드를 가장 많이 사용하는 세 가지 방법을 살펴 보겠습니다 .
3.1. 익명 소비자 구현
익명 클래스를 사용하여 Consumer 인터페이스 의 구현을 인스턴스화 한 다음 forEach 메서드에 인수로 적용 할 수 있습니다 .
Consumer<String> printConsumer= new Consumer<String>() {
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. 컬렉션 반복
컬렉션 유형의 모든 이터 러블 — list , set , queue 등 — forEach 를 사용하는 데 동일한 구문이 있습니다.
따라서 우리가 본 것처럼 List의 요소를 다음과 같이 반복 할 수 있습니다.
List<String> names = Arrays.asList("Larry", "Steve", "James");
names.forEach(System.out::println);
그리고 세트는 비슷합니다.
Set<String> uniqueNames = new HashSet<>(Arrays.asList("Larry", "Steve", "James"));
uniqueNames.forEach(System.out::println);
마지막으로 컬렉션 이기도 한 Queue 를 살펴 보겠습니다 .
Queue<String> namesQueue = new ArrayDeque<>(Arrays.asList("Larry", "Steve", "James"));
namesQueue.forEach(System.out::println);
4.2. Map의 forEach를 사용하여 맵 반복
맵은 Iterable 이 아니지만 BiConsumer 를 허용하는 forEach 의 자체 변형을 제공합니다 .
자바는 8 개 소개하는 BiConsumer 대신 소비자 의 Iterable의에 대해 forEach 액션이의 키와 값을 모두 수행 할 수 있도록 Map 를 동시에.
다음 항목 으로 맵 을 생성 해 보겠습니다 .
Map<Integer, String> 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 를 사용하여 Map 항목을 반복했습니다 .
(key, value) -> System.out.println(key + " " + value)
4.3. entrySet 를 반복 하여 맵 반복
Iterable의 forEach를 사용하여 Map 의 EntrySet 을 반복 할 수도 있습니다 .
때문에 a의 항목 Map가 A의 저장되어있는 세트 라는 EntrySet을, 우리는 사용하는 것을 반복 할 수 대해 forEach를 :
namesMap.entrySet().forEach(entry -> System.out.println(
entry.getKey() + " " + entry.getValue()));
5. Foreach 대 For-Loop
단순한 관점에서 두 루프는 동일한 기능을 제공합니다. 즉, 컬렉션의 요소를 반복합니다.
그들 사이의 주요 차이점은 서로 다른 반복 자라는 것입니다. 향상된 for 루프 는 외부 반복자 인 반면 새로운 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);
}
List을 반복하는 동안 명시 적으로 hasNext () 또는 next () 메서드를 호출하지는 않지만 이 반복 작업을 수행하는 기본 코드는 이러한 메서드를 사용합니다. 이것은 이러한 작업의 복잡성이 프로그래머에게 숨겨져 있지만 여전히 존재한다는 것을 의미합니다.
컬렉션이 자체적으로 반복을 수행하는 내부 반복 기와는 달리, 여기에서는 컬렉션에서 모든 요소를 가져 오는 외부 코드가 필요합니다.
6. 결론
이 기사에서 우리는 forEach 루프가 일반 for 루프 보다 더 편리 하다는 것을 보여주었습니다 .
또한 forEach 메서드가 작동하는 방식과 컬렉션의 각 요소에 대해 작업을 수행하기 위해 인수로받을 수있는 구현 유형 도 살펴 보았습니다 .
마지막으로이 기사에 사용 된 모든 스 니펫은 GitHub 저장소 에서 사용할 수 있습니다 .
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/foreach-java
'Java' 카테고리의 다른 글
Spring WebClient 호출 로깅 (0) | 2021.03.08 |
---|---|
Spring Boot에서 테스트 (0) | 2021.03.08 |
JPA의 다 대다 관계 (0) | 2021.03.08 |
스프링 JDBC (0) | 2021.03.07 |
Java 경고 "Unchecked Cast" (0) | 2021.03.07 |