Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions 10week/collection.foreach vs stream.foreach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---

# **Collection.forEach 와 Stream.forEach 의 차이**

---

## Stream의 foreach와 for-loop는 다르다.

- stream 은 java8 부터 람다와 함께 제공된 방법이며 컬렉션 요소를 하나씩 참조해 함수형 인터페이스를 통한 반복적 처리를 가능하게 해준다.

- 이에 for문을 stream으로 대신해 처리하는 경우가 빈번하다.

**하지만 무턱대고 아무곳에서나 for문을 stream으로 바꿔 구현하는 행위는 옳지 않다.**

- 물론 Stream을 사용하면 가독성이 높아져 코드 이해도가 높아진다. 하지만 다음 예시에서는 사용을 다시 생각해 봐야할 필요가 있다.

## 🤔 **만약 Stream의 모든 요소를 도는 forEach를 사용시 종료 조건이 있는 경우에는 어떡할까?**

- 일단 Stream 에서 강제적으로 루프를 탈출 할 수 있는 방법은 없다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/82dc64e7-1599-473e-a586-8f92e1e40e1b/_2021-04-29__11.11.17.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/82dc64e7-1599-473e-a586-8f92e1e40e1b/_2021-04-29__11.11.17.png)

- 다음 코드의 결과를 보면 같은 결과 값을 내지만 기존의 for 문에서는 50까지 수행이되면 이후는 수행 되지 않고 반복문이 종료가 되지만 stream 을 사용한 아래의 코드는 return이후 코드만 처리되지 않을뿐 50이 넘어서도 모든 조건을 확인 후에 종료하게 된다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/32e7a32a-0778-423e-acb6-bff49ad79166/_2021-04-29__11.12.21.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/32e7a32a-0778-423e-acb6-bff49ad79166/_2021-04-29__11.12.21.png)

- 다음과 같이 같은 조건문을 가지더라도 모든 조건을 다 확인하는 stream에서는 중간에 종료가 불가능 하여 비효율 적이다. forEach 연산의 올바른 사용법인 Filter 를 쓰더라도 stream은 지연 연산을 지원 하기 때문에 100번 모두를 검사하게 된다.
- 또한 forEach연산을 최종 연산중 가장 기능이 적고 Stream 스럽지 못하므로 print 문을 사용할때만 쓰자.

---

## Collection.forEach 와 Stream.forEach 의 차이점

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2b59e6d0-45e5-489c-99af-ce367ebb60e0/_2021-04-29__11.46.29.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2b59e6d0-45e5-489c-99af-ce367ebb60e0/_2021-04-29__11.46.29.png)

- 코드만 봤을 경우에는 그렇게 큰 차이는 없다.
- Collection.forEach의 경우 따로 객체를 생성하지 않고 forEach메소드를 호출하는데 Iterable 인터페이스를 상속하고 있기 때문이다.
- stream.forEach의 경우는 Collection 인터페이스의 메소드인 stream() 을 통해 stream 객체를 생성해야만 forEach 호출이 가능하다.
- 출력문을 봐도 별 차이가 없다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/dbed982b-2a70-4c9c-859c-ad6c93703462/_2021-04-29__12.07.44.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/dbed982b-2a70-4c9c-859c-ad6c93703462/_2021-04-29__12.07.44.png)

- 하지만 동시성 부분에서는 차이가 있다.

**동시성**

- Collection.forEach의 경우는 중간 과정에 삭제하는 조건문을 넣어두고 수정을 감지하면 Exception을 터트리는 구조로 코드를 작성하면 변경과 동시에 Exception 을 터트린다. (ConcurrentModificationException)
- 반면 Stream.forEach의 경우에는 다르다 Collection 때 처럼 수정을 감지하는 코드를 작성해 놓으면 Stream 은 리스트를 모두 순회 하고 예외를 던진다. (NulPointerException)

- Collection의 경우에는 Iterator을 사용하고 Stream은 spliterator을 사용한다. 아래의 [Collections.java](http://collections.java) 의 코드를 보면 Synchronized 키워드가 붙어 있다. 반면 stream에는 붙어있지 않다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d5d8eb35-1b32-4693-82e8-3dd59da18eba/_2021-04-29__12.28.13.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d5d8eb35-1b32-4693-82e8-3dd59da18eba/_2021-04-29__12.28.13.png)

- 결론적으로 둘은 큰 차이가 없지만 단순 반복을 위한 forEach면 Stream사용보다 일반 collection 의 foreach사용을 권장한다.

---

## Reference

[https://woowacourse.github.io/javable/post/2020-05-14-foreach-vs-forloop/](https://woowacourse.github.io/javable/post/2020-05-14-foreach-vs-forloop/)

[https://woowacourse.github.io/javable/post/2020-09-30-collection-stream-for-each/](https://woowacourse.github.io/javable/post/2020-09-30-collection-stream-for-each/)
113 changes: 113 additions & 0 deletions 10week/스트림 정리.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---

# Stream의 특징 정리 (map, filter, sorted, distinct, limit. foreach)

---

## 자바 8 스트림?

💁 자바 8에서 추가된 스트림은 람다식을 활용한 기술 중 하나로 테이터의 흐름이라는 뜻을 가지고 있다.

💁 스트림이란 간단하게 설명하면 자바의 컬렉션의 반복을 기존의 반복문 보다 효율적으로 처리하는 방식이라고 생각하면 이해가 쉽다. 스트림 이용시 따로 멀티 스레드 코드를 구현하지 않아도 병렬로 데이터가 처리가 된다.

💁 스트림은 선언형 코드로 구현이 가능하다. 루프, if 등의 조건문을 이용해 어떻게 동작할지 지정하지 않아도 선언형 방식으로 동작을 지정할수 있어 변하는 요구사항에 효율적으로 대응이 가능하다. 따라서 람다식을 통해 기존 코드의 중복을 줄이고 특정 조건을 필터링 하는 코드를 쉽게 구현이 가능하다.

💁 위와 같은 특징으로 인해 Sort, Filter, Map 등의 빌딩 블록 연산을 이용해 복잡한 데이터 처리에 유용하며 가독성을 해치지 않는다.

- 요약

---

## 스트림과 컬렉션

💁 자바의 기존 컬렉션과 스트림 모두 순차적으로 데이터를 저장하는 형식의 자료구조 인터페이스를 제공한다. 하지만 이 둘의 가장 큰 차이점은 언제 계산하느냐 이다.

🤔 컬렉션 : 자료구조가 포함하는 모든 값을 메모리에 저장 = 즉 컬렉션에 추가 되기전에 계산이 되어야 한다.

🤔 스트림 : 이론적으로 요청 할때만 요소를 계산하는 고정된 자료구조( 스트림에 자료를 추가하거나, 삭제 불가능 ) 스트림은 요청하는 값만 스트림에서 추출을 하는데 이는 사용자는 알 수 없다. 결과적으로 생산자와 소비자관계를 형성하게 된다.

🖍 **하나의 스트림은** **스트림은 한번만 사용 가능하다.**

- 반복자와 동일하게 스트림도 한번만 탐색 할수 있으며 다시 사용 하고 싶다면 새로운 스트림을 만들어야 한다. 또 스트림은 시간적으로 흩어진 값의 집합으로 간주 할수 있다.

---

## 스트림 연산

🖍 **중간 연산**

- filter  나 sorted 같은 중간 연산은 연산 후에 다른 스트림을 반환한다. 이 특성을 이용해 연속해서 질의를 이어 나갈수 있다. 중간 연산은 중요한 특징은 Lazy한 특성을 갖고 있어 단말 연산을 스트림 파이프 라인에 실행하기 전까지는 어떤 연산도 수행도 하지 않는다. 그저 합쳐 놓고 최종 연산으로 한번에 처리 한다.

🖍 **최종 연산**

- 최종 연산은 파이프 라인에서 결과를 도출하고 스트림 이외의 결과가 반환 된다.

☝️ **생성하기**

- 보통 배열을 이용해 스트림을 만들지만 이외의 방식으로도 스트림을 생성이 가능하다.

**배열 스트림**

- 배열은 [Array.stream](http://array.stream) 메소드를 이용해 생성을 한다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c1ff0f64-78d9-4232-becf-1601432db851/_2021-04-28__11.31.17.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c1ff0f64-78d9-4232-becf-1601432db851/_2021-04-28__11.31.17.png)

**컬렉션 스트림**

- 컬렉션 타입을 이용해서도 스트림을 생성 가능하다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c030af2b-17b3-4162-a03b-1595e93f3068/_2021-04-28__11.28.35.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c030af2b-17b3-4162-a03b-1595e93f3068/_2021-04-28__11.28.35.png)

☝️**Filtering**

- 필터는 스트림 내 요소들을 하나씩 평가해 걸러내는 작업으로 boolean을 리턴하게 된다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/58492cb9-7b22-4ef6-9486-832ead9f52db/_2021-04-28__11.38.45.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/58492cb9-7b22-4ef6-9486-832ead9f52db/_2021-04-28__11.38.45.png)

- 위 코드는 요소중에 동현이라는 값을 가진 요소를 제외 하고 나머지는 필터링 하는 코드이다.
- collect을 이용해 필터링을 하고 결과를 리스트로 반환 해준다.

☝️ **Mapping**

- 특정 객체에서 특정 데이터를 선택하는 작업은 데이터 처리과정에서 자주 수행 되는 연산이다. 스트림 에서는 map 과 flatMap을 제공한다.
- Map : 스트림의 각 요소에 함수 적용
- 각 요소에 적용 돼 새로운 요소로 매핑이 된다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/7368d742-5990-4a72-ae87-088dfe3defec/_2021-04-28__12.03.14.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/7368d742-5990-4a72-ae87-088dfe3defec/_2021-04-28__12.03.14.png)

- 위 코드는 carNames 라는 string 배열의 값을 이용해 Car객체로 생성해주는 매핑이다.
- flatMap : 중간 중첩 구조를 한단계 제거 하고 단일 컬렉션으로 만들어 주는 역할을 한다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d87f0f85-808c-456e-99f4-22fd5b967b82/_2021-04-28__12.23.02.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d87f0f85-808c-456e-99f4-22fd5b967b82/_2021-04-28__12.23.02.png)

☝️ **Sorting**

- 스트림에서 sort는 스트림 아이템을 정렬후 새로운 스트림을 생성한다. 다른 정렬과 마찬가지로 comparator 를 이용하며 인자 없이 그냥 호출시 오름차순으로 정렬 된다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/0b068347-4fb2-4b89-9905-aa61607f281e/_2021-04-28__12.35.35.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/0b068347-4fb2-4b89-9905-aa61607f281e/_2021-04-28__12.35.35.png)

- 인자를 넘기는 경우에는 comparator 를 이용하게 된다. String 의 경우에는 Comparable 인터페이스가 구현이 되어있어 Comparator 를 바로 사용할수있지만 그렇지 않은경우에는 직접 정의를 해야한다.

☝️ **Distinct**

- 사전적의미로는 뚜렷한, 분명한 이란 의미를 가지고 있는데 이는 스트림에서 중복제거를 도와주는 역할을 한다. 즉 스트림에서 사용시 중복된 요소를 모두 제거 하고 새로운 스트림을 생성해준다. 중복된 요소의 판단 기준은 Object.equals(Object) 값이다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/e78bd6eb-b284-4954-935b-241db29c77ec/_2021-04-28__12.42.46.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/e78bd6eb-b284-4954-935b-241db29c77ec/_2021-04-28__12.42.46.png)

☝️**Limit**

- Limit는 어떤 스트림에서 일정 개수 만큼 가져와 새로운 스트림을 생성하는데 사용 방법은 Stream.limit(숫자) 로 숫자만큼 데이터를 셀렉하고 스트림으로 생성하게 된다.

![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c2a2929a-96b3-435e-8a17-abf793293b49/_2021-04-28__12.46.02.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c2a2929a-96b3-435e-8a17-abf793293b49/_2021-04-28__12.46.02.png)

🔍 forEach에 대해서는 다음 정리에서 다루도록 하겠습니다.

---

## Reference

[https://futurecreator.github.io/2018/08/26/java-8-streams/](https://futurecreator.github.io/2018/08/26/java-8-streams/)

[https://12bme.tistory.com/461](https://12bme.tistory.com/461)

[https://codechacha.com/ko/java8-stream-limit-skip/](https://codechacha.com/ko/java8-stream-limit-skip/)
Loading