[모던 자바 인 액션] Chapter1. 자바 8, 9, 10, 11 무슨 일이 일어나고 있는가?

SunYerim·2024년 1월 20일
0

언어

목록 보기
1/11

1.1 역사의 흐름은 무엇인가?

자바 8에서 가장 큰 변화가 일어남.

  • 사과 목록을 무게순으로 정려라는 자바 8 이전 코드
Collections.sort(inventory, new Comparator<Apple>() {
	public int compare(Apple a1, Apple a2) {
		return a1.getWeight().compareTo(a2.getWeight());
	}
});
// 위의 고전적 코드를 자바 8 버전을 이용한다면 자연어에 더 가깝게 구현 가능
inventory.sort(comparing(Apple::getWeight));

자바 8에서는 병렬 실행을 새롭고 단순한 방식으로 접근할 수 있는 방법을 제공한다.

자바 8은 간결한 코드, 멀티코어 프로세서의 쉬운 활용이라는 두 가지 요구 사항을 기반으로 한다.

  • 스트림 API
  • 메서드에 코드를 전달하는 기법
  • 인터페이스의 디폴트 메서드

자바 8은 데이터베이스 질의 언어에서 표현식을 처리하는 것처럼 병렬 연산을 지원하는 스트림이라는 새로운 API를 제공한다.

스트림을 이용하면 에러를 자주 일으키며 멀티코어 CPU를 이용하는 것보다 비용이 훨씬 비싼 키워드 synchronized 를 사용하지 않아도 된다.

스트림 API 덕분에 메서드에 코드를 전달하는 간결 기법(메서드 참조와 람다)과 인터페이스의 디폴트 메서드가 존재할 수 있음을 알 수 있다.

메서드에 코드를 전달하는 자바 8 기법은 함수형 프로그래밍에서 위력을 발휘하는데, 코드를 전달하거나 조합해서 자바의 강력한 프로그래밍 도구로 활용할 수 있다.


1.2 왜 아직도 자바는 변화하는가?

1.2.1 프로그래밍 언어 생태계에서 자바의 위치

자바는 처음부터 유용한 라이브러리를 포함하는 잘 설계된 객체지향언어로 시작했으며, 스레드와 락을 이용한 소소한 동시성도 지원했다.

코드를 JVM 바이트 코드로 컴파일하는 특징 → 인터넷 애플릿 프로그램의 주요 언어.

해당 책에서는 병렬성을 활용하는 코드, 간결한 코드를 구현할 수 있도록 자바 8에서 제공하는 기능의 모태인 세 가지 프로그래밍 개념을 설명한다.

1.2.2~4에서는 자바 8 설계의 밑바탕을 이루는 세 가지 프로그래밍 개념을 소개한다.

1.2.2 스트림 처리

  • 스트림 - 한 번에 한 개씩 만들어지는 연속적인 데이터 항목들의 모임

프로그램은 입력 스트림에서 데이터를 한 개씩 읽어 들이며 출력 스트림으로 데이터를 한 개씩 기록한다. 즉, 어떤 프로그램의 출력 스트림은 다른 프로그램의 입력 스트림이 될 수 있다.

자바 8에는 java.util.stream패키지에 스트림 API가 추가되었다.

스트림 패키지에 정의된 Stream는 T 형식으로 구성된 일련의 항목을 의미한다.

스트림 API의 핵심은 기존에는 한 번에 한 항목을 처리했지만 자바 8에서는 하려는 작업을 고수준으로 추상화해서 일련의 스트림으로 만들어 처리할 수 있다는 것이다. 스트림 파이프라인을 이용해서 입력 부분을 여러 CPU 코어에 쉽게 할당할 수 있다는 부가적인 이득도 얻을 수 있다.

스레드라는 복잡한 작업을 사용하지 않으면서도 병렬성을 얻을 수 있다.

1.2.3 동작 파라미터화로 메서드에 코드 전달하기

코드 일부를 API로 전달하는 기능이 자바 8에 추가된 두 번째 프로그램 개념이다.

메서드를 다른 메서드의 인수로 넘겨주는 기능을 제공한다. 이러한 기능을 이론적으로 동작 파라미터화라고 부른다.

1.2.4 병렬성과 공유 가변 데이터

세 번째 프로그래밍의 개념은 병렬성을 얻을 수 있다라는 말에서 시작된다.

스트림 메서드로 전달하는 코드는 다른 코드와 시에 실행되더라도 안전하게 실행될 수 있어야 한다. 다른 코드와 동시에 실행하더라도 안전하게 실행할 수 있는 코드를 만들려면 공유된 가변 데이터에 접근 하지 않아야 한다.

순수 함수, 부작용 없는 함수, 상태 없는 함수

예를 들어 두 프로세스가 공유된 변수를 동시에 바꾸려하면? → 기존처럼 synchronized 를 이용해서 공유된 가변 데이터를 보호하는 규칙을 만들 수 있을 것이다. 하지만 자바 8 스트림을 이용하면 기존의 자바 스레드 API보다 쉽게 병렬성을 활용할 수 있다.

공유되지 않은 가변 데이터, 메서드, 함수 코드를 다른 메서드로 전달하는 두 가지 기능은 함수형 프로그래밍패러다임에서 핵심적인 사항이다. 명령형 프로그래밍패러다임에서는 일련의 가변 상태로 프로그램을 정의한다.


1.3 자바 함수

자바 8에서는 함수를 새로운 값의 형식으로 추가했다. 멀티코어에서 병렬 프로그래밍을 활용할 수 있는 스트림과 연계될 수 있도록 함수를 만들었기 때문.

1.3.1 메서드와 람다를 일급 시민으로

  • 메서드 참조
    • ::
  • 람다 : 익명 함수
    • 람다 문법 형식으로 구현된 프로그램을 함수형 프로그래밍, 즉 함수를 일급값으로 넘겨주는 프로그램을 구현한다.
File[] hiddenFiles = new File(".").listFiles(File::isHidden);

1.3.3 메서드 전달에서 람다로

filterApples(inventory, (Apple a) -> GREEN.equals(a.getColor() );

한 번만 사용할 메서드는 따로 정의를 구현할 필요가 없다!


1.4 스트림

거의 모든 자바 애플리케이션은 컬렉션을 만들고 활용한다.

컬렉션에서는 반복 과정을 직접 처리해야 했는데, 즉, for-each 루프를 이용해서 각 요소를 반복하면서 작업을 수행했다. → 외부 반복

스트림 API를 이용하면 루프를 신경쓸 필요가 없으며 API에서는 라이브러리 내부에서 모든 데이터가 처리된다. → 내부 반복

1.4.1 멀티스레딩은 어렵다

조건에 따라 데이터를 필터링하거나, 데이터를 추출하거나, 데이터를 그룹화하는 등의 기능이 있다. → 라이브러리에서 반복되는 패턴을 제공

순차 처리 방식의 코드

import static java.util.stream.Collectors.toList;
List<Apple> heavyApples = inventory.stream().filter((Apple a) -> a.getWeight() > 150)
																						.collect(toList());

병렬 처리 방식의 코드

import static java.util.stream.Collectors.toList;
List<Apple> heavyApples = inventory.parallelStream().filter((Apple a) -> a.getWeght() > 150)
																										.collect(toList());

1.5 디폴트 메서드와 자바 모듈

디폴트 메서드를 이용하면 기존의 코드를 건드리지 않고도 원래의 인터페이스 설꼐를 자유롭게 확장할 수 있다. 자바 8에서는 인터페이스 규격명세에 default라는 새로운 키워드를 지원한다.


1.6 함수형 프로그래밍에서 가져온 다른 유용한 아이디어

자바 8에서는 NullPointer 예외를 피할 수 있도록 도와주는 Optional 클래스를 제공한다. Optional는 값을 갖거나 갖지 않을 수 있는 컨테이너 객체다. 이는 값이 없는 상황을 어떻게 처리할지 명시적으로 구현하는 메서드를 포함하고 있다.

Optional를 사용하면 NullPointer 예외를 피할 수 있다. 즉, 형식 시스템을 이용해서 어떤 변수에 값이 없을 때 어떻게 처리할지 명시할 수 있다

profile
내 안에 있는 힘을 믿어라.

0개의 댓글