스트림(Stream)

Sunny·2023년 1월 25일
0

🌱 스트림(Stream)이란?

스트림은 자바 8부터 추가된 컬렉션(배열 포함)의 저장 요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해주는 반복자이다.

자바 7 이전까지는 List 컬렉션에서 요소를 순차적으로 처리하기 위해 Iterator 반복자를 다음과 같이 사용했다.

List<String> list = Arrays.asList("홍길동","김자바","신길동");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
	String name = iterator.next();
  	System.out.println(name);
}

위의 코드를 Stream을 사용해서 변경하면 다음과 같다.

List<String> list = Arrays.asList("홍길동","김자바","신길동");
Stream<String> stream = list.stream();
stream.forEach(name -> System.out.println(name));

컬렉션의 stream() 메소드로 스트림 객체를 얻고 나서 stream.forEach(name -> System.out.println(name)); 메소드를 통해 컬렉션의 요소를 하나씩 콘솔에 출력한다.


🌱 스트림의 특징

1. 람다식으로 요소 처리 코드를 제공

Stream이 제공하는 대부분의 요소 처리 메소드는 함수적 인터페이스 매개 타입을 가지기 때문에 람다식 또는 메소드 참조를 이용해서 요소 처리 내용을 매개값으로 전달할 수 있다.

// 요소 처리를 위한 람다식
public class Ex {
	public static void main(String[] args) {
  		List<Student> list = Arrays.asList(
  			new Student("홍길동", 90),
  			new Student("김자바", 80)
  		);
  
  		Stream<Student> stream = list.stream(); // 스트림 얻기
  		// List 컬렉션에서 Student를 가져와 람다식의 매개값으로 제공
  		stream.forEach( s -> {
  			String name = s.getName();
  			int score = s.getScore();
  			System.out.println(name + "-" + score);
  		});
    }  
}
  
// 학생 클래스
public class 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 int getScore() { return score; }
}

2. 내부 반복자를 사용하므로 병렬 처리가 쉬움

외부 반복자(external iterator)란 개발자가 코드로 직접 컬렉션의 요소를 반복해서 가져오는 코드 패턴을 말한다. index를 이용하는 for문, Iterator를 이용하는 while문은 모두 외부 반복자를 이용한다.

내부 반복자(Internal iterator)는 컬렉션 내부에서 요소들을 반복시키고, 개발자는 요소당 처리해야 할 코드만 제공하는 코드 패턴을 말한다.

Iterator은 컬렉션의 요소를 가져오는 것에서부터 처리하는 것까지 모두 개발자가 작성해야하지만, 스트림은 람다식으로 요소 처리 내용만 전달할 뿐, 반복은 컬렉션 내부에서 일어난다. 스트림을 이용하면 코드도 간결해지지만, 무엇보다도 요소의 병렬 처리가 컬렉션 내부에서 처리되므로 일석이조의 효과를 가져온다.

병렬(parallel) 처리란 한 가지 작업을 서브 작업으로 나누고, 서브 작업들을 분리된 스레드에서 병렬적으로 처리하는 것을 말한다. 병렬 처리 스트림을 이용하면 런타임 시 하나의 작업을 서브 작업으로 자동으로 나누고, 서브 작업의 결과를 자동으로 결합해서 최종 결과물을 생성한다.

3. 스트림은 중간 처리와 최종 처리를 할 수 있음

스트림은 컬렉션의 요소에 대해 중간 처리와 최종 처리를 할 수 있다.

중간 처리 - 매핑, 필터링, 정렬 수행
최종 처리 - 반복, 카운팅, 평균, 총합 등의 집계 처리 수행

다음은 예제이다. List에 저장되어 있는 Student 객체를 중간 처리에서 score 필드값으로 매핑하고, 최종 처리에서 score 평균값을 산출한다.

public class Ex {
	public static void main(String[] args) {
  		List<Student> studentList = Arrays.asList(
  			new Student("홍길동", 10),
  			new Student("이길동", 20),
  			new Student("박길동", 30)
  		);
  
  		double avg = studentList.stream()
  				// 중간 처리(학생 객체를 점수로 매핑)
  				.mapToInt(Student :: getScore)
				// 최종 처리(평균 점수)
  				.average()
  				.getAsDouble();
  
  		System.out.println("평균 점수:"+avg);
   	}
}
profile
개발에 재미를 붙여보기 :)

0개의 댓글