명령형 vs. 함수형 스타일
이전 버전의 Java에서는 명령형 프로그래밍 스타일과 객체 지향 패러다임이 혼합되어 지원되었습니다. Java 8부터는 코드에 함수형 프로그래밍 스타일을 혼합할 수도 있습니다. 이전 버전의 Java에 주로 익숙한 프로그래머가 Java 7 또는 그 이후에 코드 베이스를 시작한 경우 명령형 스타일 코드로 채워집니다.
명령형 스타일은 수행해야 할 작업과 수행 방법을 알려주는 스타일입니다. 함수형 스타일은 본질적으로 선언적이며, 무엇을 할 것인지를 말하고 방법이나 세부 사항은 기본 라이브러리에 위임합니다. 명령형 스타일 코드는 대부분의 사람들이 매우 익숙하기 때문에 작성하기가 더 쉬울 수 있습니다. 하지만 코드가 장황하고 복잡하며 읽기 어렵습니다. 함수형 스타일은 대부분의 프로그래머가 익숙하지 않기 때문에 처음에는 어려울 수 있습니다. 일반적으로 함수형 스타일은 읽고, 이해하고, 변경하기가 더 쉽습니다. 연습을 하다 보면 작성하기도 쉬워집니다.
이 튜토리얼 시리즈에서는 일반적인 명령형 스타일 코드 몇 가지를 살펴보고 대신 사용할 수 있는 매핑 또는 이와 동등한 함수형 스타일 코드를 찾아보겠습니다. 코드를 기반으로 작업하다가 버그를 수정하거나 기능을 개선할 준비가 되면 명령형 스타일 코드 중 일부를 함수형 스타일로 리팩터링하는 것이 유용할 수 있습니다. 이 튜토리얼을 가이드로 삼아 몇 가지 일반적인 상황에 대한 명령형과 함수형 스타일 매핑을 찾을 수 있습니다.
이 튜토리얼에서는 간단한 루프에 중점을 두겠습니다.
Simple for Loops
범위의 인덱스 값에 대해 작업을 수행하는 기존의 for 루프부터 시작해 보겠습니다.
for(int i = 0; i < 5; i++) {
System.out.println(i);
}위 코드에서 본질은 0에서 5보다 작은 1까지의 범위입니다. how(방법) 으로부터의 나오는 관습과 노이즈인인 문법은 인덱스 변수 코드를 함수형 스타일로 바꾸면 본질을 유지하고 관습을 제거할 수 있습니다.i에 대한 증분 연산입니다.
함수형 스타일을 사용하여 이 for 루프를 작성하고 싶다면 아주 쉽게 할 수 있으며 단서는 코드 앞 문장에 있습니다: 범위에 대한 인덱스. 범위를 반복하는 것이므로 IntStream의 range 메서드가 이에 직접적으로 해당합니다.
import java.util.stream.IntStream;
...
IntStream.range(0, 5)
.forEach(i -> System.out.println(i));println 메서드에 대한 메서드 참조를 사용하면 이 과정을 더욱 간결하게 만들 수 있습니다.
import java.util.stream.IntStream;
...
IntStream.range(0, 5)
.forEach(System.out::println);함수형 스타일 코드는 명령형 버전보다 더 간결하고 읽기 쉬우며 의도가 더 명확합니다.
다음 코드에서처럼 for 루프가 종료 값을 포함하도록 실행되면 어떻게 되는지 궁금할 수 있습니다.
for(int i = 0; i <= 5; i++) {
System.out.println(i);
}IntStream 인터페이스에는 이러한 목적을 위한 rangeClosed 메서드가 있습니다.
import java.util.stream.IntStream;
...
IntStream.rangeClosed(0, 5)
.forEach(System.out::println);rangeClosed 메서드는 시작 값에서 끝 값을 포함할 때까지 반복하는 데 유용합니다.
range 메서드를 사용하든 rangeClosed 메서드를 사용하든 내부 반복자를 사용하여 작업을 수행할 수 있는 int 값의 스트림을 얻게 됩니다. 이 시리즈의 후반부에서는 forEach를 넘어서는 연산에 대해 살펴보겠습니다.
이전 코드 예제에서는 내부 이터레이터가 반복 처리의 부담을 덜어주었습니다. 스트림은 값의 범위를 한 번에 하나씩 단계적으로 처리합니다. 여러분은 forEach 메서드에서 제공되는 각 요소에 대해 수행해야 할 작업에만 집중하면 됩니다. 예제에서는 제공된 값을 인쇄하기만 했습니다. 정보를 데이터베이스에 저장하거나 원격 서비스로 전송하는 등 원하는 거의 모든 작업을 수행할 수 있습니다.
for 루프가 제공하는 외부 이터레이터와 달리 내부 이터레이터를 사용하는 코드는 더 간결하고 노이즈가 적으며 인덱스 변수를 명시적으로 변경할 필요가 없고 읽기 쉽고 수정하기 쉬우며 작업하기가 더 즐겁습니다.
자신의 코드 베이스에서 기존의 for 루프가 보이는 부분을 찾아 IntStream의 range 또는 rangeClosed 메서드를 사용하도록 수정하세요. 변경 후 코드가 예상대로 작동하는지, 가급적이면 이미 가지고 있는 자동화된 테스트를 실행하여 확인하세요.
매핑하기
간단한 for 루프가 표시되는 곳이면 어디에서나 IntStream의 range 또는 rangeClosed 메서드를 사용할 수 있습니다. 끝 값을 포함하지 않고 끝 값까지 반복하려면 range 메서드를 사용합니다. 반복에 종료 값도 포함하려면 rangeClosed를 사용합니다.