본문 바로가기

프로그래밍/Java

Java8 변경사항 - 스트림API 특징과 생성

스트림이란?

자바 8에서 추가된 스트림 API에 대해 알아봅시다.
기존에 자바에서는 수많은 데이터를 다룰 떄 컬렉션이나 배열을 사용하였고 이 데이터에 접근하기 위해 for문과 Iterator를 사용하였습니다. 그러나 이렇게 작성된 코드는 길고 가독성도 떨어지며 재사용의 거의 불가능합니다.
이러한 문제를 해결하기 위해 자바8 부터 스트림 API가 도입되었습니다.
스트림은 데이터를 추상화하여 하루며 배열이나 컬렉션 뿐만 아니라 파일에 저장된 데이터도 모두 같은 방법으로 다룰수 있도록 해줍니다.

스트림 API의 특징

  1. 스트림은 작업을 내부 반복으로 처리한다.

     for(String str : list){
      System.out.println(str);
     }
     //use stream
     stream.forEach(System.out::println);
  2. 스트림은 일회용이다.
    스트림은 Iterator가 재사용할수 없는 것처럼 사용할 수 없으며 필요시 스트림을 다시 생성해야 한다.

     stream1.sorted().forEach(System.out::println);
     int num = stream1.count(); // 불가능
  3. 스트림은 원본데이터를 변경하지 않는다.
    스트림은 데이터를 읽기만할 뿐 원본데이터를 변경하지 않기 때문에 필요할떄는 정렬된 결과를 컬렉션이나 배열에 담아서 반환해야한다.

     List<String> sortedResult = stream1.sorted().collect(Collectors.toList());
  4. 지연연산을 통해 성능을 최적화한다.
    스트림은 최종 연산이 수행되기 전까지는 중간연산이 수행되지 않는다. 최종연산이 수행되어야 중간 연산을 거쳐 최종연산에서 소모된다.

  5. 스트림은 parallel() 메소드를 통해 손쉽게 병렬 처리를 할 수 있다.

     int sum = stream1.parallel()    //병렬 스트림으로 전환
                  .mapToInt(s -> s.length())
                  .sum();

스트림 만들기

스트림의 소스가 될수 있는 대상은 아래와 같다.

  1. 컬렉션
  2. 배열
  3. 특정 범위의 연속된 정수
  4. 난수
  5. 람다 표현식
  6. 파일
  7. 빈 스트림

1. 컬렉션

자바에서 제공하는 모든 컬렉션의 가장 상위의 조상인 Collection에 Stream이 정의되어 있다.
따라서 collection 인터페이스를 구현한 모든 List와 Set 구현한 컬렉션 클래스에서 스트림을 생성할 수 있다.

ArrayList<Integer> list = Arrays.asList(1,2,3,4);
Stream<Integer> stream = list.stream(); //스트림 생성
stream.forEach(System.out::println);    //스트림 요소 출력

2. 배열

배열에 스트림을 생성하기위해 Arrays클래스에 다양한 메서드가 정의되어 있다.
기본형인 int, long, double은 별도로 정의 되어있다.

Stream<String> stream1 = Arrays.stream(new String[]{"a","b","c"});
IntStream.of(1,2,3,4,5);

3. 특정 범위의 연속된 정수

IntStream과 LongStream 인터페이스에는 range(), rangeClosed()메소드가 정의되어 있다.
range(): 시작정수를 포함하지만 마지막 정수를 포함하지 않고 스트림 생성
rangeClosed(): 시작과 끝을 포함하는 스트림 생성

IntStream stream1 = IntStream.range(1, 4);  // 1 2 3
IntStream stream2 = IntStream.rangeClosed(1,4); // 1 2 3 4

4. 난수

난수를 생성하는데 사용하는 Random클래스에 ints(), longs(), doubles()메서드가 정의되어 있다.
이 메서드들은 반환하는 스트림의 크기가 정해지지 않은 무한 스트림 이므로 limit을 사용하여 스트림의 크기를 제한해야 한다.

IntStream stream = new Random().ints();
stream.limit(5).forEach(System.out::println);   // 5개의 요소만 출력

5. 람다 표현식

Stream 클래스의 iterate()와 generate()는 람다식을 매개변수로 받아서 람다식에 의해 계산된 값을 무한스트림으로 생성한다.
iterate(): seed로 명시된 값을 람다식에 사용하여 반환된 값을 다시 시드로 사용하는 무한 스트림 생성
generate(): 매개변수가 없는 람다식을 사용하여 반환된 값으로 무한 스트림 생성

IntStream stream = Stream.iterate(2, n-> n+2); //2 4 6 8 ...
Stream<Double> stream2 = Stream2.generate(Math::random);

6. 파일

파일의 한 줄을 요소로 하는 스트림을 생성하는 lines()메서드와 디렉토리에 있는 파일의 목록을 요소로 하는 스트림을 생성하는 list()메서드 등이 있다.

String<String> stream = Files.lines(Paths.get("file.txt"));

7. 빈 스트림

empty()메서드를 사용하여 아무런 요소도 없는 빈 스트림을 생성할 수 있다.

Stream stream = Stream.empty();
long count = stream.count();    //value: 0

'프로그래밍 > Java' 카테고리의 다른 글

java8 - time  (0) 2020.03.10
java8 - Optional  (0) 2020.02.23
java8 변경사항 - 스트림API 최종연산  (0) 2020.02.07
Java8 변경사항 - 스트림API 중간연산  (0) 2020.02.07
Java8 변경사항 - 람다 표현식  (0) 2020.01.29