-
[Java] 스트림과 병렬처리 - 필터링, 매핑, 정렬CSE/Java 2015. 9. 9. 15:14스트림과 병렬 처리는 여러 절로 구성되어 있습니다.
4. 필터링(distinct(), filter())
필터링은 중간 처리 기능으로 요소를 걸러내는 역할을 합니다.
필터링 메소드인 distinct()와 filter() 메소드는 모든 스트림이 가지고 있는 공통 메소드 입니다.
리턴 타입
메소드(파라미터)
설명
Stream
IntStream
LongStream
DoubleStream
distinct()
중복 제거
filter(Predicate)
조건 필터링
filter(IntPredicate)
filter(LongPredicate)
filter(DoublePredicate)
distinct() 메소드는 중복을 제거하는 데, Stream의 경우 Object.equals(Object) 가 true 이면 동일한 객체로 판단하고 중복을 제거합니다.
IntStream, LongStream, DoubleStream은 동일값일 경우 중복을 제거합니다.
filter() 메소드는 파라미터로 주어진 Predicate가 true를 리턴하는 요소만 필터링합니다.
다음 예제는 이름 List에서 중복된 이름을 제거하고 출력합니다.
* FilteringExam.java
12345678910111213141516171819202122232425262728293031323334353637package stream;import java.util.Arrays;import java.util.List;public class FilteringExam {public static void main(String[] args) {List<String> names = Arrays.asList("Jack Daniel","Andy Smith","Demian Rice","Mike Tomson","Jack Daniel","Jolie Martonne");names.stream().distinct().forEach(n -> System.out.println(n));System.out.println();names.stream().filter(n -> n.startsWith("J")).forEach(n -> System.out.println(n));System.out.println();names.stream().distinct().filter(n -> n.startsWith("J")).forEach(n -> System.out.println(n));}}cs 5. 매핑(flatMapXXX(), mapXXX(), asXXXStream(), boxed())
매핑(mapping)은 중간 처리 기능으로 스트림의 요소를 다른 요소로 대체하는 작업을 말합니다.
스트림에서 제공하는 매핑 메소드는 flatXXX()와 mapXXX(), 그리고 asDoubleStream, asLongStream, boxed 가 있습니다.
5.1 flatMapXXX() 메소드
flatMapXXX() 메소드는 요소를 대체하는 복수 개의 요소들로 구성된 새로운 스트림을 리턴합니다.
다음 그림을 보면서 확인해봅시다. 스트림에서 A라는 요소는 A1, A2 요소로 대체되고, B라는 요소는 B1, B2로 대체된다고 가정했을 경우, A1, A2, B1, B2 요소를 가지는 새로운 스트림이 생성됩니다.
flatMapXXX() 메소드의 종류는 다음과 같습니다.
리턴 타입
메소드(파라미터)
요소 -> 대체 요소
Stream<R>
flatMap(Function<T, Stream<R>>)
T -> Stream<R>
DoubleStream
flatMap(DoubleFunction<DoubleStream>)
double -> DoubleStream
IntStream
flatMap(IntFunction<IntStream>)
int -> IntStream
LongStream
flatMap(LongFunction<LongStream>)
long -> LongStream
DoubleStream
flatMapToDouble(Function<T, DoubleStream>)
T -> DoubleStream
IntStream
flatMapToInt(Function<T, IntStream>)
T -> IntStream
LongStream
flatMapToLong(Function<T, LongStream>)
T -> LongStream
다음 예제는 입력된 데이터들이 List<String>에 저장되어 있다고 가정하고, 요소별로 단어를 뽑아 단어 스트림을 재생성합니다.
만약 입력된 데이터들이 숫자라면 숫자를 뽑아 숫자 스트림을 재생성합니다.
* FlatMapExam.java
123456789101112131415161718192021222324252627282930313233package stream;import java.util.Arrays;import java.util.List;public class FlatMapExam {public static void main(String[] args) {List<String> inputList1 = Arrays.asList("java8 lamda", "Stream mapping");inputList1.stream().flatMap(data -> Arrays.stream(data.split(" "))).forEach(word -> System.out.println(word));System.out.println();List<String> inputList2 = Arrays.asList("10, 20, 30", "40, 50, 60");inputList2.stream().flatMapToInt(data -> {String[] strArr = data.split(",");int[] intArr = new int[strArr.length];for (int i = 0; i < strArr.length; i++) {intArr[i] = Integer.parseInt(strArr[i].trim());}return Arrays.stream(intArr);}).forEach(number -> System.out.println(number));}}cs 5.2 mapXXX() 메소드
mapXXX() 메소드는 요소를 대체하는 요소로 구성된 새로운 스트림을 리턴합니다.
다음 그림을 보면서 확인해봅시다. 스트림에서 A요소는 C요소로 대체되고, B요소는 D요소로 대체된다고 했을 경우 C, D 요소를 가지는 새로운 스트림이 생성됩니다.
다음 예제는 학생 List에서 학생의 점수를 요소로 하는 새로운 스트림을 생성하고, 점수를 순차적으로 콘솔에 출력합니다.
* MapExam.java
1234567891011121314151617181920212223package stream;import java.util.Arrays;import java.util.List;public class MapExam {public static void main(String[] args) {List<Student> student = Arrays.asList(new Student("Jack", 10),new Student("Jolie", 20),new Student("Smith", 30));student.stream().mapToInt(Student :: getScore).forEach(score -> System.out.println(score));}}cs 5.3 asDoubleStream(), asLongStream(), boxed() 메소드
asDoubleStream() 메소드는 IntStream의 int 요소 또는 LongStream의 long 요소를 double 요소로 타입 변환해서 DoubleStream 을 생성합니다.
마찬가지로 asLongStream() 메소드는 IntStream의 int 요소를 long 요소로 타입 변환해서 LongStream을 생성합니다.
boxed() 메소드는 int, long, double 요소를 Integer, Long, Double 요소로 박싱해서 Stream을 생성합니다.
리턴 타입
메소드(파라미터)
설명
DoubleStream
asDoubleStream()
int -> double
long -> double
LongStream
asLongStream()
int -> long
Stream<Integer>
Stream<Long>
Stream<Double>
boxed()
int -> Integer
long -> Long
double -> Double
다음 예제는 int[] 배열로부터 IntStream 을 얻고 난 다음 int 요소를 double 요소로 타입 변호나해서 DoubleStream을 생성합니다.
또한 int 요소를 Integer 객체로 박싱해서 Stream<Integer> 를 생성합니다.
* AsDoubleStreamAndBoxedExam.java
1234567891011121314151617181920212223242526package stream;import java.util.Arrays;import java.util.stream.IntStream;public class AsDoubleStreamAndBoxedExam {public static void main(String[] args) {int[] intArr = {10, 20, 30, 40, 50, 60};IntStream intStream = Arrays.stream(intArr);intStream.asDoubleStream().forEach(d -> System.out.println(d));System.out.println();intStream = Arrays.stream(intArr);intStream.boxed().forEach(obj -> System.out.println(obj.intValue()));}}cs 6. 정렬(sorted())
스트림은 요소가 최종 처리되기 전에 중간 단계에서 요소를 정렬해서 최종 처리 순서를 변경할 수 있습니다.
요소를 정렬하는 메소드는 다음과 같습니다.
리턴 타입
메소드(파라미터)
설명
Stream<T>
sorted()
객체를 Comparable 구현 방법에 따라 정렬
Stream<T>
sorted(Comparator<T>)
객체를 주어진 Comparator에 따라 정렬
DoubleStream
sorted()
double 요소를 오름차순으로 정렬
IntStream
sorted()
int 요소를 오름차순으로 정렬
LongStream
sorted()
long 요소를 오름차순으로 정렬
객체 요소일 경우에는 클래스가 Comparable을 구현하지 않으면 sorted() 메소드를 호출했을 때 ClassCastException이 발생하기 때문에 Comparable을 구현한 요소에서만 sorted() 메소드를 호출해야 합니다.
다음은 점수를 기준으로 Student 요소를 오름차순으로 정렬하기 위해 Comparable을 구현했습니다.
* Student.java
12345678910111213141516171819202122232425262728293031323334package stream;public class Student implements Comparable<Student> {private String name;private int score;public Student(String name, int score) {this.name = name;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}@Overridepublic int compareTo(Student o) {return Integer.compare(score, o.score);}}cs 객체 요소가 Comparable을 구현한 상태에서 기본 비교(Comparable) 방법으로 정렬하고 싶다면 다음 세 가지 방법 중 하나를 선택해서 sorted() 메소드를 호출하면 됩니다.
123456sorted();sorted( (a, b) -> a.compareTo(b));sorted( Comparator.naturalOrder());cs 만약 객체 요소가 Comparable을 구현하고 있지만, 기본 비교 방법과 정반대 방법으로 정렬하고 싶다면 다음과 같이 sorted()를 호출하면 됩니다.
12345sorted( (a, b) -> b.compareTo(a));sorted( Comparator.reverseOrder());cs 객체 요소가 Comparable를 구현하지 않았다면 Cmparator를 파라미터로 갖는 sorted() 메소드를 사용하면 됩니다.
Comparator는 함수적 인터페이스이므로 다음과 같이 람다식으로 파라미터를 작성할 수 있습니다.
12sorted( (a, b) -> {...} );cs 중괄호 {} 안에는 a와 b를 비교해서 a가 작으면 음수, 같으면 0, a가 크면 양수를 리턴하는 코드를 작성하면 됩니다.
다음 예제를 보면 숫자 요소일 경우에는 오름차순으로 정렬한 후 출력했습니다.
nbsp;Student 요소일 경우에는 Student의 기본 비교(Comparable) 방법을 이용해서 점ㅈ수를 기준으로 오름차순으로 정렬한 후 출력했습니다.
그리고 Comparator를 제공해서 점수를 기준으로 내림차순으로 정렬한 후 출력했습니다.
* SortingExam.java
1234567891011121314151617181920212223242526272829303132333435363738package stream;import java.util.Arrays;import java.util.Comparator;import java.util.List;import java.util.stream.IntStream;public class SortingExam {public static void main(String[] args) {IntStream intStream = Arrays.stream(new int[] {9, 6, 11, 2, 3});intStream.sorted().forEach(n -> System.out.print(n + ", "));System.out.println();List<Student> studentList = Arrays.asList(new Student("Jack", 80),new Student("John", 100),new Student("Andy", 99),new Student("Jolie", 70));studentList.stream().sorted().forEach(s -> System.out.print(s.getScore() + ", "));System.out.println();studentList.stream().sorted( Comparator.reverseOrder()).forEach(s -> System.out.print(s.getScore() + ", "));}}cs * 이 포스트은 서적 '이것이 자바다' 를 참고하여 작성한 포스트입니다.
'CSE > Java' 카테고리의 다른 글
[Java] 컬렉션 프레임워크 - Intro (0) 2015.09.11 [Java] 스트림과 병렬 처리 - 수집, 병렬 처리 (0) 2015.09.10 [Java] 스트림과 병렬 처리 - 루핑, 매칭, 집계 (0) 2015.09.10 [Java] 스트림과 병렬 처리 - 파이프라인 (0) 2015.09.09 [Java] 스트림과 병렬 처리 - 스트림 (0) 2015.09.08 [Java] NIO 기반 입출력 및 네트워킹 - UDP 채널 (0) 2015.09.06