[Java] 스트림 (Stream) 타입별 변환
스트림 (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 변환하여 메서드 활용도 가능하다.
입맛에 맞게 사용해보자.
'JAVA > Java' 카테고리의 다른 글
[Java] 중복 키 허용 MultiValueMap 와 HashMap 차이 (0) | 2022.12.12 |
---|---|
[Java] Comparator, Lamda 사용하여 2차원 배열 정렬하기 (0) | 2022.12.12 |
[Java] Arrays.sort 와 Collections.sort 정리 (0) | 2022.12.12 |
[Java] StringTokenizer Class 사용 및 Split 비교 (0) | 2022.12.12 |
[Java] POI 엑셀 다운로드 시 Invalid char (/) found at index (6) in sheet name 에러 (0) | 2022.12.12 |
[Java] Lombok 사용 시 @Data compileJava 오류 (0) | 2022.11.15 |
[Java] 윈도우 cmd 명령어 실행 : Java로 실행파일 실행시키기 응용 (0) | 2022.11.15 |
[Java] FTP 서버로 파일 전송(업로드) 방법 및 다계층 디렉토리 만들기 (0) | 2022.11.15 |