Java

< Java > Stream

98kg 2023. 8. 25. 13:04
Stream 이란?

컬랙션 등의 내부에 있는 요소(element)를 처리하는 방식을 주입해서 그 결과를 빠르게 그리고 쉽게 도출하여 원하는 다음 

요소로 변경해서 최종적으로 결과 값을 원하는 연산로직에 쉽게 도출하도록 만드는 요소이다.

매우 다양한 형태가 존재하며 모두 외울 필요는 없다.

또한 이 데이터를 도출할 때는 내부적으로 콜백 형태의 함수형 인터페이스를 받도록 파라미터가 정의 되었기 때문에

반드시 람다를 이용해야만 사용가능합니다.


아래는 코드로 보는 간단한 Stream의 예제입니다.

@AllArgsConstructor
@NoArgsConstructor
@Data
class FullStScore{
    // 우리반 학생 점수를 관리하는 클래스
    private String name;
    private  int score;
   
}

public class StreamEx1 {
    public static void main(String[] args) {
	List<String> list = new ArrayList();
	list.add("가");
	list.add("나");
	list.add("다");
	list.add("라");
	list.add("마");
	
	Stream<String> pStream = list.parallelStream();
	pStream.forEach(t -> { System.out.println(t);});

스트림을 통해 전달될 데이터를 원하는 타입으로 변경 가능하도록 만들 수 있습니다.

 


대부분 메서드를 통해 변경을 하는데, 하나 주의 해야할 것은 변경이 되면,

변경된 타입의 데이터는 또다른 스트림을 통해 전달된다는 것이다. 꼭 기억하기!!
이렇게 변환되어 전달된 최종 스트림의 데이터는 메서드를 통해서 여러가지 기능의
산술, 정렬 등의 메서드를 통해 결과를 도출 할 수 있습니다.
이때, 꼭 주위해야 할 점은,

집계 요소 메서드를 ( average ) 호출하지 않으면, 중간에 변환된 스트림이 제기능을 못하게 된다는 점이다.
이 스트림 변환은 일반적으로 메서드 체인 방식으로 구현합니다.

 

아래는 스트림을 통한 데이터 타입의 예입니다.

@AllArgsConstructor
@NoArgsConstructor
@Data
class FullStScore{
    // 우리반 학생 점수를 관리하는 클래스
    private String name;
    private  int score;
   
}

public class StreamEx1 {
    public static void main(String[] args) {
	List<String> list = new ArrayList();
	list.add("가");
	list.add("나");
	list.add("다");
	list.add("라");
	list.add("마");
	
	Stream<String> pStream = list.parallelStream();
	pStream.forEach(t -> { System.out.println(t);});
	
	
	FullStScore a = new FullStScore("lee", 100);
	FullStScore b = new FullStScore("moon", 48);
	FullStScore c = new FullStScore("sun", 77);
	
	ArrayList< FullStScore> score = new ArrayList();
	
	score.add(a);
	score.add(b);
	score.add(c);
	
	Stream<FullStScore> scoreStream = score.stream();
	// 요소의 특정 데이터를 특정 타입으로 변환 하도록하자
	IntStream ist =  scoreStream.mapToInt( value -> value.getScore());
	
	double avg = ist.average().getAsDouble();
	System.out.println("평균 점수 : " + avg);
	
	double avg2 = score.stream().mapToInt(value ->value.getScore()).asDoubleStream().average().getAsDouble();
	System.out.println("평균 점수 : " + avg2);
	
    }

IntStream


int 타입의 요소를 스트림을 통해 전달하는 스트림이다.
 mapToInt() 등의 스트림 변화 메서드를 통해 다른요소의 값을   int로 변환해서 전달하기도하고,

다른 메서드를 통해 특정 범위의 int값을 스트림을 통해 전달 할 수도 있다.


 

1 ~ 100 사이의 int 값 생성 후 스트림을 통해 전달받는 법을 코드로 보여드리겠습니다.

 

import java.util.stream.IntStream;

public class IntStreamEx {
    
    static  int sum = 0;
    
    public static void main(String[] args) {
	
	
	//int sum = 0;
	//final int sum = 0;
	

	IntStream.range(1, 100).forEach(value -> System.out.println(sum += value)); // 1 부터 99 까지 생성
	
	IntStream.rangeClosed(1, 100).forEach(value -> System.out.println(sum += value));  // 1 부터 100 까지 생성
    	}
	
    }

지역변수 sum이 스트림 내부에서 람다의 변수로 사용되면 지역 익명객체의 target 변수가 된다.
자바에서는 4개의 중첩이 존재하는데,

이 중 지역 중첩은 지역 (메서드) 내의 변수를 중첩 클래스에서 사용 할 시엔 반드시 final 로 선언이 되어야 한다.
때문에, 지역 sum 이 final 로 선언하면 가능하나 reassign 이 안되기 때문에 static member 로 선언해서 사용한다.

 


 

줄이자면, Stream에서 값을 변경하기위해 reassign  을 이용하려면 static member로 선언해야한다 !!