[Java] 스트림 (Stream) 타입별 변환

2022. 12. 12. 14:01 JAVA/Java

스트림 (Stream) 만들기

 

컬렉션 스트림

Collection에 stream()이 정의되어 있어 Collection의 자손인 List와 Set을 구현한 컬렉션 클래스들은 모두 stream()으로 스트림을 생성할 수 있다.

 

Stream<T> Collection.stream()

// List로부터 스트림 생성
List<Integer> list = ARrays.asList(1,2,3,4,5);
Stream<Integer> intStream = list.stream();

 

배열 스트림

배열을 소스로하는 스트림을 생성하는 메서드로 Stream과 Arrays에 static 메서드로 정의되어 있다.

 

문자열 스트림

 

Stream<String> srtSTream = Stream.of("a","b","c");	// 가변인자
Stream<String> srtSTream = Sream.of(new Stringp[{"a","b","c"});
Stream<String> srtSTream = Arrays.sream(new String[]{"a","b","c"});
Stream<String> srtSTream = Arrays.sream(new String[]{"a","b","c"}, 0, 3);

 

기본형(int, long, double) 배열 스트림

 

 IntStream IntStream.of(int...values)
 IntStream IntStream.of(int[])
 IntStream Arrays.stream(int[])
 IntStream Arrays.stream(int[] array, int startInclusive, endExclusive)


count()만 제공하는 Stream 과 달리 기본형 스트림은 숫자를 다루는데 편리한 메서드들을 제공한다.

 

int sum()                   스트림 모든 요소의 총합
OptionalDouble average()    sum()/count()
OptionalInt max()           스트림 요소 중 제일 큰 값
OPtionalInt min()           스트림 요소 중 제일 작은 값

* max()와 min()은 Stream에도 정의되어 있지만 매개변수로 Comparator를 지정해야 한다.
* 이 메서드들은 최종연산이다.
* sum()과 average()를 모두 호출하려면 summaryStatistics() 메서드 사용



스트림 (Stream) 변환하기

 

Stream 스트림 - 기본형 스트림 변환

map()은 연산의 결과로 Stream 타입의 스트림을 반환하는데,
스트림의 요소를 숫자로 변환하는 경우 IntStream과 같은 기본형 스트림으로 변환하는 것이 더 유용할 수 있다.

 

DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper)  
IntStream mapToInt(ToIntFunction<? super T> mapper)
LongStream mapToLong(ToLongFunction<? super T> mapper)

// 스트림에 포함된 모든 학생의 성적을 합산하기 위해 map()으로 새로운 스트림 생성
Stream<Integer> studentScoreStream = studentStream.map(Student::getTotalScore);

// 애초에 Stream<Integer>가 아닌 IntStream 타입의 스트림 생성하기
// 성적을 더할 때 Integer를 int로 변환할 필요 없어서 더 효율적이다.
IntStream studentScoreStream = studentStream.mapToInt(Student::getTotalScore);
int allTotalScore = studentScoreStream.sum();

 

Stream - Stream 변환

flatMap() 사용

 

// 요소가 문자열 배열(String[])인 스트림
Stream<String[]> strArrStrm = Stream.of(
                              new String[]{"abc", "def", "ghi"},
                              new String[]{"ABC", "DEF"m "JKLMN"}
                              );

// Stream<String[]>을 map(Arrays::stream)으로 변환한 결과는 Stream<String>이 아닌 Stream<Stream<String>>.
// 즉 스트림의 스트림이다.
Stream<Stream<String>> strStrStrm = strArrStrm.map(Arrays::stream);

//map() 대신 flatMap() 사용하면 각 배열이 하나의 스트림의 요소가 된다.
Stream<String> strStrm = strArrStrm.flatMap(Arrays::stream);

 

스트림 - 컬렉션/배열 변환

toList(), toSet(), toMap(), toCollection(), toArray()

 

// 스트림의 모든 요소를 컬렉션에 수집하려면, Collectors클래스의 toList()와 같은 메서드를 사용하면 된다.  
List<String> names = stuStream.map(Student::getName)
                              .collect(Collectors.toList());

// List나 Set이 아닌 특정 컬렉션을 지정하려면,
// toCollection()에 해당 컬렉션의 생성자 참조를 매개변수로 넣어주면 된다.
ArrayList<String> list = names.stream()
                              .collect(Collectors.toCollection(ArrayList::new));
                              
// Map은 객체의 어떤 필드를 키와 값으로 사용하지 지정해야 한다.
// 요소의 타입이 Person인 스트림에서 사람의 주민번호(regId)를 키로 하고, 값으로 Person 객체를 그대로 저장
Map<String, Person> map = personStream.collect(Collectors.toMap(p->p.getRegId(), p->p)

// 스트림에 저장된 요소들을 T[] 타입의 배열로 변환하려면 toArray() 사용
// 단, 해당 타입의 생성자 참조를 매개변수로 지정해줘야 한다. 지정하지 않으면 반환되는 배열의 타입은 Object[]
Student[] stuNames = studentStream.toArray(Student[]::new);   // OK
Student[] stuNames = studentStream.toArray();                 // 에러
Object[] stuNames = studentStream.toArray();                  // OK

 

 

 

스트림 (Stream) 변환 예제

 

List - Array - 기본형 Stream 변환하여 average( ) 메서드 사용하기

데이터를 동적으로 추가할 때, array의 경우 초기에 array 사이즈를 지정하고 동적으로 데이터를 추가하는 데 불편함이 있다. 그래서 주로 ArrayList의 add 메서드를 사용하여 데이터를 가공하고는 한다.

 

List<Double> doubleList = new ArrayList<Double>();

// DB 조회한 데이터의 특정 값을 doubleList add 하였다고 가정한다.

// List를 Double클래스타입의 Array로 생성하면서 사이즈를 할당해준다.
Double[] dbArray = doubleList.toArray(new Double [doubleList.size()]);
// 기본형 double의 Array로 변환한다.
double[] doubleArray = ArrayUtils.toPrimitive(dbArray);

// 기본형 double Array로 변환한 것을 기본형 Stream으로 변환하여 average 메서드를 사용한다.
Arrays.stream(doubleArray).average().getAsDouble();

 

위 코드 간략화하면 아래와 같다.

 

List<Double> doubleList = new ArrayList<Double>();

// DB 조회한 데이터의 특정 값을 doubleList add 하였다고 가정한다.

double[] doubleArray = ArrayUtils.toPrimitive(doubleList.toArray(new Double [doubleList.size()]));
Arrays.stream(doubleArray).average().getAsDouble();

 

변환 과정 자체는 List - Stream - 기본형 Stream 변환하여 메서드 활용도 가능하다.

입맛에 맞게 사용해보자.

 

출처 : https://haenny.tistory.com/293