배경
- 지금까지 대부분의 자바 프로그램은 코어 중 하나만을 사용
- 자바 8이 등장하기 이전에는 나머지 코어를 활용하기 위해 스레드를 사용하는 것이 좋음
- 자바 5에서는 병렬실행 관련하여 스레드풀(thread pool), 병렬 실행 컬렉션(concurrent collection) 등이 도입됨
- 자바 8에서는
- 스트림 API
- DB 질의 언어에서 고수준 언어로 원하는 동작을 표현하면, 구현에서 최적의 저수준 실행방법을 선택하는 방식과 유사하게 동작
- 메서드에 코드를 전달하는 기법 (Method Reference, Lambda)
- 동작 파라미터화 (behavior parameterization)
- 인터페이스의 디폴트 메서드
- C, C++ 은 프로그래밍 안전성은 부족하지만 작은 메모리 사용량으로 임베디드에 많이 사용
- 스칼라, 그루비 등도 JVM에서 실행되는 자바의 경쟁 언어이다
스트림 처리
- 유닉스 명령행에서는 파이프(|)를 이용해서 명령들을 병렬로 연결한다
- 자바 8에는
java.util.stream
패키지에 스트림 API가 추가됨
Stream<T>
는 T 형식으로 구성된 일련의 항목을 의미
- 스레드라는 복잡한 작업을 사용하지 않으면서도 공짜로 병렬성을 얻을 수 있음
- 스트림 메서드로 전달하는 코드는 다른 코드와 동시에 실행하더라도 안전하게 실행될 수 있어야함
- 공유된 가변 데이터에 접근하지 않아야 함
- synchrozied 키워드는 시스템 성능에 악영향을 끼치므로 다른 방식으로 구성되어 있음
- 스트림 라이브러리 자체에
- 큰 스트림을 병렬로 처리할 수 있도록 작은 스트림으로 분할하도록
- 구성되어 있어, 우리가 직접 신경쓸 필요 X
- 컬렉션에서는 반복 과정을 직접 처리해야했음
- for-each 루프 활용: 외부 반복 (external iteration)
- 스트림 API에서는 라이브러리 내부에서 모든 데이터가 처리
- 내부 반복 (internal iteration)
- ETL(Extract, Transform, Load)의 기능을 모두 가지고 있음
- 컬렉션은 어떻게 데이터를 저장하고 접근할지에 중점을 두지만, 스트림은 데이터에 어떤 계산을 할 것인지에 중점을 둔다
stream().
, parallelStream()
등을 사용
- 이전 자바버전에서의 스레드 API로 멀티스레딩 코드를 구현해서 병렬성을 이용하는 것은 not easy
함수형 프로그래밍
- 우리가 하려는 작업이 최우선시 되고, 그 작업의 수행 방법은 별개의 문제로 취급됨
- java 8 이전에 메서드와 클래스는 그 자체로 값이 될 수 없음
- 메서드 참조 (method reference)
::
: 이 메서드를 값으로 사용하라는 의미
- ex)
File[] tmp = new File().listFiles(File::isHidden);
- 자바 8에서는 메서드 뿐만 아니라, 람다 (or 익명 함수(anonymous functions)를 포함하여 함수도 값으로 취급할 수 있다.
- List에서 데이터를 필터링 할 때, 필터링 조건에 따라 메번 filter 메서드를 조건만 다르고, 중복으로 구현, 복붙해서 구현해야하나?
- 자바8에서는 코드를 인수로 넘겨줄 수 있으므로 filter 메소드를 중복으로 구현할 필요가 X
- filter 자체 중복구현이 아니라, 조건에 대해서만 새롭게 메소드를 만들면 Predicate로 넘겨주면 됨
- Predicate: 인수로 값을 받아 true/false를 반환하는 함수
- 하지만 메서드 전달도 일일이 만들어서가 아니라, 익명 함수(람다)를 사용해서 손쉽게 전달할 수 있다!
디폴트 메서드
Collection.list(list, comparator)
보다 list.sort(comparator)
가 더 beautiful 한데,
- List가 인터페이스라 sort 메소드를 추가하는데 거부감이 든다.
- 인터페이스를 업데이트하려면 해당 인터페이스를 구현하는 모든 클래스도 업데이트해야하기 때문
- 인터페이스 자체에는 abstract method만 선언할 수 있었으니까!
- 기존의 구현을 고치지 않고도 이미 공개된 인터페이스의 변경을 손쉽게 하기 위해 디폴트 메서드의 등장
- 디폴트 메서드는 특정 프로그램을 구현하는데 도움을 주는 기능이 아니라
- 미래에 프로그램이 쉽게 변화할 수 있는 환경을 제공하는 기능!
- Java 8은 구현 클래스에서 구현하지 않아도 되는 메서드를 인터페이스에 추가할 수 있는 기능을 제공
- 인터페이스 규격명세에
default
라는 새로운 키워드를 지원
- Optional
- 값을 갖거나 갖지 않을 수 있는 컨테이너 객체
- 값이 없는 상황을 어떻게 처리할 지 명시적으로 구현하는 메서드를 포함하고 있다
생각해볼 문제
- 하나의 클래스에서 여러 인터페이스의 implement가 가능한데
- 여러 인터페이스에 다중 디폴트 메서드가 존재할 수 있다는 것은
- 결국 다중 상속이 허용되는거 아닌가?! abstract class를 다중으로 상속받는 느낌으로?
- --> 어느정도는 그렇다! ->
다이아몬드 상속 문제