스트림

이동주·2025년 3월 17일

JAVA

목록 보기
27/30

스트림

  • Java 8부터 컬렉션 및 배열의 요소를 반복 처리하기 위해 스트림 사용
  • 데이터 베이스 없이도 데이터 관리를 아주 빠르게 처리 가능
  • 요소들이 하나씩 흘러가면서 처리된다는 의미
  • 컬렉션에 대한 부분에서 많이 사용!
  • List 컬렉션의 stream() 메소드로 Stream 객체를 얻고, forEach() 메소드로 요소를 어떻게 처리할지를 람다식으로 제공함!
  • 배열의 요소를 반복 처리하기 때문에 for문의 기능을 하기도 한다!

스트림과 Iterator의 차이점

  • 내부 반복자이므로 처리 속도가 빠르고 병렬 처리에 효율적
  • 람다식으로 다양한 요소 처리를 빙의
  • 중간 처리와 최종 처리를 수행하도록 파이프 라인을 형성
package ch17.sec01;

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;

public class StreamExample {
	public static void main(String[] args) {
		// Set 컬렉션 생성 (파라미터를 문자열 형태로 사용!)
		Set<String> set = new HashSet<>();
		
		// Set 컬렉션에 문자열 추가
		set.add("홍길동");
		set.add("신용권");
		set.add("감자바");
		
		// Stream을 얻는 과정!
		// Stream : set, list 등의 컬렉션을 스트림으로 변환하여 반복문 없이
		// 데이터를 처리할 수 있게 해주는 역할을 함!
		Stream<String> stream = set.stream();
		 
//		for(var name : set) {
//			System.out.println(name);
//		}
//		
		// 위의 for 구문과 비슷하다고 보면 됨!
		// name : 향상된 for loop에서 인자라고 보면 됨!
		// set 컬렉션으로 받은 스트림을 반복문 처리해준다고 보면됨!
		// forEach : 향상된 for loop를 간단하게 표현했다고 보면 됨!
		stream.forEach(name -> System.out.println(name));
	}
}

내부 반복자

  • 요소 처리 방법을 컬렉션 내부로 주입시켜서 요소를 반복 처리
  • 개발자 코드에서 제공한 데이터 처리코드 (람다식)를 가지고 컬렉션 내부에서 요소를 반복 처리!
    -> 내부에서 반복도 하면서 처리까지 수행하는 것!
  • 멀티 코어 CPU를 최대한 활용하기 위해 요소들을 분배시켜 병렬 작업이 가능함
  • 내부 반복자는 멀티 코어 CPU를 최대한 활용하기 위해 요소들을 분배시켜 병렬 작업 가능!
    -> 내부에서 for loop를 직접 돌림

package ch17.sec02;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class ParallelStreamExam {
	public static void main(String[] args) {
		// List 컬렉션 생성함 (파라미터값이 문자열!)
		List<String> list = new ArrayList<>();
		
		// List에 요소 추가!
		list.add("홍길동");
		list.add("신용권");
		list.add("감자바");
		list.add("람다식");
		list.add("박병렬");
		
		// 병렬 스트림 얻는 구문!
		// 여러 개의 스레드를 사용하여 리스트의 데이터를 동시에 처리할 수 있도록 변환함
		Stream<String> parallelStream = list.parallelStream();
		
		// 리스트에 요소들을 하나씩 가져와서 해당 요소와 실행중인 스레드를 출력함
		// 멀티스레드로 병렬처리를 하기 때문에 작업이 편해짐!
		parallelStream.forEach(name -> {
			System.out.println(name + ": " + Thread.currentThread().getName());
		});
		
	}
}

중간 처리와 최종 처리

스트림의 처리 과정

  • 1단계 : 컬렉션이나 배열로 스트림 객체를 만듬
  • 2단계 : 중간 처리 (데이터를 가공 : 계산 또는 선택이 일어남)
    -> 필터링이나 매핑!
  • 3단계 : 최종 처리 (집계 처리!)
    -> 합계, count, 반복 작업 등..

스트림 파이프라인

  • 컬렉션의 오리지널 스트림 뒤에 필터링 중간 스트림이 연결될 수 있고 그 뒤에 매핑 중간 스트림이 연결될 수 있음

  • 스트림 : 논리적인 객체
  • 오리지널 스트림과 집계 처리 사이의 중간 스트림들은 최종 처리를 위해 요소를 걸러내거나 (필터링 : if문), 요소를 변환시키거나 (매핑 : 자료 변환), 정렬하는 작업은 수행
  • 최종 처리는 중간 처리에서 정제된 요소들을 반복하거나, 집계(카운팅, 총합, 평균) 작업을 수행
  • 최종 처리는 단 한 번만 진행됨 (단일 책임의 원칙)
  • 중간 처리는 여러 번 실행 가능!

package ch17.sec03;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter // Getter 메소드 생성
@AllArgsConstructor // 모든 필드를 인자로 가지는 생성자 만듦
public class Student {
	private String name;
	private int score;	
}
package ch17.sec03;

import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamPipeLineExample {
	public static void main(String[] args) {
		// Arrays.asList를 이용하여 배열로 값을 받고, List 컬렉션으로 변환함
		List<Student> list = Arrays.asList(
			new Student("홍길동", 10),
			new Student("신용권", 20),
			new Student("유미선", 30)
		);
		
		// list로 받은 값을 stream 형태로 변환하여 저장
		// stream을 사용하면서 반복문 없이 데이터 처리하는데 용이해짐
		Stream<Student> studentStream = list.stream();
		
		// IntStream : int 값을 처리할 수 있는 스트림
		// studentStream에서 받은 요소들 중에 int 타입의 요소들만 추출함
		IntStream scoreStream = studentStream.mapToInt(
				student -> student.getScore());
		
		// scoreStream에서 받은 int 값의 평균을 구해서 double 형태로 변환
		double avg = scoreStream.average().getAsDouble();
	}
}

스트림 인터페이스

  • java.util.stream 패키지에 BaseStream 인터페이스를 부모로 한 자식 인터페이스들은 상속 관계임
  • BaseStream에는 모든 스트림에서 사용할 수 있는 공통 메소드들이 정의됨
  • IntStream, LongStream 등 타입이 미리 정해진 타입들에 비해, Stream은 타입이 정해져있지 않음!

  • 스트림을 생성하는 메소드

컬렉션으로부터 스트림 얻기 (90퍼이상 사용)

  • java.util.Collection 인터페이스는 스트림과 parallelStream() 메소드를 가지고 있어서 자식 인터페이스인 List와 Set 인터페이스를 구현한 모든 컬렉션에서 객체 스트림을 얻을 수 있음
package ch17.sec04.exam01;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

@Getter // getter 함수만 생성
@AllArgsConstructor // 모든 필드를 인자로 가지는 생성자
@ToString // toString 함수 생성
public class Product {
	//필드 입력
	private int pno;
	private String name;
	private String company;
	private int price;
}
package ch17.sec04.exam01;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class StreamExam {
	public static void main(String[] args) {
		// List 컬렉션 생성
		List<Product> list = new ArrayList<>();
		
		for(int i=1;i<=5;i++) {
			// Product 생성자에 인자 넣기!
			Product product = new Product(1, "상품"+i, "멋진 회사", 
					(int)(10000*Math.random()));
			
			list.add(product);
		}
		
		// List 컬렉션으로 받은 Product 객체의 요소들을 Stream 형태로 변환
		Stream<Product> stream = list.stream();
		
		// stream을 통해 Product에 저장된 요소들을 모두 출력함
		stream.forEach(p -> System.out.println(p));
	}
}

배열로부터 스트림 얻기

  • java.util.Arrays 클래스로 다양한 종류의 배열로부터 스트림을 얻을 수 있음
package ch17.sec04.exam02;

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamExam {
	public static void main(String[] args) {
		// 문자열 배열 생성
		String[] strArray = {"홍길동", "신용권", "김미나"};
		
		// 배열을 Stream 형태로 변환하기
		Stream<String> strStream = Arrays.stream(strArray);
		
		// 문자열 배열을 하나씩 출력해줌
		strStream.forEach(item -> System.out.print(item + ","));
		System.out.println();
		
		
		// 정수형 배열 생성
		int[] intArray = {1, 2, 3, 4, 5};
		
		// 정수형 배열을 stream 형태로 변환
		// 기본형 타입의 경우 타입Stream 클래스명으로 선언!
		IntStream intStream = Arrays.stream(intArray);
		
		// 정수형 배열의 요소들을 하나씩 출력
		intStream.forEach(item -> System.out.print(item + ","));
		System.out.println();
	}
}

숫자 범위로부터 스트림 얻기

  • IntStream 또는 LongStream의 정적 메소드인 range()와 rangeClosed() 메소드로 특정 범위의 정수 스트림을 얻을 수 있음
package ch17.sec04.exam03;

import java.util.stream.IntStream;

public class StreamExam {
	// 람다식에 적용하기 위해서는 정적 변수로 선언해줘야함
	public static int sum;
	
	public static void main(String[] args) {
		// 1부터 100까지의 숫자 범위!
		IntStream stream = IntStream.rangeClosed(1, 100);
		
		// range(a,b) : a부터 b 바로 전의 수까지의 범위
		// rangeClosed(a,b) : a부터 b까지의 범위
		
		// 지역변수는 람다식에서 사용 못함
		// int sum1 = 0;
		
		// 1부터 100까지의 값을 모두 더함!
		stream.forEach(a -> sum += a);
		System.out.println("총합: " + sum);
	}
}

파일로부터 스트림 얻기

  • java.nio.file.Files의 lines() 메소드로 텍스트 파일의 행 단위 스트림을 얻을 수 있음
package ch17.sec04.exam04;

import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class StreamExample {
	public static void main(String[] args) throws Exception {
		
		// StreamExample.class : StreamExample 클래스를 참조한다는 뜻
		// getResource("data.txt") : data.txt 파일을 찾음
		// toURI() : getResource()는 URL 객체를 반환하는데 이를 URI 형태로 변환하는것
		// URI 형태로 변환하는 이유 -> 웹 페이지에 국한된게 아닌 더 많은 종류의 파일을 찾기 위해서!
		// Paths.get을 Path 객체의 형태로 변환 : 파일이나 디렉토리의 경로를 표현하는 클래스
		Path path = Paths.get(StreamExample.class.getResource("data.txt").toURI());
		
		// Path로 받은 경로의 파일을 인코딩하여 한 줄씩 읽어들임
		Stream<String> stream = Files.lines(path, Charset.defaultCharset());
		
		// 받아온 파일을 한 줄씩 출력함
		stream.forEach(line -> System.out.println(line));
		
		// stream 닫기
		// 파일이나 네트워크같이 외부 자원을 사용하는 스트림은 시스템 리소스가
		// 반납되지 않을 수도 있기 때문에 close를 통해 자원을 명시적으로 해제해줘야함
		stream.close();
	}
}

필터링 (요소 걸러내기)

  • 필터링 : 요소를 걸러내는 중간 처리 기능

  • distinct() 메소드 : 요소의 중복을 제거함

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

  • Predicate : 함수형 인터페이스

  • 모든 Predicate는 매개값을 조사한 후 boolean을 리턴하는 test() 메소드를 가지고 있다

package ch17.sec05;

import java.util.ArrayList;
import java.util.List;

public class FilteringExample {
	public static void main(String[] args) {
		
		// List 컬렉션 생성, ArrayList 사용
		List<String> list = new ArrayList<>();
		
		// List 컬렉션에 요소 추가 (문자열)
		list.add("이동주");
		list.add("홍길동");
		list.add("이동주");
		list.add("감자바");
		list.add("이진아");
		
		// 중복 제거
		// list.stream() : 스트림을 사용하여 컬렉션의 데이터를 처리!
		list.stream()
			// distinct() : 중복 제거
			.distinct()
			// forEach() : 값을 차례대로 출력
			.forEach(n -> System.out.println(n));
		System.out.println();
		
		// 성이 "이"로 시작하는 사람 출력
		list.stream()
			// filter() : 요소를 거르는 역할로, 조건문 역할을 함
			.filter(n -> n.startsWith("이"))
			.forEach(n -> System.out.println(n));
		System.out.println();
		
		// 성이 "이"로 시작하는 사람을 출력하고, 중복 제거 실시
		list.stream()
			.distinct()
			.filter(n -> n.startsWith("이"))
			.forEach(n -> System.out.println(n));
	}
}

매핑(요소 변환)

  • 스트림의 요소를 다른 요소로 변환하는 중간 처리 기능
  • 매핑 메소드: mapXxx(), asDoubleStream(), asLongStream(), boxed(), flatMapXxx() 등

요소를 다른 요소로 변환

  • mapXxx() 메소드 : 요소를 다른 요소로 변환한 새로운 스트림을 리턴함

  • 매개타입인 Function은 함수형 인터페이스

  • 모든 Function은 매개값을 리턴값으로 매핑하는 applyXxx() 메소드를 가짐

package ch17.sec06.exam01;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter // getter 사용
@AllArgsConstructor // 모든 필드를 매개변수로 가지는 생성자
public class Student {
	private String name;
	private int score;
}
package ch17.sec06.exam01;

import java.util.ArrayList;
import java.util.List;

public class MapExample {
	public static void main(String[] args) {
		
		// List 컬렉션 생성
		List<Student> studentList = new ArrayList<>();
		
		// List 컬렉션에 요소를 추가
		studentList.add(new Student("이동주", 95));
		studentList.add(new Student("이진아", 97));
		studentList.add(new Student("홍길동", 50));
		
		// Student 객체를 stream으로 변환
		studentList.stream()
			// Student 객체에 받은 값중에 int 타입의 요소만을 받기
			.mapToInt(s -> s.getScore())
			
			// 위의 조건으로 받은 요소들을 모두 출력
			.forEach(score -> System.out.println(score));
	}
	
}
  • 기본 타입 간의 변환이거나 기본 타입 요소를 래퍼(Wrapper) 객체 요소로 변환하려면 간편화 메소드를 사용 가능!

package ch17.sec06.exam02;

import java.util.Arrays;
import java.util.stream.IntStream;

public class MapExample {
	public static void main(String[] args) {
		int[] intArray = {1, 2, 3, 4, 5};
		
		// intArray를 int 타입으로 반복 처리
		IntStream intStream = Arrays.stream(intArray);
		
		intStream
			// int 형태로 처리한 Stream을 double 타입으로 변환하여 stream 처리
			.asDoubleStream()
			// forEach : 하나씩 값을 가져오는 역할!
			.forEach(d -> System.out.println(d));
		
		System.out.println();
		
		intStream = Arrays.stream(intArray);
		intStream
			// boxed() : 기본형 스트림을 래퍼 클래스 (Integer, Double 등 클래스)의 스트림으로 변환
			// 래퍼 클래스로 변환함으로써 컬렉터나 제네릭을 활용할 수 있음
			.boxed()
			// Integer 타입의 값들을 int 타입으로 변환해서 하나씩 출력함
			.forEach(obj -> System.out.println(obj.intValue()));
	}
}

요소를 복수개의 요소로 변환

  • flatMapXxx() 메소드 : 하나의 요소복수 개의 요소들로 변환한 새로운 스트림을 리턴함

package ch17.sec06.exam03;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class FlatMappingExample {
	public static void main(String[] args) {
		// ArrayList 사용
		// 문장 스트림을 단어 스트림으로 변환함
		List<String> list1 = new ArrayList<>();
		list1.add("this is java");
		list1.add("i am a best developer");
		
		list1.stream()
			// flapMap : 여러 개의 스트림을 변환하여 하나의 스트림의 형태로 만듬!
			// Arrays.stream -> 배열을 스트림 형태로 변환하는 역할을 함!
			// split : 해당 문자를 기준으로 문자열을 나눔
			.flatMap(data -> Arrays.stream(data.split(" ")))
			.forEach(word -> System.out.println(word));
		
		
		// 문자열 숫자 목록 스트림을 숫자 스트림으로 변환함
		List<String> list2 = Arrays.asList("10, 20, 30, 40, 50");
		list2.stream()
			// String 형태의 스트림을 int 형태의 스트림으로 변환함
			.flatMapToInt(data -> {
				// 쉼표로 문자열을 나눔
				String[] strArr = data.split(",");
				// list에서 나눠진 문자들의 갯수만큼 int 배열 생성
				int[] intArr = new int[strArr.length];
				// 문자열의 앞뒤 공백을 제거하여 정수 형태로 변환 후 int 배열에 값을 하나씩 저장
				for(int i=0;i<strArr.length;i++) {
					intArr[i] = Integer.parseInt(strArr[i].trim());
				}
				// 위 int 배열을 스트림형태로 변환
				return Arrays.stream(intArr);
			})
			// 위 스트림에 있는 값들을 하나씩 출력!
			.forEach(number -> System.out.println(number));
	}
}

요소 정렬

정렬

  • 요소를 오름차순 또는 내림차순으로 정렬하는 중간 처리 기능
  • 정렬하려면 Comparable 객체를 구현하거나 Comparator 객체를 구현하기!

Comparable 구현 객체의 정렬

  • 스트림의 요소가 객체일 경우 객체가 Comparable을 구현하고 있어만 sorted() 메소드를 사용하여 정렬이 가능하다.
  • 그렇지 않다면 ClassCastException 발생
package ch17.sec07.exam01;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
// Comparable<T> : 클래스 내에서 값을 비교하기 위해 사용!
public class Student implements Comparable<Student> {
	private String name;
	private int score;
	
	@Override
	public int compareTo(Student o) {
		// 두 수가 같으면 0, 작으면 음수, 클경우 양수를 리턴함
		return Integer.compare(score, o.score);
	}
}
package ch17.sec07.exam01;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class SortingExample {
	public static void main(String[] args) {
		// ArrayList 사용 
		List<Student> studentList = new ArrayList<>();
		
		// List에 요소를 추가함
		studentList.add(new Student("홍길동", 30));
		studentList.add(new Student("이동주", 10));
		studentList.add(new Student("감자바", 20));
		
		studentList.stream()
			// sorted() : 점수(정수 타입의 값)를 기준으로 오름차순 정렬
			.sorted()
			// 이름과 점수를 순차적으로 출력함
			.forEach(s -> System.out.println(s.getName() + ": " + s.getScore()));
		
		System.out.println();
		
		studentList.stream()
			// Comparator.reverseOrder() : 점수(정수 타입의 값 기준으로 내림차순 정렬
			.sorted(Comparator.reverseOrder())
			.forEach(s -> System.out.println(s.getName() + ": " + s.getScore()));
	}
}

Comparator를 이용한 정렬

  • 구조
sorted((o1, o2) -> { ... })
  • 요소 객체가 Comparable을 구현하고 있지 않다면, 비교자를 제공하면 요소를 정렬시킬 수 있음

  • 괄호 안에는 o1이 o2보다 작으면 음수, 같으면 0, 크면 양수를 리턴하도록 작성

  • Integer.compare(o1, o2) : o1, o2가 정수일 때 호출

  • Double.compare(o1, o2) : o1, o2가 실수일 때 호출

package ch17.sec07.exam02;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class Student {
	private String name;
	private int score;
}
package ch17.sec07.exam02;

import java.util.ArrayList;
import java.util.List;

public class SortingExample {
	public static void main(String[] args) {
		// ArrayList 사용
		List<Student> studentList = new ArrayList<>();
		
		// List에 요소 추가
		studentList.add(new Student("홍길동", 30));
		studentList.add(new Student("이동주", 10));
		studentList.add(new Student("감자바", 20));
		
		studentList.stream()
			// score를 기준으로 오름차순 정렬
			.sorted((s1, s2) -> Integer.compare(s1.getScore(), s2.getScore()))
			.forEach(s -> System.out.println(s.getName() + ": " + s.getScore()));
		
		studentList.stream()
		// s2와 s1의 순서를 바꿔 score를 기준으로 내림차순 정렬
			.sorted((s1, s2) -> Integer.compare(s2.getScore(), s1.getScore()))
			.forEach(s -> System.out.println(s.getName() + ": " + s.getScore()));
	}
}

루핑 (요소를 하나씩 처리)

  • 스트림에서 요소를 하나씩 반복해서 가져와 처리하는 것

  • 매개타입인 Consumer는 함수형 인터페이스
  • 모든 Consumer는 매개값을 처리(소비)하는 accept() 메소드를 가지고 있음

매칭 (요소 조건 만족 여부)

  • 요소들이 특정 조건에 만족하는지 여부를 조사하는 최종 처리 기능
  • allMatch(), anyMatch(), noneMatch() 메소드는 매개값으로 주어진 Predicate가 리턴하는 값에 따라 true 또는 false를 리턴함
  • 많이 사용함

집계 (요소 기본 집계)

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

스트림이 제공하는 기본 집계

  • 스트림은 카운팅, 최대, 최소, 평균, 합계 등을 처리하는 다음과 같은 최종 처리 메소드를 제공

Optional 클래스

  • Optional, OptionalDouble, OptionalInt, OptionalLong 클래스는 단순히 집계값만 저장하는 것이 아니라, 집계값이 없으면 디폴트 값을 설정하거나 집계값을 처리하는 Consumer를 등록

최종 처리에서 average 사용 시 요소 없는 경우를 대비하는 방법

1) isPresent() 메소드가 true를 리턴할 때만 집계값을 얻는다
2) orElse() 메소드로 집계값이 없을 경우를 대비해서 디폴트 값을 정해놓는다
3) ifPresent() 메소드로 집계값이 있을 경우에만 동작하는 Consumer 람다식을 제공함

요소 커스텀 집계

스트림이 제공하는 메소드

  • 스트림은 기본 집계 메소드인 sum(), average(), count(), max(), min()을 제공하지만, 다양한 집계 결과물을 만들 수 있도록 reduce() 메소드도 제공

  • reduce()는 스트림에 요소가 없을 경우 예외가 발생하지만, identity 매개값이 주어지면 이 값을 디폴트 값으로 리턴함
  • reduce()의 기본값 :
    -> 사칙 연산 +- : 0, */ : 1

요소 수집

필터링한 요소 수집

  • Stream의 collect(Collector<T,A,R> collector) 메소드는 필터링 또는 매핑된 요소들을 새로운 컬렉션을 수집하고 이 컬렉션을 리턴함
  • 매개값인 Collector는 어떤 요소를 어떤 컬렉션에 수집할 것인지를 결정함
  • 타입 파라미터의 T는 요소, A는 누적기(accumulator), 그리고 R은 요소가 저장될 컬렉션

요소 그룹핑

  • Collectors.groupingBy() 메소드에서 얻은 Collector를 collect() 메소드를 호출할 때 제공함
  • groupingBy()는 Function을 이용해서 T를 K로 매핑 후 K를 키로 해 List를 값으로 갖는 Map 컬렉션을 생성

  • Collectors.groupingBy() 메소드는 그룹핑 후 매핑 및 집계 (평균, 카운팅, 연결, 최대, 최소, 합계)를 수행할 수 있도록 두 번째 매개값인 Collector를 가질 수 있음

요소 병렬 처리

동시성과 병렬성

  • 동시성 : 멀티 작업을 위해 멀티 스레드가 하나의 코어에서 번갈아 가며 실행하는 것
  • 병렬성 : 멀티 작업을 위해 멀티 코어를 각각 이용해서 병렬로 실행하는 것

  • 데이터 병렬성 : 전체 데이터를 분할해서 서브 데이터셋으로 만들고, 이 서브 데이터셋들을 병렬 처리해서 작업을 빨리 끝내는 것
  • 작업 병렬성 : 서로 다른 작업을 병렬 처리하는 것

포크조인 프레임워크

  • 전체 요소에 관한 것을 각각의 파트로 나누고, 각각의 코어에 처리를 맡김! (마지막에는 모두 합침)
  • 합치는 과정을 조인(Join) 이라고 함!
  • 포크 단계 : 전체 요소들을 서브 요소셋으로 분할하고, 각각의 서브 요소셋을 멀티 코어에서 병렬로 처리함
  • 조인 단계 : 서브 결과를 결합해서 최종 결과를 만들어냄

병렬 스트림 사용

  • 자바 병렬 스트림은 백그라운드에서 포크조인 프레임워크가 사용하므로 병렬 처리 용이
  • parallelStream() 메소드는 컬렉션(List, Set)으로부터 병렬 스트림을 바로 리턴
  • parallel() 메소드는 기존 스트림을 병렬 처리 스트림으로 변환

병렬 처리 성능에 영향을 미치는 요인

  • 요소의 수와 요소당 처리 시간
  • 스트림 소스의 종류
  • 코어(Core)의 수
profile
끄작끄작

0개의 댓글