250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- spring
- MessageQueue
- sqlserver
- 스트림
- JPA
- 보안
- apache.poi
- 자바8
- 제이쿼리그리드
- java
- docker
- 엑셀 업로드
- mom
- stream api
- Stream
- ci/cd
- rabbitmq
- 그리드
- poi
- 자동배포
- ORM
- mssql
- jqGrid
- 대용량 업로드
- Javascript
- DevOps
- QueryDSL
- Jenkins
- JQuery
- 자동빌드
Archives
- Today
- Total
개발 메모장
[Java] Stream API(1) - 스트림 데이터 생성 본문
728x90
#. 서비스 중인 프로젝트가 기존 Java 7이었고 알다시피 Java 7은 22년 7월 29일부로 수명이 종료됐습니다.
#. 수명 종료로 인한 업데이트 및 보안 패치 미적용으로 자바 버전을 8로 올려야 했습니다.
#. 이에 따라 Java 8부터 추가된 Stream API에 대해 알아보려고 합니다.
#. Stream API는 크게 보면 데이터 생성, 데이터처리, 결과도출 방식으로 메서드를 호출하는데 데이터 생성에 대한 부분을 먼저 살펴보려 합니다.
- Stream 사용의 장점
- 코드를 간결히 작성할 수 있습니다.
- 병렬 처리와 같은 기술로 처리 속도를 높일 수 있습니다.
- Stream 내부적으로 반복된 작업을 처리하여 편합니다.
- 여러 종류의 컬렉션들을 Stream으로 변환하여 처리할 수 있어 데이터 처리에 일관성이 생깁니다.
- 한 메서드를 통해 연결된 여러 작업을 한 번에, 원활히 구성할 수 있게 합니다.(메서드 체이닝)
- Stream 사용의 단점
- 스트림 초기화, 메서드 호출 등의 비용으로 성능 오버헤드가 발생해 기존 방식보다 성능이 떨어지는 경우가 있습니다.
- 코드가 추상화되기 때문에 실수할 가능성이 있습니다.
- 일반적으로 순차처리 되는 소스보다 디버깅이 어렵습니다.
- 스트림은 일회성이라 여러 작업을 수행해야 할 때 스트림을 다시 생성해야 할 수 있고 이로 인한 비용이 발생할 수 있습니다.
- Stream 사용 전후 비교
// Stream 사용 전
String[] strArr = {"test1", "test2", "test3"};
List<String> testList = Arrays.asList(strArr);
Collections.sort(nameList);
for (String str : testList) {
System.out.println(str);
}
// Stream 사용 후
String[] strArr = {"test1", "test2", "test3"};
List<String> testList = Arrays.asList(strArr);
Stream<String> testListStream = testList.stream();
testListStream.sorted().forEach(System.out::println);
- Stream 인스턴스 생성
- 스트림 데이터로 변환하기 위한 전처리라고 보면 좋을 것 같습니다.
- 데이터는 스트림을 이용해 처리한 뒤 리스트형으로 변환하여 찍은 결과를 보여드릴 예정입니다.
- 배열, 컬렉션, 스트림 of 등을 통해 만들어진 객체를 변환하는 방법은 아래와 같습니다.
- 스트림 메서드 데이터 처리
- Stream.of를 이용해 데이터를 넣어줍니다.
public static void streamTest() {
Stream<String> streamData = Stream.of("bird", "fish", "plant");
List<String> streamDataList = streamData.collect(Collectors.toList());
// [bird, fish, plant]
}
- 배열 데이터 처리
- 배열 데이터는 스트림으로 처리가 불가하므로 List로 변환 후 처리합니다.
public static void streamTest() {
String[] strArr = {"seoul", "incheon", "bucheon", "suwon", "ansan"};
List<String> strArrList = Arrays.asList(strArr);
List<String> strArrStreamList = strArrList.stream()
.filter(a -> a.startsWith("i") || a.startsWith("a"))
.map(String::toUpperCase)
.collect(Collectors.toList());
// [INCHEON, ANSAN]
}
- 리스트 데이터 처리
public static void streamTest() {
List<String> myList = Arrays.asList("january", "march", "july", "december");
List<String> filteredList = myList.stream()
.filter(a -> a.startsWith("j"))
.map(String::toUpperCase)
.collect(Collectors.toList());
// [JANUARY, JULY]
}
- 셋 데이터 처리
public static void streamTest() {
Set<String> mySet = new HashSet<>();
mySet.add("orange");
mySet.add("pear");
mySet.add("kiwi");
Set<String> startWithOList = mySet.stream()
.filter(o -> o.startsWith("o"))
.collect(Collectors.toSet());
// [orange]
}
- 맵 데이터 처리
public static void streamTest() {
Map<String, Object> myMap = new HashMap<>();
myMap.put("animal", "lion");
myMap.put("star", "orion");
myMap.put("veg", "carrot");
Map<String, Object> mapStream = myMap.entrySet().stream()
.filter(a -> a.getValue().toString().startsWith("o"))
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()));
// {star=orion}
}
- 타입형 Stream 인스턴스 생성
- 변수 타입으로 많이 접해본 int, Long, Double, chars 등의 스트림 생성 방법입니다.
- IntStream
IntStream is = IntStream.rangeClosed(20, 30);
int[] arrayIs = is.toArray();
System.out.println(Arrays.toString(arrayIs));
// [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
- 위처럼 IntStream을 사용하지 않으면 아래처럼 비교적 복잡한 방법을 사용해야 합니다.(Long, Double도 동일)
int startNum = 20;
int endNum = 30;
List<Integer> integerStream = Stream.iterate(startNum, i -> i <= endNum, i -> i + 1)
.limit(endNum - startNum + 1)
.collect(Collectors.toList());
System.out.println(integerStream);
// [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
- LongStream
LongStream ls = LongStream.range(9, 12);
long[] arrayLs = ls.toArray();
System.out.println(Arrays.toString(arrayLs));
// [9, 10, 11]
- DoubleStream
DoubleStream ds = DoubleStream.iterate(1, n -> n + 1).limit(10);
double[] arrayDs = ds.toArray();
System.out.println(Arrays.toString(arrayDs));
// [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
- iterate()
- iterate() 인자 값에 리턴 계산식을 추가하여 값을 처리합니다.
- limit 메서드를 사용해 반복될 횟수를 지정해 주어야 합니다.
- 만약 지정하지 않으면 무한 반복되어 PC 소리가 커지면서 OOM이 발생하게 됩니다.
Stream<Integer> iter = Stream.iterate(5, n -> n + 2).limit(10);
System.out.println(iter.toList());
// [5, 7, 9, 11, 13, 15, 17, 19, 21, 23]
- generate()
- generate는 람다식에 넣은 값을 limit의 인자만큼 추가해 줍니다.
- limit에 값을 정하지 않으면 무한으로 생성하므로 OOM이 발생합니다.
- 람다식은 Supplier<? extends String> s와 같이 들어가고 이는 인자 없이 리턴값만 정해주면 됩니다.
Stream<String> generate = Stream.generate(() -> "test").limit(3);
System.out.println(generate.toList());
// [test, test, test]
- concat()
- 2개 이상의 스트림으로 생성한 값을 한 스트림으로 합치고자 할 때 사용합니다.
- 기본적으로 중복 허용되나 distinct()를 이용해 중복 제거를 할 수 있습니다.
- 인자로 들어가는 객체가 스트림이 아닐 경우 스트림 객체로 파싱 해줘야 합니다.( .stream() )
Stream<String> concat1 = Stream.of("test", "test1");
Stream<String> concat2 = Stream.of("test3", "test1");
List<String> concatList = Stream.concat(concat1, concat2).distinct().toList();
System.out.println(concatList);
// [test, test1, test3]
#. 이 밖에도 더 많은 메서드들이 있으나 하나하나 보기엔 조금 무리가 있고 기본적인 흐름은 위 정리한 바와 같습니다.
#. 자바 7을 사용했다 보니 조금 어색하고 눈에 잘 안 들어오긴 하나 익숙해지면 개발적인 부분이나 가독성 부분도 좋게 느껴질 것 같습니다.
===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!
===========================================================
728x90
'Java' 카테고리의 다른 글
[Java] Stream API(3) - 결과 도출 (0) | 2023.12.14 |
---|---|
[Java] Stream API(2) - 스트림 데이터 가공 (0) | 2023.12.13 |
[Java] Zip 파일 생성 후 파일 다운로드(Ajax 이용) (1) | 2023.12.08 |
[Java] 공공데이터 - 공휴일 API 사용하기 (1) | 2023.12.06 |
[Java] OOM과 GC (Out of Memory Error와 가비지 컬렉터) (1) | 2023.12.04 |