19.04.20 스트림과 병렬 처리

Back-End/Java 2019. 4. 20. 21:13
728x90
반응형

-스트림(Stream)-

 

컬렉션 (배열포함)의 저장 요소를 하나씩 참조해서 람다식(함수적-스타일)로 처리할 수 있도록 해주는
반복자이다.
Stream은 Iterator과 비슷한 역할을 하는 반복자이지만, 람다식으로 요소 처리 코드를 제공하는 점과
내부 반복자를 사용하므로 병렬 처리가 쉽다는점, 그리고 중간 처리와 최종 처리 작업을 수행하는 점에서 차이를
가지고 있다.

 

 


-외부 반복자-

 

개발자가 코드로 직접 컬렉션의 요소를 반복해서 가져오는 코드.
index를 이용하는 for문 그리고 Iterator를 이용하는 while문 등이 있다.

 

 


-내부 반복자-

 

컬렉션 내부에서 요소들을 반복시키고, 개발자는 요소당 처리해야 할 코드만 제공하는 코드 패턴을 말한다.
내부 반복자를 사용해서 얻는 장점은 컬렉션 내부에서 어떻게 요소를 반복시킬 것인가는 컬렉션에게 맞겨두고,
개발자는 요소 처리 코드에만 집중할 수 있다는 것이다.

 

 

 

 


-병렬 처리-

 

한 가지 작업을 서브 작업으로 나누고, 서브 작업들을 분리된 스레드에서 병렬적으로 처리하는 것을 말한다.

 

 

 

-스트림 파이트라인-

 

스트림은 데이터의 필터링, 매핑, 정렬, 그룹핑 등의 중간 처리와 합계, 평균, 카운팅, 최댓값. 최소값
등의 최종 처리를 파이프라인으로 해결한다.
파이프라인은 여러개의 스트림이 연결되어 있는 구조를 말한다.
파이프라인에서 최종 처리를 제외하고는 모두 중간 처리 스트림이다.
중간 스트림이 생성될 때 요소들이 중간 처리(필터링, 정렬 등) 되는 것이 아니라 최종 처리가
시작되기 전까지 중간 처리는 지연된다.
최종 처리가 시작되면 비로소 컬렉션의 요소가 하나씩 중간 스트림에서 처리되고 최종 처리까지 오게 된다.

 

 


 

-예제 및 출력 결과-

 

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 com.hs.chap16;
 
public class Member {
    public static int MALE = 0;
    public static int FEMALE = 1;
 
    private String name;
    private int sex;
    private int age;
 
    public Member(String name, int sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
 
    public int getSex() {
        return sex;
    }
 
    public int getAge() {
        return age;
    }
 
}
 
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.hs.chap16;
 
import java.util.Arrays;
import java.util.List;
 
public class StreamPipelinesExample {
    public static void main(String[] args) {// Arrays.asList 메소드를 사용해서 새로운 객체를 생성해 list에 넣어준다.
        List<Member> list = Arrays.asList(new Member("홍길동", Member.MALE, 30), new Member("김나리", Member.FEMALE, 20),
                new Member("신용권", Member.MALE, 45), new Member("박수미", Member.FEMALE, 27)
 
        );
 
        double ageAvg = list.parallelStream().filter(m -> m.getSex() == Member.MALE).mapToInt(Member::getAge).average()
                .getAsDouble(); // 매개변수 m의 getsex()메소드를 호출해 그 값이 MALE와 같은것만 필터링하고, Member 객체를 age 값으로 매핑해 age를
                                // 요소로 갖는 스트림을 생성하고 그 평균을 계산하고, 그 값을 읽기위해 getAsDouble()메서드를 호출해서 그 값을 읽고,
                                // ageAvg에 저장한다.
 
        System.out.println("남자 평균 나이: " + ageAvg);
    }
 
}
 
cs

 

 

 

 

-필터링-

 

필터링은 중간 처리 기능으로 요소를 걸러내는 역할을 한다.
필터링 메소드인 distinct()와 filter() 메소드는 모든 스트림이 가지고 있는 공통 메소드이다.

distinct() 메소드는 중복을 제거하는데 equals를 사용해 true면 동일한 객체로 판단하고 중복을 제거한다.

filter() 메소드는 매개값으로 주어진 Predicate가 true를 리턴하는 요소만 필터링한다.

 

 

 

-매핑-

 

매핑(mapping)는 중간 처리 기능으로 스트림의 요소를 다른 요소로 대체하는 작업을 말한다.

 

flatMapXXX() 메소드는 요소를 대체하는 복수 개의 요소들로 구성된 새로운 스트림을 리턴한다.

 

A -> A1,A2

B -> B1,B2

 

mapXXX() 메소드는 요소를 대체하는 요소로 구성된 새로운 스트림을 리턴한다.

 

A -> C
B -> D

 


-정렬-

 

스트림은 요소가 최종 처리되기 전에 중간 단계에서 요소를 정렬해서 최종 처리 순서를 변경할 수 있다.

 

 

 

-루핑-

 

루핑은 요소 전체를 반복하는 것을 말한다.
루핑하는 메소드에는 peek(), forEach()가 있다.

peek()는 중간 처리 단계에서 전체 요소를 루핑하면서 추가적인 작업을 하기 위해 사용한다.
또한 최종 처리 메소드가 호출되어야 동작한다.

 

intStream
.filter( a -> a%2 == 0)
.peek( a -> System.out.println(a) )
.sum()

 

하지만 forEach()는 최종 처리 메소드이기 때문에 파이프라인 마지막에 루핑하면서 요소를 하나씩 처리한다.

 

 

 

-집계-

 

최종 처리 기능으로 요소들을 처리해서 카운팅, 합계, 평균값, 최대값, 최소값 등과 같이 하나의 값으로 산출하는 것

 

 

 

-수집-

 

스트림은 요소들을 필터링 또는 매핑한 후 요소들을 수집하는 최종 처리 메소드인 collect()를 제공하고 있다.

이 메소드를 이용하면 필요한 요소만 컬렉션으로 담을 수 있고, 요소들을 그룹핑한 후 집계 할 수 있다.

 

List<Student> maleList = totalList.stream( )                  

.filter(s -> s.getSex() == Student.Sex.MALE) 

.collect(Collectors.toList( ) );

 

-예제 및 출력결과-

 

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
39
40
41
42
43
44
45
46
47
48
49
50
package com.hs.chap16;
 
public class Student {
 
    public enum Sex {
        MALE, FEMALE
    }
 
    public enum City {
        Seoul, Pusan
    }
 
    private String name;
    private int score;
    private Sex sex;
    private City city;
 
    public Student(String name, int score, Sex sex) {
        this.name = name;
        this.score = score;
        this.sex = sex;
 
    }
 
    public Student(String name, int score, Sex sex, City city) {
        this.name = name;
        this.score = score;
        this.sex = sex;
        this.city = city;
 
    }
 
    public String getName() {
        return name;
    }
 
    public int getScore() {
        return score;
    }
 
    public Sex getSex() {
        return sex;
    }
 
    public City getCity() {
        return city;
    }
 
}
 
cs


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
39
40
41
42
package com.hs.chap16;
 
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
 
 
public class ToListExample {
    
 
    public static void main(String[] args) {
        List<Student> totalList = Arrays.asList(
        new Student("홍길동",10,Student.Sex.MALE),
        new Student("김수애",6,Student.Sex.FEMALE),
        new Student("신용권",10,Student.Sex.MALE),
        new Student("박수미",6,Student.Sex.FEMALE)
                
        );
        
        //남학생들만 묶어 List 작성
        List<Student> maleList = totalList.stream()
                .filter(s->s.getSex() == Student.Sex.MALE)
                .collect(Collectors.toList());
        maleList.parallelStream()
        .forEach(s->System.out.println(s.getName()));
        
        System.out.println();
        
        //여학생들만 묶어 HashSet 생성
        Set<Student> femaleSet = totalList.stream()
                .filter(s->s.getSex() == Student.Sex.FEMALE)
                .collect(Collectors.toCollection(HashSet :: new));
        femaleSet.stream()
        .forEach(s-> System.out.println(s.getName()));
 
    }
 
}
 
cs

 

 

 

 

-동시성-

 

멀티 작업을 위해 멀티 스레드가 번갈아가며 실행하는 성질

 

 

 

-병렬성-

 

멀티 작업을 위해 멀티 코어를 이용해서 동시에 실행하는 성질

 

 

 

-데이터 병렬성-

 

데이터 병렬성은 전체 데이터를 쪼개어 서브 데이터들로 만들고 이 서브 데이터들을 병렬 처리해서 작업을 빨리
끝내는 것을 말한다.
예를 들어 쿼드 코어 CPU일 경우 4개의 서브 요소들로 나누고, 4개의 스레드가 각각의 서브 요소들을 병렬 처리한다.

 

 

 

-작업 병렬성-

 

작업 병렬성은 서로 다른 작업을 병렬 처리하는 것을 말한다.

작업 병렬성의 대표적인 예는 웹 서버이다.

웹 서버는 각각의 브라우저에서 요청한 내용을 개별 스레드에서 병렬로 처리한다.

 

 

 

-병렬 스트림-

 

parallelStream( ) 메소드는 컬렉션으로부터 병렬 스트림을 바로 리턴한다.

 

parallel( ) 메소드는 순차 처리 스트림을 병렬 처리 스트림으로 변환해서 리턴한다.

728x90
반응형

'Back-End > Java' 카테고리의 다른 글

19.04.22 IO기반 입출력 및 네트워킹-2  (0) 2019.04.22
19.04.21 IO 기반 입출력 및 네트워킹-1  (0) 2019.04.21
19.04.19 컬렉션 프레임워크  (0) 2019.04.19
19.04.18 람다식  (0) 2019.04.18
19.04.17 제네릭,와일드카드  (0) 2019.04.17
: