Stream
자바에서 데이터를 저장하기 위해 배열, 리스트, 맵 등 다양한 방식을 사용한다. 그런데 이런 데이터들을 이용하기 위해 for문, iterator을 사용할때 코드가 굉장히 길어지거나 가독성이 떨어지는 경우가 있다.
이런 문제를 해결할 수 있는 것이 스트림이다. 스트림은 기본적으로 데이터를 담고있는 자료형(배열,리스트..)을 사용할때 자주 사용할 법한 메소드들을 가지고 있다.
우선 예를 들어보자 우리가 배열안의 요소들을 출력하는 방식이다.
int[] arr = {1,2,3,4,5};
for(Integer i:arr){
System.out.println(i);
}
이런 간단하면서도 아주 많이 쓰이는 상황을 메소드로 만들어 아래처럼 사용할 수 있다.
public void printArr(int[] arr){
for(Integer i:arr){
System.out.println(i);
}
}
그런데 위의 메소드는 배열의 요소를 하나씩 접근하면서 단순히 출력만을 해주는데, 배열의 요소에 하나씩 접근해서 무언가 작을 을 하는 메소드또한 우리는 매우 많이 만들어 보았을 것이다.
그때마다 기본적인 틀을 위의 메소드에서 for문 안의 내용만 다를뿐 모두 같다.
이럴때 우리는 스트림과 람다를 이용해서 메소드를 따로 정의하지 않고 필요한 것을 만들 수 있다.
String[] strArr ={"A","B","C"};
Stream<String> stream = Arrays.stream(strArr);
stream.forEach(System.out::println);
위의 코드는 스트림을 이용하여 배열의 요소에 하나씩 접근해 출력을 하는 코드이다. forEach안의 람다식을 바꾸면 출력이 아닌 다른 용도로 언제든 바꿀 수 있다.
이렇게 하면 데이터를 저장한 자료형에 하나씩 접근해서 무언가를 하는 메소드를 일일이 정의할 필요없이 필요한곳에 짧은 코드로 만들 수 있다.
한가지 예를 더 보자
이번에는 데이터를 정렬을 하는 스트림이다. 스트림으로 정렬을 하기 위해서는 sorted메소드를 사용하면 된다.
String[] strArr ={"D","B","C"};
Stream<String> stream = Arrays.stream(strArr);
stream.sorted().forEach(System.out::println);
//B
//C
//D
위의 코드를 보면 forEach전에 sorted메소드를 사용해서 미리 정렬을 했다.
보다싶이 스트림의 몇몇 메소드는 체이닝이 가능하게끔 반환이 스트림으로 되어있다. 반대로 몇몇은 반환이 없거나 특정 자료형이다.
위의 차이점은 반환이 스트림으로 되어있는 메소드는 중간 메소드로서 최종 결과로 사용되는 것이 아니라 중간단계로 사용되고 반환이 없거나 스트림이 아닌 메소드는 최종 결과물을 만들어낸다. 또한 최종으로 사용되는 메소드를 호출하면 해당 스트림은 소멸한다. 즉, 스트림은 일회용이다.
그리고 중간 메소드는 최종 메소드가 호출되기 전까지는 실행을 하지않고 대기하다 최종 메소드가 호출되고 나서 호출이 된다.
다음으로 중요한것은 스트림은 데이터 자체를 변경하지 않는 다는 것이다. 위의 코드에서 스트림으로 정렬을 하였는데 strArr 자체는 정렬되지 않고 스트림에서 복사를 해서 정렬을 한다음 사용한다.
다음으로는 스트림을 생성하는 방법을 보자
우선 스트림은 당연하게도 배열과 컬렉션 두가지의 자료형을 사용할때 사용하니 두가지에 각각 스트림을 만드는 메소드가 있다.
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
Stream<Integer> integerStream = list.stream();
String[] strArr ={"D","B","C"};
Stream<String> stream = Arrays.stream(strArr);
위에 두가지 방식을 코드로 보여줬다.
하지만 여기서 람다때와 비슷한 문제가 있다. 바로 wrapping이다 기본 자료형같은 경우는 람다와 마찬가지로 전용 스트림이 있다. 여기에는 IntStream,LongSteam,DoubleStream이 있다.
마지막으로 스트림의 메소드들을 간략하게 정리한것을 표로 보겠다.
중간
최종