자바8은 자바 역사 상 가장 큰 변화가 일어났다. 물론 자바 9, 10 에도 변화가 있지만 8만큼 획기적이거나 생산성이 바뀐것은 아니었다. 변화 덕분에 프로그램 구현은 훨씬 쉬워졌다.
아래 코드는 사과 목록을 무게 순으로 정렬하는 코드이다.
Collections.sort(inventory,new Comparator<Apple>(){
public int compare(int a, int b){
return a.getWeight().compareTo(b.getWeight());
}
});
하지만 이처럼 4줄에 달하는 코드를 자바8이 등장하며 아래와 같은 방식으로 구현할 수 있다.
inventory.sort(comparing(Apple::getWeight));
위 코드에 대한 설명은 앞으로 책에서 설명하게 될 것이다!
스트림 API란 데이터베이스 질의언어에서 표현식을 처리하는 것처럼 병렬 연산을 지원하는 API이다.
스트림이란?
한번에 한 개씩 만들어지는 연속적인 데이터 항목들의 모임이다. 어떤 프로그램의 출력 스트림은 다른 프로그램의 입력 스트림이 될 수 있다.
자동차 생산 공장에 이를 비유해보자. 자동차 생산 공장 각각의 작업장에서는 자동차를 받아서 수리한 후 다음 작업장에서 다른 작업을 처리할 수 있도록 넘겨준다. 여러 자동차로 구성된 생산 라인을 스트림이라고 이해할 수 있다.
스트림 API의 핵심
자바8에는 java.util.stream 패키지에 스트림 API가 추가되었다.
스트림 API의 핵심은 우리가 하려는 작업을 고수준으로 추상화해서 일련의 스트림으로 만들어 처리할 수 있다는 것이다. 또한 스트림 파이프 라인을 이용해서 입력 부분을 여러 CPU 코어에 쉽게 할당할 수 있다. 스레드를 사용하지 않으면서 동시에 공짜로 병렬성을 얻을 수 있다.
스트림API는 '컬렉션을 처리하면서 발생하는 모호함과 반복적인 코드 문제' 그리고 '멀티코어 활용 어려움'이라는 두가짐 문제를 모두 해결했다. 기존의 컬렉션에서는 데이터를 처리할 때 반복되는 패턴이 많았다. 따라서 라이브러리에서 이러한 반복되는 패턴을 제공한다면 좋을 것이라고 아이디어가 나왔다.
반복되는 패턴으로 주어진 조건에 따라 데이터를 필터링 하거나 데이터를 추출하거나 그룹화하거는 기능이 있다.
이제는 컬렉션을 스트림으로 바꾼 후 병렬로 처리하여 다시 리스트로 복원하면 빠르게 데이터를 필터링하고 그룹화할 수 있다.
자바 8부턴 코드의 일부를 API전달할 수 있다. sort 메소드를 생각해보자.
예를 들어 2013UK0001, 2014US0002.. 등의 형식을 갖는 송장 ID가 있다고 가정하자. 처음 네개 숫자는 연도를, 다음 두 글자는 국가 코드를, 마지막 네개 숫자는 고객ID를 뜻한다. 이제 우리는 이 송장 ID를 고객 ID 혹은 국가 코드 순으로 정렬해야한다. 즉, sort가 고객ID나 국가 코드로 송장ID를 정렬하도록 sort에 따로 코드를 제공해야 한다.
자바 8 이전에는 메서드를 다른 메서드로 전달할 방법이 없었다. 아까 위에서 본 코드 예제처럼 Comparator 객체를 만들어서 sort에 넘겨줄 순 있다. 하지만 자바 8에서는 메서드를 다른 메서드의 인수로 넘겨주는 기능을 제공한다. 이를 바로 동작 파라미터화라고 부른다.

compareUsingCustomerId를 이용해 sort의 동작을 파라미터화 할 수 있다. 동작 파라미터화는 앞으로 더 자세히 설명할 예정이다.
일급이란?
자바 프로그램에서 조작할 수 있는 값을 생각해보자. 첫번째로 int 형식, double 형식 등의 기본값이다. 두번째로 객체도 값이다. 그리고 함수는 이러한 값들을 바꿀 수 있다. 이처럼 함수로 값을 바꿀 수 있는 것을 일급이라고 부른다. 자바 프로그래밍 언어의 다양한 구조체(메서드, 클래스 같은)가 값의 구조를 표현하는 데 도움이 될 수 있다. 하지만 모든 구조체를 자유롭게 전달할 수 는 없다. 이렇게 전달할 수 없는 구조체는 이급이다. 즉, 메서드와 클래스 등은 이급 시민이다. 이들은 그 자체로 값이 될 수 없다.
자바 8에서는 이급 시민을 일급 시민으로 바꿀 수 있는 기능을 추가했다.
메서드 참조
아래 코드는 FileFilter 객체 내부에 위치한 isHidden결과를 File.listFiles 메서드로 전달하는 코드이다.
File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
public boolean accept(File file){
return file.isHidden();
}
});
FileFilter객체 내부에 위치한 isHidden()결과를 File.listFiles 메서드로 전달했다.
하지만 이제 자바 8에서는 위와 같은 코드를 한줄로 바꿀 수 있다.
File[] hiddenFiles = new File(".").listFiles(File::isHidden);
이제 :: (이 메서드를 값으로 사용하라는 의미) 를 이용하여 listFiles에 메서드를 전달할 수 있다.
따라서 이제 메서드도 이급이 아닌 일급값이 되었다! 기존에 new로 객체 참조를 생성함으로써 객체를 주고받았던 것처럼 File::isHidden을 이용해 메서드를 참조하고 전달할 수 있다.
filterApples(inventory, (Apple a) -> GREEN.equals(a.getColor());
filterApples(inventory, (Apple a) -> a.getWeight() > 150);
람다를 이용하면 위처럼 간결하게 코드를 짤 수 있다. 즉, 한번만 사용할 메서드는 따로 정의할 필요가 없다.
그 유명한 '모던 자바 인 액션'을 이제서야 읽기 시작했다! 맹목적으로 스트림이 간결하니까 쓰자!! 이게 아니라 스트림 API의 탄생 배경도 알며 자바의 역사를 알게 되니 흥미롭다. 앞으로의 챕터에서도 알게될 자바의 진화(?)가 궁금하다. 그리고 확실히 블로깅을 하니 공부한 것을 내 것으로 만드는 느낌이다ㅎㅎ 앞으로도 열심히 블로깅해야지!!