본문 바로가기
교육/Java

Java 개발자 수업 92일차 - 파이프 라인(Pipe Line)

by yhyuk 2021. 8. 7.
728x90
반응형

파이프 라인(Pipe Line)


파이프 라인(Pipe Line)

- 스트림(Stream)에서 제공하는 기능이다.

- 메소드 체인이라고도 불린다.

- 시작 스트림 -> 중간 파이프 -> 최종 파이프

- 원리

배열 -> 스트림 -> 조작(A) -> 스트림 -> 조작(A) -> 스트림 -> 조작(B) -> ...반복

1. 시작, 중간조작(A): 중간처리 -> 필터링, 매핑, 정렬, 그룹핑 등...
2. 마지막 조작(B): 최종처리 -> 합계, 평균, 카운트, 최댓값, 최솟값, forEach 등...

 

[ 필터링 ]

- filter()

- 중간 처리 파이프

- 반환값으로 필터링이 된 Stream을 반환하기 때문에 계속 이어서 다른 파이프를 연결할 수 있다.

 

[ 예제1 - 필터링으로 짝수 구하기 ]

- 스트림 시작 -> filter 처리(중간 파이프) -> forEach 처리(최종 파이프)

- 스트림 시작 -> 홀수 걸러내기(짝수 찾기) -> 남은 숫자(짝수) 출력하기

// 수업상 편의를 위해 Data.getIntList(15)에 임의의 숫자가 15개 들어있습니다. 
// [36, 12, 36, 86, 24, 1, 32, 65, 85, 86, 78, 16, 57, 7, 65]

List<Integer> list = Data.getIntList(15); 

list.stream()                                      // 스트림 시작
    .filter(n -> n % 2 == 0)                       // 중간 파이프(filter)
    .forEach(n -> System.out.printf("%4d" , n));   // 최종 파이프(forEach)
    


--> Output
36  12  36  86  24  32  86  78  16

 

[ 예제2 - 필터링으로 성별 구하기 ]

// 수업상 편의를 위해 Data.getUserList()에 임의의 정보가 들어가 있습니다.
// [name=하하하, age=25, weight=75, height=177, gender=2], [name=박명수, age=23, weight=82, height=183, gender=1]...


// gender가 1인 사람(남자)
Data.getUserList().stream()
                  .filter(user -> user.getGender() == 1)
                  .forEach(user -> System.out.println(user.getName()));

// gender가 2인 사람(여자)
Data.getUserList().stream()
                  .filter(user -> user.getGender() == 2)
                  .forEach(user -> System.out.println(user.getName()));
                  


--> 남자 Output
홍길동
아무개
유재석
박명수
강호동
이수근
정형돈


--> 여자 Output
하하하
테스트
호호호

 

[ 중복 제거 ]

- distinct()

- 중간 처리 파이프

 

[ 예제 - 중복 제거 + 필터링 ]

- 배열에 들어있는 내용 중 중복된 문자를 제거하고, 3글자 이상만 불러오기

List<String> names = Arrays.asList("홍길동", "아무개", "하하하", "김훈", "김훈", "홍길동", "호호호", "아무개", "김길동", "테스트");

names.stream()
     .distinct()                          // 중간 파이프(중복 제거)
     .filter(name -> name.length() >= 3)  // 중간 파이프(필터링)
     .forEach(name -> System.out.println(name));


--> Output
홍길동
아무개
하하하
호호호
김길동
테스트

 

[ 매핑 ]

- mapXXX()

- 중간 처리 파이프

- 스트링 요소 -> 다른 형태의 요소(값)으로 변환해서 반환하는 작업

- 매핑은 데이터 가공(변환)할때 쓰인다.

- 매핑은 리턴값에 따라 자료형이 달라진다. 

   1) word -> word.lenth() : Integer

   2) word -> word          : String

   3) word -> true           : Boolean

 

[ 예제 - 나이를 구해서 세대(데이터 가공) 구하기 ]

// 수업 편의를 위해 Data.getIntList(10)에는 임의의 숫자 10개가 들어가 있습니다.
// [36, 12, 36, 86, 24, 1, 32, 65, 85, 86]

Data.getIntList(10).stream
                   .map(n -> (n / 10) * 10) // 원본데이터 -> 다른 성격의 데이터 가공
                   .forEach(n -> System.out.println("세대: " + n + "대"));
                   

--> Output
세대: 30대
세대: 10대
세대: 30대
세대: 80대
세대: 20대
세대: 0대
세대: 30대
세대: 60대
세대: 80대
세대: 80대

 

[ 정렬 ]

- 배열, 컬렉션

- 스트림 정렬

- sorted()

- 중간 처리 파이프

- 요소를 정렬 후 정렬된 스트림을 반환한다.

 

[ 예제1 - 배열에 있는 숫자 정렬 ]

- sort vs sorted

// 수업상 편의를 위해 Data.getIntList(15)에 임의의 숫자 15개가 들어있습니다.
// [ 36  12  36  86  24   1  32  65  85  86  78  16  57   7  65 ]


// 방법1 - 기존 sort
List<Integer> list1 = Data.getIntList(15);

list1.sort((a, b) -> a - b); // 오름차순 정렬
ist1.stream().forEach(n -> System.out.printf("%4d", n));


// 방법2 - sorted
List<Integer> list2 = Data.getIntList(15);

list2.stream()
     .sorted()
     .forEach(n -> System.out.printf("%4d", n));



--> sort Output
1   7  12  16  24  32  36  36  57  65  65  78  85  86  86

--> sorted Output
1   7  12  16  24  32  36  36  57  65  65  78  85  86  86

 

[ 예제2 - 배열에 있는 숫자 역정렬 ]

List<Integer> list1 = Data.getIntList(15);

list4.stream()
     .sorted((a, b) -> b - a)
     .forEach(n -> System.out.printf("%4d", n));
     
     
--> Output
86  86  85  78  65  65  57  36  36  32  24  16  12   7   1

 

[ 집계 ]

- 통계값 함수

- 최종 처리 파이프

- count()

- 데이터 집합의 요소를 가공해서 축소하는 작업(Reduction)

 

[ 예제 - 필터 + 집계 함수 이용 ]

- 임의의 숫자 리스트에서 짝수, 홀수 개수 구하기

- 임의의 정보 리스트에서 남자, 여자 개수 구하기

// 임의의 숫자 리스트에서 짝수, 홀수 개수 구하기
System.out.println(Data.getIntList().stream().count());                          // 총 개수
System.out.println(Data.getIntList().stream().filter(n -> n % 2 == 0).count());  // 짝수 개수
System.out.println(Data.getIntList().stream().filter(n -> n % 2 == 1).count());  // 홀수 개수
System.out.println();

// 임의의 정보 리스트에서 남자, 여자 개수 구하기
System.out.println(Data.getUserList().stream().count());                                       // 총 정보 수
System.out.println(Data.getUserList().stream().filter(user -> user.getGender() == 1).count()); // 총 남자 수
System.out.println(Data.getUserList().stream().filter(user -> user.getGender() == 2).count()); // 총 여자 수


--> 짝수, 홀수 Output
100
56
44

--> 남자, 여자 Output
10
7
3

 

 

[ 중간 파이프 이용 시 주의 사항 ]

- 오늘 배운 중간 파이프 filter, distinct, map, sort 등 여러가지가 있는데, 중간 파이프는 계속 이어서 붙여 나갈 수 있는 특징이 있다. 하지만 위치(순서)에 따라 값이 달라질 수도 있다.

1. distinct -> filter
2. filter -> distinct 

위 두 방식의 결과는 달라질 수 있다!

 

[ 요약 정리 ]

중간파이프   filter   중간에 걸러내는 작업이며 즉, 조건을 줄 수 있다.( 여러개 붙여서 가능
  distinct   중복값 제거
  map   데이터 가공할 때 쓰이며, 기존 스트링 요소를 다른 형태의 값으로 변환해서 반환해준다.
  sorted   정렬
최종파이프

  forEach   배열에 있는 리스트를 하나씩 읽어 온다. (향상된 for문과 비슷)
  count   집계

MEMO>

# 스트림 사용시 여러 파이프를 연결하다 보면 코드가 길어질 수 있는데, 그때마다 .stream 형식으로 끝나는 지점에 들여쓰기를 하기도한다. (회사마다 다름)

# 스트림 filter에서 조건을 줄 수 있는데, 하나의 filter에서 여러개의 조건을 주는것도 가능하지만, 가독성도 떨어지고 에러가 날수 있으므로 권장하는 방법은 filter를 여러개 쓰는것이다!! ---> 하나의 조건당 하나의 필터!

# 스트림 요소가 동작하는 흐름을 잘 파악해보자. 스트림 Start -> 중간 파이프 작업 -> 최종 파이프 작업..

# 중간 파이프는 계속 이어서 쓸 수 있지만, 순서에 따라 결과가 달라질 수도 있다는걸 명심하자.
728x90
반응형

댓글