[Java] 자바 Stream

AlBan·2021년 5월 16일
1

JAVA

목록 보기
1/1

Stream?

JDK 8에서 추가된 API로 데이터 소스를 추상화 하고, 데이터를 다루는데 자주 사용되는 메서드들을 정의해 놓았다.

데이터 소스의 추상화란 데이터 소스가 무엇이든 같은 방식으로 다룰 수 있게 하는 것을 의미한다.

// stream 사용 전
String[] stringArray = {"naver","kakao","google","toss"};

List<String> stringList = Arrays.asList(stringArray);

Arrays.sort(stringArray);
Collections.sort(stringList);

for(String str : stringArray){
	System.out.println(str);
}
for(String str : stringList){
	System.out.println(str);
}

// stream 사용 후
Stream<String> arrayStream = stringArray.stream();
Stream<String> listStream = Arrays.stream(stringArray);

arrayStream.sorted().forEach(System.opt::println);
listStream.sorted().forEach(System.opt::println);

Stream의 특징

  • 스트림은 데이터 소스를 변경하지 않는다.
    • 스트림은 데이터 소스로부터 데이터를 읽기만 할뿐, 데이터 소스를 변경하지 않는다. 필요시에는 결과를 컬렉션이나 배열에 담아 반환할 수 있다.
      List<String> sortedList = listStream.sorted().collect(Collections.toList());
      
  • 스트림은 일회용이다.
    • 스트림은 Iterator처럼 일회용이다. 스트림은 한번 사용하고 나면, 다시 사용할 수 없다. 필요하다면 스트림을 다시 생성해서 사용해야 한다.
    listStream.sorted().forEach(System.out::println);
  • 스트림은 작업을 내부 반복으로 처리한다.
    • 스트림을 이용한 작업이 간결할 수 있는 이유중 하나가 바로, 내부 반복. 내부반복은 반복문을 메서드의 내부에 숨길 수 있다는 것을 의미한다.

Stream의 핵심 메서드

map()

  • 스트림 요소에 저장된 값에 일정한 처리를 할 수 있는 메서드. 매개변수로 일정한 처리를 하는 메서드를 넘겨주어야 하며, 람다식 또한 사용이 가능하다.
// 요소들을 모두 대문자로 변경
listStream.map(String::toUpperCase).forEach(System.out::println);

flatMap()

  • 스트림의 요소가 배열이거나 map()의 연산결과가 배열인 경우, 즉 스트림의 타입이 Stream<T[]>인 경우에 사용하여 Stream<T>의 형태로 변환한다.
// stream의 타입이 T[] 형태
Stream<String[]> arrStream = Stream.of(new String[] {"a", "b", "c"}), new String[] {"d", "e", "f"});

filter()

  • filter는 이름과 같이 스트림의 각 요소를 주어진 메서드에 맞게 걸러내주는 역할을 한다.
// 첫글자가 n인 요소만 골라서 출력
Stream<String> strStream = Arrays.asList(new String[]{"naver", "kakao", "google", "toss"}).stream();
strStream.filter(str->str.toCharArray()[0] - 'n' == 0).forEach(System.out::println);	// naver

collect()

  • 이름에서 알 수 있듯이 스트림의 모든 요소를 모아주는 역할을 한다. 스트림 요소를 모두 모은 이후 List로 변환하는 등의 처리를 할 수 있다.
    그래서 스트림의 적용 결과가 계속해서 필요하게 될경우 collect()를 사용하여 변수에 할당할 수 있다.
// 스트림의 요소를 모아 List<String>의 형태로 반환해준다.
List<String> sortedList = listStream.sorted().collect(Collections.toList());

reduce()

  • 스트림의 요소를 줄여나가며 연산을 수행하고 최종결과를 반환한다. 처음 두 요소를 가지고 연산을 한 다음, 그 다음 요소와 다시 연산을 한다. 이 과정에서 스트림의 요소를 하나씩 소모하고, 스트림의 모든 요소를 소모하면 최종결과를 반환한다.
List<Integer> list = new ArrayList<>(Arrays.asList(1, 12, 15, 7, 8, 10, 88));
    System.out.println(list.stream().reduce(Integer::max)); // 88

마무리

스트림을 사용하면 반복문을 여러번 사용하지 않고도 손쉽게 Iterable한 요소들에 처리를 할 수 있다. 그러니 생각날 때 사용하는 것도 나쁘지 않을 것 같다.

profile
[Spring, React를 공부하는 끈질긴 개발자 지망생] 잊어버리지 않도록! 정리 또 정리!

0개의 댓글