기록용 블로그

[Java] Stream 이란? 1. 생성하기 본문

개발/JAVA

[Java] Stream 이란? 1. 생성하기

andjane 2023. 4. 29. 02:04

스트림에 대해 좀 더 자세히 알아보고 싶었는데,

마침 좋은 글이 있어 해당 글을 필사하는 느낌으로 정리해본다.

 

* 출처 : https://futurecreator.github.io/2018/08/26/java-8-streams/

https://velog.io/@chamominedev/스트림stream이란-무엇인가

 

스트림(stream)이란 무엇인가?

자바에서는 파일이나 콘솔의 입출력을 직접 다루지 않고, 스트림(stream)이라는 흐름을 통해 다룹니다. 스트림이란 실제의 입력이나 출력이 표현된 데이터의 이상화된 흐름을 의미합니다. 즉, 스

velog.io

 

Java 스트림 Stream (1) 총정리

이번 포스트에서는 Java 8의 스트림(Stream)을 살펴봅니다. 총 두 개의 포스트로, 기본적인 내용을 총정리하는 이번 포스트와 좀 더 고급 내용을 다루는 다음 포스트로 나뉘어져 있습니다. Java 스트

futurecreator.github.io

 


 

Stream

- JAVA8에서 추가된 스트림은 람다를 활용하는 기술이다.

- 스트림이란 곧 '데이터의 흐름'으로, 컬렉션에 저장되어 있는 엘리먼트들을 하나씩 순회하면서 처리할 수 있는 코드패턴이다.

(기존 for, foreach 루프문이 가지고 있던 성능 저하 문제를 개선)

- 배열 또는 컬렉션 인스턴스에 함수 여러 개를 조합해서 원하는 결과를 필터링하고 가공된 결과를 얻을 수 있다. 즉, 배열과 컬렉션을 함수형으로 처리할 수 있다.

- 스트림은 원본 데이터를 변경하지 않는다.

- 또한 내부 반복자를 사용하기 때문에 병렬처리에 용이하다.

 

스트림은 크게 생성 -> 가공 -> 결과 의 내용으로 나눌 수 있다.

해당 포스트에선 생성에 대해 적어보기로 한다.

 

1.  스트림 생성하기

 

* 배열 스트림 : Arrays.stream 메소드 사용

String[] arr = new String[]{"jane", "rose", "kim"};
Stream<String> stream = Arrays.stream(arr);
Stream<String> streamOfArrayPart = Arrays.stream(arr, 1, 3); //idx 1~2 요소

 

* 컬렉션(Collection, List, Set) 스트림 : 인터페이스에 추가된 디폴트 메소드 stream 을 이용

List<String> list = Arrays.asList("jane", "rose", "kim");
Stream<String> stream = list.stream();
Stream<String> parallelStream - list.parallelStream(); // 병렬 처리 스트림

 

* 비어있는 스트림 : 요소가 없을 때 null 대신 사용 가능

public Stream<String> streamOf(List<String> list){
	return list == null || list.isEmpty() ? Stream.empty() : list.stream();
}

 

* Stream.builder() : 빌더를 사용하면 스트림에 직접적으로 원하는 값을 넣을 수 있다. 마지막에 build 메소드로 스트림을 리턴한다.

Stream<String> builderStream = 
	Stream.<String>builder()
    .add("jane").add("kim").add("rose")
    .build();

 

* Stream.generate() : generate 메소드를 이용하면 Supplier<T>에 해당하는 람다로 값을 넣을 수 있다.

Supplier<T>는 인자는 없고 리턴값만 있는 함수형 인터페이스이다. 람다에서 리턴하는 값이 들어간다.

public static<T> Stream<T> generate(Supplier<T> s){...}

 

 

* Stream.iterate() : iterate 메소드를 이용하면 초기값과 해당 값을 다루는 람다를 이용해서 스트림에 들어갈 요소를 만든다. 다음 예제에서는 30이 초기값이고 값이 2씩 증가하는 값들이 들어가게 된다. 즉 요소가 다음 요소의 인풋으로 들어간다. 이 방법도 스트림의 사이즈가 무한하기 때문에 특정 사이즈로 제한해야 한다.

Stream<Integer> iteratedStream = 
  Stream.iterate(30, n -> n + 2).limit(5); // [30, 32, 34, 36, 38]

 

* 기본 타입형 스트림 : 제네릭을 사용하지 않고, 직접적으로 해당 타입의 스트림을 다룰 수 있다. range와 rangeClosed는 범위의 차이 이다. 두 번째 인자인 종료지점이 포함되느냐 안되느냐의 차이이다.

IntStream intStream = IntStream.range(1, 5); // [1, 2, 3, 4]
LongStream longStream = LongStream.rangeClosed(1, 5); // [1, 2, 3, 4, 5]

 

제네릭을 사용하지 않기 때문에 불필요한 오토박싱이 일어나지 않는다. 필요한 경우 boxed 메소드를 이용해서 박싱(boxing)할 수 있다.

(Boxing : 기본 타입 -> Wrapper 클래스)

Stream<Integer> boxedIntStream = IntStream.range(1, 5).boxed();

 

이 외에도 문자열 스트림, 파일 스트림 등이 있다.

 

* 스트림 연결하기 : Stream.concat 메소드를 사용

Stream<String> stream1 = Stream.of("Java", "Scala", "Groovy");
Stream<String> stream2 = Stream.of("Python", "Go", "Swift");
Stream<String> concat = Stream.concat(stream1, stream2);
// [Java, Scala, Groovy, Python, Go, Swift]

 

'개발 > JAVA' 카테고리의 다른 글

[JAVA] String, StringBuffer, StringBuilder의 차이  (0) 2023.05.01