HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🛁
공부기록
/
🩰
스트림을 사용해보자
🩰

스트림을 사용해보자

속성
Jun 13, 2022

스트림 총 정리

스트림이 뭔데

  • 자바8에서 추가한 스트림은 람다를 활용할 수 있는 기술 중 하나입니다. 자바 8 이전에는 배열 또는 컬렉션 인스턴스를 다루는 방법은 for 또는 foreach 문을 돌면서 하나씩 꺼내서 다루는 방법이였습니다.
  • 간단한 경우라면 상관없지만 로직이 복잡해질수록 코드의 양이 많아져 로직이 섞이게 되고 메소드를 나눌 경우 루프를 여러번 도는 경우가 발생합니다.
    • 스트림은 데이터의 흐름입니다. 배열 또는 컬렉션 인스턴스에 함수 여러개를 조합해서 원하는 결과를 필터링하고 가공된 결과를 얻을 수 있습니다. 또한 람다를 이용해서 코드의 양을 줄이고 간결하게 표현할 수 있습니다. 즉 배열과 컬렉션을 함수형으로 처리할 수 있습니다.
  • 스트림의 다른 장점으로 간단하게 병렬처리가 가능하다는 점 입니다. 하나의 작업을 둘 이상의 작업으로 잘게 나눠 동시에 진행하는 것을 병렬 처리라고 합니다.
    • 즉 쓰레드를 이용해 많은 요소들을 빠르게 처리할 수 있습니다.
  • 스트림에 대한 내용은 크게 세가지로 생성 / 가공 / 결과 순으로 있습니다.
    • 전체 > 맵핑 > 필터링 1 > 필터링 2 > 결과만들기 > 결과

생성하기 실습해보기

public class StreamPractice { public static void main(String[] args) throws IOException { // 생성하기 1 - 배열로 생성 String[] arr = new String[]{"A", "B", "C"}; Stream<String> stream = Arrays.stream(arr); Stream<String> streamOfArrayPart = Arrays.stream(arr, 1, 3); // 생성하기 2 - 컬렉션 스트림 // 생성하기 3 - 비어있는 스트림 // 빈 스트림은 요소가 없을 때 null 대신 사용할 수 있다. List<String> list = Arrays.asList("a", "b", "C"); Stream<String> stream1 = list.stream(); Stream<String> stringStream = list.parallelStream(); // 병렬처리 스트림 // 생성하기 4 - Stream.generate() // generate 메소드를 이용하면 Supplier<T>에 해당하는 람다로 값을 넣을 수 있다. // Suplier<T>는 인자는 없고 리턴값만 있는 함수형 인터페이스다. Stream<String> generate = Stream.generate(() -> "get").limit(5); // ["get","get",...] 5개 // 생성하기 5 - Stream.builder() // 빌더를 사용하면 스트림에 직접적으로 원하는 값을 넣을 수 있습니다. 마지막에 build메서드를 통해 스트림을 리턴합니다. Stream<String> streamBuild = Stream.<String>builder() .add("Eric") .add("Elena") .add("Java") .build(); // 생성하기 6 - Stream.iterate() // 메소드를 이용하면 초기값과 해당 값을 이루는 람다를 이용해서 스트림에 들어갈 요소를 만듭니다. // 다음 예제에는 30이 초기값이고 2씩 증가하는 값들이 들어가게 된다. Stream<Integer> iteratedStream = Stream.iterate(30, n -> n + 2).limit(5); // 기본 타입형 스트림 // 제네릭을 사용하면 리스트나 배열을 이용해서 기본 타입(int, long, double) 스트림을 생성할 수 있습니다. IntStream intStream = IntStream.range(1, 5);// [1,2,3,4] IntStream intStream1 = IntStream.rangeClosed(1, 5); // [1,2,3,4,5] // 제네릭을 사용하지 않기 때문에 불필요한 오토박싱이 일어나지 않습니다. 필요한 경우 boxed 메소드를 이용해서 박싱할 수 있습니다. Stream<Integer> boxedIntStream = IntStream.range(1, 5).boxed(); // 자바 8의 랜덤 클래스는 난수를 가지고 세가지 타입의 스트림(Int, Long, Double)을 만들 수 있습니다. 쉽게 난수 스트림을 생성해서 여러가지 후속 작업을 취할 수 있어 유용합니다. DoubleStream doubles = new Random().doubles(3); // 난수 3개 발생 // 문자열 스트링 // 스트링을 사용해서 스트림을 생성할 수 잇습니다. 다음은 스트링의 각 문자를 IntStream으로 변환하는 예제입니다. char는 문자이지만 본질적으로는 숫자이기 때문에 가능합니다. IntStream charsStream = "Stream".chars(); // [83,116,114,101,97,109] // 정규표현식을 이용해서 문자열을 자르고 각 요소들을 스트림으로 만드는 예제 Stream<String> stringStream1 = Pattern.compile(", ").splitAsStream("Eric, Elena, Java"); // 파일 스트림 // 자바 NIO의 파일클래스의 lines 메소드는 해당 파일의 각 라인을 스트링 타입의 스트림으로 만들어줍니다. Files.lines(Paths.get("file.txt"), Charset.forName("UTF-8")); // 병렬 스트림 // 스트림 생성 시 사용하는 스트림 대신 parallelStream 메소드를 사용해서 병렬 스트림을 쉽게 생성할 수 있습니다. // 내부적으로는 쓰레드를 처리하기 위해 자바 7부터 도입된 Fork/Join Framework를 사용합니다. List<Integer> integers = Arrays.asList(1, 2, 3); Stream<Integer> parallelStream = integers.parallelStream(); // 병렬 여부 확인 boolean isParallel = parallelStream.isParallel(); // 따라서 다음 코드는 각 작업을 쓰레드를 이용해 병렬 처리됩니다. parallelStream .map(integer -> integer * 10) .anyMatch(amount -> amount > 20); // 배열을 이용해서 병렬스트림을 생성하는 경우 Arrays.stream(new int[]{1, 2, 3}).parallel(); // 컬렉션과 배열이 아닌 경우는 다음과 같이 parallel 메소드를 이용해서 처리합니다. IntStream parallel = IntStream.range(1, 150).parallel(); parallel.isParallel(); // 다시 시퀀셜 모드로 돌리고 싶다면 sequential 메소드를 사용합니다 IntStream sequential = parallel.sequential(); boolean parallel1 = sequential.isParallel(); // 스트림 가공하기 // 스트림 concat 메소드를 이용해 두 개의 스트림을 연결해서 새로운 스트림을 만들어 낼 수 있습니다. Stream<String> stream_1 = Stream.of("Java", "Scala", "Groovy"); Stream<String> stream_2 = Stream.of("python", "C++", "C#"); Stream<String> concat = Stream.concat(stream_1, stream_2); } }

스트림 가공하기

  • 전체요소 중 다음과 같은 API를 이용해서 내가 원하는 것만 뽑아낼 수 있습니다. 이러한 가공 단계를 중간작업이라고 하는데 이러한 작업은 스트림을 리턴하기 때문에 여러 작업을 이어 붙일 수 있습니다.
아래의 예제는 List names = Arrays.asList(“Eric”,“Elena”,“Java”) 리스트를 대상으로합니다.