개발공부/자바

[자바] stream()이 무엇일까?(1)

장아장 2022. 11. 1. 19:32

알고리즘을 풀다보면 HashMap을 다른 구조로 전환해야 하는 경우가 있다. 이를 위해서 for문을 돌리고, 이를 다시 List나 Array에 담아서 전환한 후에 이를 리턴해야 하는 수고스러움이 있다. 

 

메서드를 분리함에 있어 이 때문에 새로운 for문 메서드를 만들고, 이 안에서 List에 담거나, 혹은 담는 조건이 있다면 조건문 메서드를 따로 만들어서 담는 방식을 사용했었다. 

 

그러다가, stream()방식을 찾게 되었다. 이러한 수고스러움을 줄여주고, 조건을 하나의 문장에서 구현할 수 있고, 심지어 type을 변경시켜줄 수도 있다. (너무 편하다!)

 

이러한 stream()이 어떻게 되어있는지 찾아보았다. 

https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html

 

Stream (Java Platform SE 8 )

A sequence of elements supporting sequential and parallel aggregate operations. The following example illustrates an aggregate operation using Stream and IntStream: int sum = widgets.stream() .filter(w -> w.getColor() == RED) .mapToInt(w -> w.getWeight())

docs.oracle.com

(찾아보는건 역시 Oracle이 제일 편해!!)\

 

간단하게 구조부터를 한번 확인해보고 세부적인 기능들을 봐야할 것 같다. 

구조를 보면, Source, Zero or More Intermediate Operations, Terminal Operation으로 나누어져 있다고 한다. 

  • Source : 말 그대로 사용할 구조를 말한다고 이해했다. 예를 들어, HashMap<String, Integer>형 변수를 가져온다면, 이를 변수.EntrySet.stream()으로 불러오게 된다.
  • Intermediate Operations : 존재하지 않을 수 있으며, 스트림의 데이터에 조건을 걸거나, 순서를 조정하거나 등의 조작을 하며 스트림의 타입을 다른 타입으로 변경시켜준다.
  • Terminal Operation : count(), forEach() 같은 메서드를 통해 원하는 결과를 리턴하거나 그로 인해 발생하는 다른 값들을 구하게 해 준다.  

이 일련의 과정을 Oracle에서는 Stream pipeline에 존재하는 과정들이라고 한다. 

이 pipeline의 연산들은 

  1. 스트림을 적용시키는 Source의 데이터에 변화를 주지 않는다. 
  2. 스트림의 결과는 stateless이다. 즉, 인스턴스 변수가 존재하지 않는다. 

 

이러한 특이점이 있었다. 

 

그러면 이걸 보고서 어떻게 써먹었을까?

private static List<String> sortNameByScore(){
    return scoreToUser.entrySet().stream()
            .sorted(Map.Entry.comparingByKey())
            .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
            .map(Map.Entry::getKey)
            .limit(5)
            .collect(Collectors.toList());
}

요런식으로 써먹었다. 

여기서 scoreToUser은 HashMap<String, Integer> 형 변수이다. HashMap을 EntrySet형으로 캐스팅하고, 이를 stream()을 이용해서 정렬하기 시작했다. 

Intermediate Operation으로 sorted, map, limit을 사용하고, 마지막에 terminal operation으로 collect를 사용했다. 

 

stream을 쓰지 않았다면,

  1. HashMap의 keySet을 List로 담는다. 
  2. List를 오름차순으로 정렬한다. 
  3. List의 value를 보고, value를 내림차순으로 정렬한다. (이렇게 하면, value가 같은 key들은 오름차순이 유지된다. )

이를 하나하나 메소드화 시켰어야 한다. 또한, 반복문과 해시맵에서 값을 가져오기를 계속해야한다. 이를 조금 더 보기 편하고, 쓰기 쉽게 정리해줄 수 있다는 장점이 있는 것 같다. 

 

어떤 기능들이 있는지는 다음에 써야할 것 같다. 나도 공부하고 써야지