자바

모던 자바 인 액션 -1-

정한_s 2021. 12. 6. 13:41

멀티코어 CPU의 대중화와 같은 하드웨어적인 변화가 자바에 영향을 미쳤다.  자바에서 스레드를 활용한 병렬 실행 환경은 개발자가 활용하기 어려웠다. 따라서 자바 8은 간결한 코드, 멀티 코어 프로세서의 쉬운 활용을 기반이다.

 

자바 8 기능

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

스트림 API

자바 8은 데이터베이스 질의 언어에서 표현식을 처리하는 것처럼 병렬 연산을 지원하는 스트림이라는 API를 제공한다. 스트림을 이용하면 자바의 스트림 라이브러리가 최적의 저수준 실행 방법으로 구현해 주기 때문에 키워드 synchronized를 사용하지 않아도 된다. 

 

*스트림 이란? : 한 번에 한 개씩 만들어지는 연속적인 데이터 항목들의 모임, 

java.util.stream 패키지 : Stream<T> T 형식으로 구성된 일련의 항목을 의미한다.

 

기존에는 한 번에 한 항목을 처리했지만 자바 8에서는 하려는 작업을 스트림으로 만들어 처리할 수 있다. 

또한 스트림 파이프라인을 이용해서 입력 부분을 여러 CPU 코어에 쉽게 할당할 수 있다.

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

 

 

병렬성과 공유 가변 데이터

스트림을 사용한다면 병렬성을 얻을 수 있다고 했다. 하지만 이러한 병렬성을 얻기 위해서는 코드의 동작 방식을 조금 바꾸어야 한다.

스트림 메서드로 전달하는 코드는 다른 코드와 동시에 실행하더라도 안전하게 실행될 수 있어야 한다.

안정하게 실행할 수 있는 코드를 만들기 위해서는 공유된 가변 데이터에 접근해야 하지 않아야 한다. 이러한 함수를 순수 함수, 부작용 없는 함수, 상태 없는 함수라고 부른다.

 

메서드에 코드를 전달하는 기법

// java8 이전의 메서드 참조(익명 클래스를 넘겨주는 우회 방식)
File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isHidden();
            }
        });
// java8 이후 메서드를 인수로 전달 가능 // 코드를 간략하게 만들 수 있다
// 메서드 참조 :: ('이 메서드를 값으로 사용하라')
// File 클래스의 isHidden의 메소드를 값으로 사용해라
File[] hiddleFiles = new File(".").listFiles(File::isHidden);

자바 8 이전의 자바에서는 메서드를 다른 메서드로 전달할 방법이 없었다. 자바 8에서는 메서드를 다른 메서드의 인수로 넘겨주는 기능을 제공한다. 이러한 기능을 동적 파라미터화라고 부른다. 

 

 

*자바의 함수

프로그래밍 언어의 핵심은 값을 바꾸는 것이다. 값이 바꿀 수 있는 것은 일급 시민이다(기본값이나 객체 인스턴스). 값의 구조를 표현하는 것은 이급 시민이다(메서드, 클래스 등). 이급 시민은 자유롭게 전달할 수 없다. 즉 메서드와 클래스는 그 자체로 값이 될 수 없다. 자바 8에서는 이급 시민을 일급 시민으로 바꿀 수 있는 기능을 추가했다(메서드).

 

*일급 시민 조건

  1. 변수나 데이터에 할당 할 수 있어야 한다.
  2. 객체의 인자로 넘길 수 있어야 한다.
  3. 객체의 리턴값으로 리턴 할수 있어야 한다.

람다 : 익명 함수

자바 8에서는 메서드를 일급값으로 취급할 뿐 아니라 람다(익명함수)를 포함하여 함수도 값으로 취급할 수 있다.

 

 

컬렉션과 스트림

컬렉션에서는 반복 과정을 직접 처리해야 했다. 각 요소를 반복하면서 작업을 수행해야했다. 이를 외부 반복이라고 한다.

스트림 API에서는 라이브러리 내무에서 모든 데이터가 처리된다. 이러한 반복을 내부 반복이라고 한다.

 

자바 8은 스트림 API로 컬렉션을 처리하면서 발생하는 '모호함과 반복적인 코드 문제' 그리고 '멀티코어 활용 어려움'이라는 두 가지 문제를 모두 해결했다. 기존의 컬렉션에서 데이터를 처리할 때 반복되는 패턴을 스트림에서 제공해주었다.(조건에 따라 필터링, 데이터 추출 데이터 그룹화 등)

 

ex) 두 CPU를 가진 환경에서 리스트를 필터링 할 때 병렬화 방법

filter를 두개의 CPU로 포킹한 다음 결과를 합친다

인터페이스의 디폴트 메서드 

인터페이스에 default 라는 키워드를 통해, 구현 클래스에서 구현하지 않아도 되는 메서드를 인터페이스에 추가할 수 있다. 이는 기존의 구현을 고치지 않고도 이미 공개된 인터페이스를 변경할 수 있도록 만든 것이다.

디폴트 메스드를 이용하면 기존의 코드를 건드리지 않고 원래의 인터페이스 설계를 자유롭게 확장할 수 있다.

 

Optional<T>

자바 8에서 NullPointer 예외를 피할 수 있도록 도와주는 Optional<T> 클래스를 제공한다. Optional<T>는 값을 갖거나 갖지 않을 수 있는 컨터이너 객체이다.

 

*자바 9에는 모듈 시스템이 추가 되었다. 모듈을 정의 하는 문법을 제공하고 이를 이용해 패키지 모음을 포함하는 모듈을 정의할 수 있다.