Collection 과 Stream

Dayon·2024년 5월 15일
0

CS공부

목록 보기
17/18

Collection이란?

  • Collection
    • 데이터를 수집하기 위한 집합

    • 집계된 데이터를 저장, 검색, 조작, 전달하는 데 사용


  • Collection Framework
    • 데이터를 수집하여 저장하기 위해 사용할 수 있도록 정의해 놓은 클래스들을 표준화한 설계
    • 데이터 그룹을 다루고 표현하기 위한 단일화 된 구조


  • Collection에는 List, Map, Set, Stack, Queue 등이 있다.
  • 컬렉션은 각 인터페이스와 클래스들이 계층 구조로 이뤄져있다.

인터페이스구현 클래스자료구조의 특징
SetHashSet, TreeSet순서를 유지하지 않는 데이터의 집합으로 데이터의 중복을 허용하지 않는다.
ListLinkedList, Vector, ArrayList순서가 있는 데이터의 집합으로 데이터의 중복을 허용한다.
QueueLinkedList, PriorityQueue먼저 들어간 자료가 먼저 나오는 구조 FIFO(First In FIrst Out)
MapHashtable, HashMap, TreeMap키(Key), 값(Value)의 쌍으로 이루어진 데이터의 집합으로, 순서는 유지되지 않으며 키(Key)의 중복을 허용하지 않으나 값(Value)의 중복은 허용한다.

왜 Collection을 사용하는 것일까?

  • 자료 구조를 자바로 반영해둔 프레임워크로 제공을 하기에 자료구조 알고리즘을 고민하고, 직접 구현하지 않아도 된다.
  • 데이터 구조와 알고리즘에 대해 고성능, 고품질 구현을 제공한다.
  • 배열과 달리 크기를 유연하게 변경 가능하고, 삽입 삭제가 편리하다. 따라서 객체의 수를 상황에 맞게 조절할 수 있기에 공간의 효율성이 높아진다.

JAVA 의 컬렉션 프레임워크라면 대표적으로 List, Set, Map으로 알고 있는데, 위 사진을 보면 알수 있듯 List와 Set은 컬렉션이라는 인터페이스를 상속받지만 Map은 아니다.


Map은 왜 없는가 ?

  • JAVA의 공식문서에 따르면 “맵은 컬렉션이 아니고, 컬렉션도 맵이 아니다” 라고 한다.
  • Map이 Collection 이라면 Map의 구조를 봤을 때 합리적인 답은 'key-value 쌍'이 Map의 Element가 될 것이다. 하지만 이건 Map의 매우 제한적인 추상화를 제공하게 된다.
  • 주어진 Key에 매핑 되는 Value를 찾아 올 수 없고, Key만으로 key-value 쌍을 지울 수도 없다.
  • 억지로 Map과 Collection을 연관관계로 묶는다면 부자연스러운 인터페이스가 만들어지기에 제공하지 않는다.



Stream 이란?

Stream은 데이터의 흐름이다.

  • 데이터 소스에서 데이터를 읽고, 처리하고, 출력하는 연산을 수행하는데 사용된다.

  • 컬렉션, 배열 또는 I/O 자원 등 다양한 소스에서 데이터를 다루는 일관된 방법을 제공한다.

  • 자바 8에서 추가한 스트림(Streams)은 람다를 활용할 수 있는 기술 중 하나.

  • 자바 8 이전에는 배열 또는 컬렉션 인스턴스를 다루는 방법은 for 또는 foreach 문을 돌면서 요소 하나씩을 꺼내서 다루는 방법을 사용했다.


장점

  • 람다를 이용해 코드의 양을 줄이고 간결한 표현이 가능하다. ⇒ 컬렉션을 함수형으로 처리할 수 있다
  • 병렬처리가 가능하다.

순서

  1. 생성하기 : Stream 인스턴스 생성.
  2. 가공하기 : 필터링(filtering) 및 맵핑(mapping) 등 원하는 결과를 만들어가는 중간 작업(intermediate operations).
  3. 결과 만들기 : 최종적으로 결과를 만들어내는 작업 (terminal operations)
    • Calculating - 최소, 최대, 합, 평듄 등 기본형 타입 계산 가능
    • Reduction - 스트림에 있는 여러 요소의 총합 , accumulator, identity, combiner
    • Collecting - 리스트로 반환(Collectors.toList()), 하나의 스트링으로 이어붙이기 (Collectors.joining()), Collectors.averageingInt(), Collectors.summingInt() …

특징

  1. 선언형 프로그래밍 방식: 코드를 작성할 때 데이터를 어떻게 처리할지에 대해 명시할 수 있으며, 구체적인 구현 방법은 숨겨짐.

    → 간결하고 가독성있는 코드

  2. 내부 반복(internal iteration): 내부 반복을 사용하여 요소를 처리

  3. 지연 연산(lazy evaluation):

    스트림은 중간 연산(intermediate operations)과 최종 연산(terminal operations)으로 구성.

    중간 연산은 스트림을 리턴하며, 최종 연산은 스트림을 사용해 결과를 리턴합니다.

    이때, 중간 연산은 지연 연산이 적용되어 최종 연산이 호출되기 전까지 실제로 처리가 이루어지지 않는다.

    지연연산 : 결과값이 필요할때까지 계산을 늦추는 기법




코드에서 찾아보기

상품 목록 불러오는 API

1. 생성하기 : Stream 인스턴스 생성.

  • 컬렉션의 경우 Interface에 있는 defalut 메소드 stream() 을 이용해 Stream 인스턴스를 생성하였다.

  • ⇒ Stream 파이프라인의 시작

2. 가공하기 : 필터링(filtering) 및 맵핑(mapping) 등 원하는 결과를 만들어가는 중간 작업(intermediate operations).

  • map() 메서드는 스트림 내의 요소들을 특정 값으로 변환해준다. (이때, 람다를 인자로 받는다)
 <R> Stream<R> map(Function<? super T, ? extends R> mapper);
  • .map(productMapper::fromListEntity)
      요소 내 들어있는 Products 개체의 정보들을 꺼내온다. 
      

fromListEntity ⇒ 각 Product 객체는 ProductPreViewDto 객체로 매핑한다.

3. 결과 만들기 : 최종적으로 결과를 만들어내는 작업

.collect(Collectors.toList()) :

  • collect() 메서드는 스트림의 요소를 수집하여 새로운 컬렉션으로 반환

  • Collectors.toList() 스트림의 모든 요소를 리스트에 추가하고, 그 결과로 리스트를 반환




각 페이지의 상품 목록을 처리하기 위해 Java의 List를 사용

toList()


⇒ 스트림에서 요소를 수집하여 리스트로 변환하는 toList() 컬렉터

  • 입력 요소를 발생 순서대로 새 List에 누적하는 Collector를 반환한다.
  • toList() 메서드 : List의 type, 변경 가능성, 직렬화 가능성, 스레드 안전성에 대해 보장을 하지 않는다.
  • 수 있는 것
    1. ArrayList::new로 새로운 ArrayList 인스턴스를 생성
    2. List.add 메서드를 사용하여 요소를 리스트에 추가
    3. addAll 메서드를 사용해 병렬 처리 시 실행된 각 부분 결과를 모두 합쳐 하나의 리스트로 생성

정리

productPage에서 가져온 Product 객체들을 ProductPreViewDto 객체로 매핑하고, 이를 리스트로 수집하여 반환합니다.



참고 문헌

profile
success is within reach, allow yourself time

0개의 댓글