일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- Javascript
- ORM
- 제이쿼리그리드
- Jenkins
- QueryDSL
- jqGrid
- MessageQueue
- 보안
- mom
- 자동배포
- rabbitmq
- mssql
- docker
- JPA
- 스트림
- JQuery
- ci/cd
- 자동빌드
- java
- 그리드
- 자바8
- DevOps
- Stream
- stream api
- apache.poi
- spring
- 대용량 업로드
- sqlserver
- 엑셀 업로드
- poi
- Today
- Total
개발 메모장
[Java] Stream API(2) - 스트림 데이터 가공 본문
#. 생성한 스트림으로 처리가 가능하다면 사용하지 않겠지만 데이터를 가공해 처리해야 하는 경우 사용하는 메서드들에 대해 알아보려 합니다.
#. 아래 작성한 내용 외에도 많은 메서드가 존재하니 일부 메서드에 대한 내용만 간단히 알아보도록 하겠습니다.
- 처리 방법에 따른 메서드 설정
- 병렬 처리 시 parallel()을 추가해 주면 되며, 이를 확인하는 방법은 Boolean형의 isParallel()로 확인 가능합니다.
List<String> mmyList = myList.stream().parallel().toList();
Stream<String> tream = myList.parallelStream();
- 순차 처리 시 sequential()을 추가해 주면 됩니다.
Boolean parallelChk = myList.stream().parallel().isParallel(); // true
Stream<String> tream = myList.parallelStream().sequential();
// isParallel() -> false
- 병렬 처리 시 유의 사항
1. 스레드 안전성 고려
- 데이터를 추가하거나 삭제 등 불일치로 이어질 수 있는 상태 작업이나 변경 가능한 고유 데이터 작업은 피하는 것이 좋습니다.
2. 성능 확인
- 병렬 처리는 계산 처리에는 유용할 수 있지만 항상 성능이 좋진 않으므로 유의해야 합니다.
- 데이터 세트가 작거나 계산 집약도가 낮은 작업은 병렬화 오버헤드가 발생할 수 있습니다.
3. 순서 유지 확인
- forEachOrdered(), forEach() 메서드와 같이 순차처리하는 작업에선 동시 실행으로 인한 데이터 순서가 유지되지 못하는 경우가 있을 수 있습니다.
- 아래 메서드들의 사용을 위한 리스트 스트림 객체 생성
List<String> dataList = Stream.of("water","123", "earth", "air", "fire", "fry", "").toList();
- map
- 값들을 map에서 요청한 방법에 맞게 값을 변환해 주는 기능입니다.
- 인자는 람다가 들어가며 아래는 String 클래스의 메서드를 사용하여 각각의 값들을 변환시켜줍니다.
List<String> mappedDataList = dataList.stream().map(String::toUpperCase).toList();
// [WATER, 123, EARTH, AIR, FIRE, FRY, ]
- 직접 생성한 클래스와 메서드도 사용 가능합니다.
class StringTransformer {
public String transformString(String str) {
return str.toUpperCase();
}
}
public void testStream() {
StringTransformer transformer = new StringTransformer();
List<String> stringStream = Stream.of("a", "b", "c");
Stream<String> transformedStream = stringStream.map(transformer::transformString);
}
- flatMap
- 플랫맵을 사용해 여러 구조를 하나로 만들 듯 평면화한다고 생각하면 좋을 것 같습니다.
- 이중 리스트에서 리스트로 각각의 값을 꺼내어 만드는 것보다 더 쉽게 처리가 가능하게 됩니다.
// 객체 생성
List<List<String>> listOflists = Arrays.asList(
Arrays.asList("apple", "banana"),
Arrays.asList("orange", "grape"),
Arrays.asList("watermelon", "pineapple")
);
// [[apple, banana], [orange, grape], [watermelon, pineapple]]
// flatMap 처리
List<String> flattenedStream = listOflists.stream()
.flatMap(List::stream).toList();
// [apple, banana, orange, grape, watermelon, pineapple]
- filter
- 불필요한 값이나 필요한 값을 찾기 위해 필터링해주는 메서드입니다.
List<String> filteredDataList = dataList.stream()
.filter(a -> a.endsWith("e"))
.toList();
// [fire]
// 이 밖에도 사용가능한 기능이 많음
// contains("e") -> e가 포함된 데이터만 호출
// contentEquals("earth") -> earth와 같은 데이터만 호출(equals()도 같은 역할이나 객체 대상)
// isBlank() -> 빈 문자열 또는 공백 문자열을 필터링
// isEmpty() -> 빈 문자열을 필터링
// matches("\\d+") -> 정규식을 넣어 정규식에 맞는 데이터만 필터링
List<String> test = dataList.stream()
.filter(a -> a.regionMatches(0, "fire", 0, 4))
.toList();
// [fire]
// regionMatches(1, 2, 3, 4)
// 1. 람다식 a의 인덱스
// 2. 비교문자열
// 3. 2의 시작 인덱스
// 4. 1과2에 적용할 길이
- sorted
- 정렬 처리를 위한 메서드이며 기본 값은 ASC입니다.
- DESC의 경우 Comparator.reverseOrder()를 이용해 처리해야 합니다.
List<String> sortedDataList = dataList.stream()
.sorted()
.toList();
// [, 123, air, earth, fire, fry, water]
List<String> sortedDataListDesc = dataList.stream()
.sorted(Comparator.reverseOrder())
.toList();
// [water, fry, fire, earth, air, 123, ]
- distinct
- 스트림 객체 또는 리스트 등 컬렉션에서 중복된 값이 있을 경우 이를 제거하고 나머지 값을 리턴합니다.
- 기존 스트림 객체와 새 스트림 객체를 concat으로 합친 데이터로 테스트하였습니다.
List<String> addDataList = Stream.of("cloud", "rain", "electric", "water", "earth", "fire").toList();
List<String> concatDataList = Stream.concat(dataList.stream(), addDataList.stream()).toList();
// [water, 123, earth, air, fire, fry, , cloud, rain, electric, water, earth, fire]
List<String> distinctConcatDataList = Stream.concat(dataList.stream(), addDataList.stream()).distinct().toList();
// [water, 123, earth, air, fire, fry, , cloud, rain, electric]
- skip
- 인자 값으로 넣은 숫자 이전은 스킵하고 그 숫자 자리부터 데이터를 리턴합니다.
List<String> skipDataList = dataList.stream().skip(5).toList();
// [fry, ]
- peek
- 기존 스트림 객체의 값을 로그에 찍어보거나 새로운 객체에 복사할 때 반복처리 됩니다.
- 결과에서 볼 수 있듯 peek -> map 순으로 처리되는 것이 아닌 peek이 전부 처리된 후 map이 처리되게 됩니다.
List<Integer> testList = new ArrayList<>();
List<Integer> intList = Stream.of(1,3,4,5,6).toList();
List<Integer> peekDataList = intList.stream().peek(testList::add).map(n -> n+2).toList();
System.out.println(testList);
// [1, 3, 4, 5, 6]
System.out.println(peekDataList);
// [3, 5, 6, 7, 8]
#. 결과를 도출하기 전 데이터를 가공하여 원하는 값을 도출하기까지 전처리하는 과정으로 손에 익으면 비교적 쉽게 처리가 가능할 것 같습니다.
===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!
===========================================================
'Java' 카테고리의 다른 글
[Java] 로그 구성하기 - Slf4j(logback, Log4j ...) (1) | 2023.12.19 |
---|---|
[Java] Stream API(3) - 결과 도출 (0) | 2023.12.14 |
[Java] Stream API(1) - 스트림 데이터 생성 (0) | 2023.12.12 |
[Java] Zip 파일 생성 후 파일 다운로드(Ajax 이용) (1) | 2023.12.08 |
[Java] 공공데이터 - 공휴일 API 사용하기 (1) | 2023.12.06 |