컬렉션 팩토리(Collection Factory) java 9에서는 작은 컬렉션 객체를 쉽게 만들 수 있는 방법을 제공한다. 자바에서 적은 요소를 포함하는 리스트를 만들때 아래처럼 사용할 것이다. List cars = new ArrayList(); cars.add("아반테"); cars.add("소나타"); cars.add("그랜저"); 이렇게 코드를 작성하게 되면 새 문자열을 저장하는데도 많은 코드가 필요하다. Arrays.asList() 팩토리 메서드를 이용하면 코드를 간단하게 줄일 수 있다. List cars = Arrays.asList("아반테", "소나타", "그랜저"); 내부적으로 고정된 크기의 변환할 수 있는 배열로 구현되었기 때문에 요소를 갱신할 순 있지만 추가하게 되면 Unsupporte..
Java
반응형
Spliterator 인터페이스란? Spliterator는 분할할 수 있는 반복자라는 의미이다. Iterator 처럼 Spliterator는 소스의 요소 탐색 기능을 제공한다는 점은 같지만 Spliterator는 병렬 작업에 특화되어 있다. 커스텀 Spliterator를 꼭 구현해야 하는 건 아니지만 Spliterator가 어떻게 동작하는지 이해한다면 병렬 스트림 동작과 관련한 통찰력을 얻을 수 있다. java8은 컬렉션 프레임워크에 포함된 모든 자료구조에 사용할 수 있는 디폴트 Spliterator 구현을 제공한다. public interface Spliterator { boolean tryAdvance(Consumer
포크/조인 프레임워크(Fork/Join Framework)란? 포크/조인 프레임워크는 병렬화할 수 있는 작업을 재귀적으로 작은 작업으로 분할한 다음에 서브태스크 각각의 결과를 합쳐서 전체 결과를 만들도록 설계되었다. 따라서 하나의 작업을 작은 단위로 나눠서 여러 쓰레드가 동시에 처리하는 것을 쉽게 만들어 준다. 이 알고리즘은 분할 후 정복(divide-and-conquer) 알고리즘의 병렬화 버전이다. 포크/조인 프레임워크에서는 서브태스크를 스레드 풀(ForkJoinPool)의 작업자 스레드에 분산 할당하는 ExecutorService 인터페이스를 구현한다. RecursiveTask 활용 스레드 풀을 이용하려면 RecursiveTask의 서브클래스를 만들어야 한다. 여기서 R은 병렬화된 태스크가 생성하는..
java7이 등장하기 전에는 데이터 컬렉션을 병렬로 처리하기가 어려웠다. 우선 데이터를 서브 파트로 분할해야 하고, 분할된 서브 파트를 각각의 스레드로 할당한다. 스레드로 할당한 다음에는 의도치 않은 레이스 컨디션이 발생하지 않도록 적절한 동기화를 추가해야 하며, 마지막으로 부분 결과를 합쳐야 한다. java7은 더 쉽게 병렬화를 수행하면서 에러를 최소화할 수 이도록 포크/조인 프레임워크(fork/join framework) 기능을 제공한다. 이번에는 스트림으로 데이터 컬렉션 관련 동작을 얼마나 쉽게 병렬로 실행하는지 살펴보자. 스트림을 이용하면 순차 스트림을 병렬 스트림으로 자연스럽게 바꿀 수 있다. 병렬 스트림이 내부적으로 어떻게 처리되는지 알아야만 스트림을 잘못 사용하는 상황을 피할 수 있다. 병렬..
Collector 인터페이스란? Collector 인터페이스는 리듀싱 연산(즉, 컬렉터)을 어떻게 구현하지 제공하는 메서드 집합으로 구성된다. 물론 우리가 Collector 인터페이스를 구현하는 리듀싱 연산을 만들 수도 있다. Collector 인터페이스를 집접 구현해서 더 효율적으로 문제를 해결하는 컬렉터를 만드는 방법을 살펴보자. Collector 인터페이스를 보면 시그니처와 다섯 개의 메서드 정의를 확인할 수 있다. public interface Collector { Supplier supplier(); BiConsumer accumulator(); BinaryOperator combiner(); Function finisher(); Set characteristics(); } 먼저 시그니처를 보면..
컬렉터(Collector)란 무엇인가? 컬렉터(Collector) 인터페이스 구현은 스트림 요소를 어떤 식으로 도출할지 지정한다. 스트림에 collect를 호출하면 컬렉터가 스트림의 요소에 리듀싱 연산을 수행하여 필요한 데이터 구조로 간단하게 도출할 수 있다. 만약 아래처럼 통화 별 주문 목록 데이터가 있다고 가정해보자. @ToString @Getter @AllArgsConstructor public class Order { private String orderNumber; private String orderProductName; private Integer payPrice; private Currency currency; } List orders = new ArrayList() {{ add(new O..
앞서 스트림이 무엇인지, 스트림을 어떻게 활용하는지 알아보았다. 이번엔 여러가지 스트림을 만드는 방법에 대해 알아보자. 값으로 스트림 만들기 임의의 수를 인수로 받는 정적 메서드 Stream.of를 이용해서 스트림을 만들 수 있다. Stream stream = Stream.of("a", "b", "c", "d", "e"); stream.map(String::toUpperCase).forEach(System.out::println); 다음 처럼 empty 메서드를 이용해서 스트림을 비울 수 있다. Stream emptyStream = Stream.empty(); null이 될 수 있는 객체로 스트림 만들기 java9에서는 null이 될 수 있는 개체를 스트림으로 만들 수 있는 새로운 메소드가 추가되었다. ..
이 전 글에는 스트림(Stream)이란 무엇인가?를 알아보았다. 그럼 스트림 API가 지원하는 다양한 연산을 알아보자. 필터링 Predicate로 필터링 (filter) 스트림 인터페이스는 filter 메서드를 지원한다. filter 메서드는 Predicate를 인수로 받아서 일치하는 모든 요소를 포함하는 스트림으로 반환한다. List vegetarianMenu = menu.stream() .filter(Dish::isVegetarian) .collect(toList()); 고유 요소 필터링 (distinct) 스트림은 고유 요소(Primary)로 이루어진 스트림을 반환하는 distinct 메서드도 지원한다.(고유 여부는 객체의 hashCode, equals로 결정) List numbers = Array..
거의 모든 자바 애플리케이션은 컬렉션으로 데이터를 그룹화하고 처리하는 과정을 포함한다. 예를 들어 가격이 3,000만원 이하의 자동차 정보를 조회할 때는 아래처럼 SQL문을 작성한다. SELECT * FROM Car WHERE price c.getPrice() c2.getPrice().compareTo(c1.getPrice())) // 비싼 차량부터 정렬 .map(Car::getName) // 자동차 이름 필터링 .collect(Collectors.toList()); Java 8 스트림 API의 특징을 다음처럼 요약할 수 있다. 선언형 : 더 간결하고 가독성이 좋아진다. 코드 조립 : 유연성이 좋아진다. 병렬화 : 성능이 좋아진다. 스트림(Stream)의 정의 스트림이란 '데이터 처리 연산을 지원하도록 ..
Java 8 API의 몇몇 함수형 인터페이스는 다양한 유틸리티 메서드를 포함한다. 예를 들어 Comparator, Function, Predicate 같은 함수형 인터페이스는 람다 표현식을 조합할 수 있도록 유틸리티 메서드를 제공한다. 이것은 무슨 의미일까? 간단히 말해, 간단한 여러 개의 람다 표현식을 조합해서 두 Predicate의 or 연산을 수행하는 커다란 Predicate를 만들 수 있다. 또한 한 함수의 결과가 다른 함수의 입력이 되도록 두 함수를 조합할 수 있다. 그런데 Java 8 API에서 지원하는 Comparator, Function, Predicate 인터페이스는 함수형 인터페이스 아닌가? "함수형 인터페이스는 추상화 메서드가 1개뿐이라며?!" 라고 생각할 수 있을것이다. 그렇다. 추..