ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    package 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


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    package 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



      

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    package 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


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    package stream;
     
    import java.util.Arrays;
    import java.util.stream.IntStream;
     
    public class AsDoubleStreamAndBoxedExam {
     
        public static void main(String[] args) {
            int[] intArr = {102030405060};
            
            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


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    package 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;
        }
     
        @Override
        public int compareTo(Student o) {
            return Integer.compare(score, o.score);
        }
    }
     
    cs






     객체 요소가 Comparable을 구현한 상태에서 기본 비교(Comparable) 방법으로 정렬하고 싶다면 다음 세 가지 방법 중 하나를 선택해서 sorted() 메소드를 호출하면 됩니다.




    1
    2
    3
    4
    5
    6
    sorted();
     
    sorted( (a, b) -> a.compareTo(b));
     
    sorted( Comparator.naturalOrder());
     
    cs





     만약 객체 요소가 Comparable을 구현하고 있지만, 기본 비교 방법과 정반대 방법으로 정렬하고 싶다면 다음과 같이 sorted()를 호출하면 됩니다.



    1
    2
    3
    4
    5
     
    sorted( (a, b) -> b.compareTo(a));
     
    sorted( Comparator.reverseOrder());
     
    cs




     객체 요소가 Comparable를 구현하지 않았다면 Cmparator를 파라미터로 갖는 sorted() 메소드를 사용하면 됩니다. 


     Comparator는 함수적 인터페이스이므로 다음과 같이 람다식으로 파라미터를 작성할 수 있습니다.



    1
    2
    sorted( (a, b) -> {...} );
     
    cs




     중괄호 {} 안에는 a와 b를 비교해서 a가 작으면 음수, 같으면 0, a가 크면 양수를 리턴하는 코드를 작성하면 됩니다.


     다음 예제를 보면 숫자 요소일 경우에는 오름차순으로 정렬한 후 출력했습니다. 


    nbsp;Student 요소일 경우에는 Student의 기본 비교(Comparable) 방법을 이용해서 점ㅈ수를 기준으로 오름차순으로 정렬한 후 출력했습니다.


     그리고 Comparator를 제공해서 점수를 기준으로 내림차순으로 정렬한 후 출력했습니다.



     * SortingExam.java


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    package 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[] {961123});
            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



     








     * 이 포스트은 서적 '이것이 자바다' 를 참고하여 작성한 포스트입니다.

    댓글

Designed by Tistory.