Lambda & Stream

Java λžŒλ‹€ ν‘œν˜„μ‹κ³Ό Stream API

JAVA 8 μ—μ„œ λžŒλ‹€ ν‘œν˜„μ‹(Lambda Expression) κ³Ό 슀트림 API(Stream API) κ°€ λ„μž…λ˜λ©΄μ„œ, μžλ°” μ–Έμ–΄λŠ” ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° νŒ¨λŸ¬λ‹€μž„μ„ λΆ€λΆ„μ μœΌλ‘œ 받아듀이고 보닀 선언적인 μ½”λ“œ μž‘μ„±μ„ μ§€μ›ν•˜κ²Œ λ˜μ—ˆμŒ. 이둜써 κ°œλ°œμžλŠ” λ°˜λ³΅λ¬Έμ΄λ‚˜ 읡λͺ… ν΄λž˜μŠ€μ— μ˜μ‘΄ν•˜λ˜ 방식을 λ²—μ–΄λ‚˜, μ½”λ“œμ˜ κ°„κ²°μ„± κ³Ό 가독성 을 높이고 λ©€ν‹°μ½”μ–΄ ν™œμš© λ“±μ˜ νš¨μœ¨μ„± 도 κ°œμ„ ν•  수 있게 λ˜μ—ˆμŒ. μ•„λž˜μ—μ„œλŠ” λžŒλ‹€ ν‘œν˜„μ‹κ³Ό 슀트림 API 의 각각의 κ°œλ… μ •μ˜, λ„μž… λ°°κ²½, 문법, μž₯단점, ν™œμš© 사둀λ₯Ό μ„€λͺ…ν• κ±°μž„.

Lambda Expression

μ •μ˜μ™€ λ„μž… λ°°κ²½

λžŒλ‹€ ν‘œν˜„μ‹ 은 λ©”μ„œλ“œ(ν•¨μˆ˜)λ₯Ό ν•˜λ‚˜μ˜ 식(expression) 으둜 ν‘œν˜„ν•˜λŠ” λ¬Έλ²•μœΌλ‘œ, 결과적으둜 단일 λ©”μ„œλ“œ μΈν„°νŽ˜μ΄μŠ€ (Functional Interface) 의 읡λͺ… κ΅¬ν˜„μ²΄μ™€ λ™λ“±ν•œ κΈ°λŠ₯을 μˆ˜ν–‰ν•¨. λ‹€μ‹œ 말해, λžŒλ‹€λ₯Ό μ‚¬μš©ν•˜λ©΄ μ½”λ“œλ₯Ό 톡해 λ™μž‘ 자체λ₯Ό 일급 객체 처럼 λ‹€λ£° 수 μžˆμ–΄μ„œ, λ©”μ„œλ“œμ˜ 인수둜 ν•¨μˆ˜ν˜• λ™μž‘μ„ 직접 μ „λ‹¬ν•˜κ±°λ‚˜ λ³€μˆ˜μ— ν• λ‹Ήν•˜λŠ” 것이 κ°€λŠ₯해짐. Java 8 μ΄μ „μ—λŠ” μ΄λŸ¬ν•œ λ™μž‘ 전달을 μœ„ν•΄ 읡λͺ… 클래슀(읡λͺ… λ‚΄λΆ€ 클래슀)λ₯Ό μ‚¬μš©ν–ˆλŠ”λ°, μ½”λ“œκ°€ μž₯ν™©ν•΄μ§€κ³  λΆˆνŽΈν•˜λ‹€λŠ” λ¬Έμ œκ°€ μžˆμ—ˆμŒ. 예λ₯Ό λ“€μ–΄ λ²„νŠΌ 클릭 이벀트 μ²˜λ¦¬λ‚˜ μ»¬λ ‰μ…˜ 정렬을 μœ„ν•΄ κ°„λ‹¨ν•œ μž‘μ—…μ΄λΌλ„ ActionListener λ‚˜ Comparator μΈν„°νŽ˜μ΄μŠ€λ₯Ό 읡λͺ… 클래슀 ν˜•νƒœλ‘œ κ΅¬ν˜„ν•΄μ•Ό ν–ˆμŒ. λžŒλ‹€ ν‘œν˜„μ‹μ€ μ΄λŸ¬ν•œ λΆˆνŽΈν•¨μ„ ν•΄μ†Œν•˜κΈ° μœ„ν•΄ λ“±μž₯ν–ˆμœΌλ©°, μžλ°”λ„ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ˜ μž₯점을 ν‘μˆ˜ν•˜μ—¬ λ™μž‘ νŒŒλΌλ―Έν„°ν™”(behavior parameterization) λ₯Ό κ°„κ²°ν•˜κ²Œ ν‘œν˜„ν•  수 있게 λ˜μ—ˆμŒ. 결과적으둜 λ³€ν™”ν•˜λŠ” μš”κ΅¬μ‚¬ν•­μ— μœ μ—°ν•˜κ²Œ λŒ€μ‘ν•˜κ³ , λΆˆν•„μš”ν•œ μ½”λ“œ 쀑볡과 λ³΅μž‘μ„±μ„ μ€„μ΄λŠ” 데 크게 κΈ°μ—¬ν•˜μ˜€μŒ.

문법과 μ‚¬μš© 방법

Java μ—μ„œ λžŒλ‹€ ν‘œν˜„μ‹μ€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ (좔상 λ©”μ„œλ“œκ°€ ν•˜λ‚˜λ§Œ μ„ μ–Έλœ μΈν„°νŽ˜μ΄μŠ€) 의 κ΅¬ν˜„μ„ μ‰½κ²Œ ν‘œν˜„ν•˜λŠ” μ‹μœΌλ‘œ μ‚¬μš©λ¨. κΈ°λ³Έ 문법은 λ‹€μŒκ³Ό κ°™μŒ.

(λ§€κ°œλ³€μˆ˜ λͺ©λ‘) -> { ν•¨μˆ˜ λ³Έλ¬Έ }
  • λ§€κ°œλ³€μˆ˜ λͺ©λ‘ : ν•¨μˆ˜μ— 전달될 λ§€κ°œλ³€μˆ˜λ₯Ό λ‚˜μ—΄ν•¨. λ§€κ°œλ³€μˆ˜κ°€ ν•˜λ‚˜μ΄λ©΄ κ΄„ν˜Έ () λ₯Ό μƒλž΅ν•  수 있음.

  • -> : λžŒλ‹€ ν™”μ‚΄ν‘œ μ—°μ‚°μžλ‘œ λ§€κ°œλ³€μˆ˜μ™€ ν•¨μˆ˜ 본문을 ꡬ뢄함.

  • ν•¨μˆ˜ λ³Έλ¬Έ : μ£Όμ–΄μ§„ λ§€κ°œλ³€μˆ˜λ₯Ό μ΄μš©ν•΄ μˆ˜ν–‰ν•  λ‘œμ§μ„ μ •μ˜ν•¨. ν•œ μ€„λ‘œ ν‘œν˜„λ˜λŠ” 경우 μ€‘κ΄„ν˜Έ {} λ₯Ό μƒλž΅ν•  수 있으며, κ·Έ 결과값이 λžŒλ‹€μ˜ λ°˜ν™˜κ°’μ΄ 됨. μ—¬λŸ¬ μ€„λ‘œ 이루어진 경우 {} 블둝 내에 μž‘μ„±ν•˜κ³  return 문을 μ‚¬μš©ν•¨.

λžŒλ‹€ ν‘œν˜„μ‹μ€ νƒ€κ²Ÿ νƒ€μž… λ¬Έλ§₯, 즉 λ³€μˆ˜ μ„ μ–Έμ΄λ‚˜ λ©”μ„œλ“œ 인수 λ“±μ˜ μœ„μΉ˜μ—μ„œ ν•΄λ‹Ή λžŒλ‹€μ™€ ν˜Έν™˜λ˜λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ˜ νƒ€μž…μ„ 톡해 μ‚¬μš©λ¨. 예λ₯Ό λ“€μ–΄ Runnable μΈν„°νŽ˜μ΄μŠ€λŠ” μΈμˆ˜κ°€ μ—†κ³  λ°˜ν™˜κ°’μ΄ μ—†λŠ” run() 좔상 λ©”μ„œλ“œλ₯Ό κ°–λŠ”λ°, 이λ₯Ό λžŒλ‹€λ‘œ ν‘œν˜„ν•˜λ©΄ () -> {...} ν˜•νƒœκ°€ 됨. κ°„λ‹¨ν•œ μ‚¬μš© 예λ₯Ό 톡해 비ꡐ해보면:

// Java 8 이전 : 읡λͺ… 클래슀둜 μ“°λ ˆλ“œ μ‹€ν–‰
Thread th1 = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello, World!");
    }
});
th1.start();


// Java 8 이후 : λžŒλ‹€ ν‘œν˜„μ‹μœΌλ‘œ μ“°λ ˆλ“œ μ‹€ν–‰
Thread th2 = new Thread(() -> System.out.println("Hello, World!"));
th2.start();

μœ„ μ½”λ“œμ—μ„œ λ³Ό 수 μžˆλ“―μ΄, λžŒλ‹€λ₯Ό μ‚¬μš©ν•˜λ©΄ 읡λͺ… 클래슀 κ΅¬ν˜„μ— λΉ„ν•΄ ꡬ문이 훨씬 κ°„κ²° 해짐. 이 외에도 λžŒλ‹€λŠ” Comparator 와 같이 ν•˜λ‚˜μ˜ λ©”μ„œλ“œλ§Œ κ°€μ§„ μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„μ— 널리 μ‚¬μš©λ¨. 예λ₯Ό λ“€μ–΄ 리슀트 정렬을 μœ„ν•œ λΉ„κ΅μžλ₯Ό λžŒλ‹€λ‘œ μ‰½κ²Œ μ œκ³΅ν•  수 있음.

List<String> fruits = Arrays.asList("banana", "apple", "cherry");

// λžŒλ‹€λ₯Ό μ‚¬μš©ν•œ μ •λ ¬: λ¬Έμžμ—΄ 길이λ₯Ό κΈ°μ€€μœΌλ‘œ μ •λ ¬
fruits.sort((a,b) -> a.length() - b.length());
System.out.println(fruits); // result : [apple, banana, cherry]

μœ„μ˜ sort ν˜ΈμΆœμ—μ„œ λžŒλ‹€ (a,b) -> a.length() - b.length() λŠ” Comparator<String> 의 compare(String o1, String o2) λ©”μ„œλ“œ κ΅¬ν˜„μ„ ν‘œν˜„ν•œ κ²ƒμž„. 이처럼 λžŒλ‹€ 문법을 μ‚¬μš©ν•˜λ©΄, μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” 읡λͺ… 클래슀 선언을 직접 ν•˜μ§€ μ•Šκ³ λ„ ν•„μš”ν•œ λ™μž‘μ„ 전달할 수 있음. λ˜ν•œ γ„Ήλ§ˆλ‹€ λ‚΄λΆ€μ—μ„œλŠ” μ™ΈλΆ€ μ§€μ—­λ³€μˆ˜ λ₯Ό μ°Έμ‘°ν•  수 μžˆλŠ”λ°, 이 경우 ν•΄λ‹Ή λ³€μˆ˜λŠ” μžλ™μœΌλ‘œ effectively final(사싀상 μƒμˆ˜) 둜 μ·¨κΈ‰λ˜μ–΄ λžŒλ‹€μ—μ„œ μ•ˆμ „ν•˜κ²Œ ν™œμš©λ¨.

μž₯점

  • μ½”λ“œ κ°„κ²°μ„± ν–₯상 : λžŒλ‹€ ν‘œν˜„μ‹μ€ λ™μΌν•œ κΈ°λŠ₯을 ν•˜λŠ” μ½”λ“œλ₯Ό 훨씬 μ§§κ³  λͺ…ν™•ν•˜κ²Œ λ§Œλ“€λ©°, 보일러 ν”Œλ ˆμ΄νŠΈ(boilerplate) μ½”λ“œλ₯Ό μ€„μ—¬μ€Œ. 읡λͺ… 클래슀 μ‚¬μš© λŒ€λΉ„ μž‘μ„±ν•΄μ•Ό ν•  μ½”λ“œλŸ‰μ΄ 크게 κ°μ†Œν•˜μ—¬ 가독성이 높아짐.

  • ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° 지원 : ν•¨μˆ˜ 자체λ₯Ό κ°’μœΌλ‘œ 전달할 수 μžˆμœΌλ―€λ‘œ, λ©”μ„œλ“œμ˜ 인자둜 λ™μž‘μ„ λ„˜κΈ°κ±°λ‚˜ μ»¬λ ‰μ…˜μ„ μ²˜λ¦¬ν•˜λŠ” λ‘œμ§μ„ μ „λž΅μ²˜λŸΌ λ°”κΏ” λΌμš°λŠ” λ“± λ™μž‘ νŒŒλΌλ―Έν„°ν™” κ°€ μ‰¬μ›Œμ§.

  • ν‘œν˜„λ ₯ 증가 : λžŒλ‹€μ™€ ν•¨κ»˜ λ„μž…λœ 슀트림 API 와 κ²°ν•©ν•˜μ—¬, λ³΅μž‘ν•œ 연산을 선언적이고 직관적인 방식 으둜 ν‘œν˜„ν•  수 있음. 무엇을 할지에 μ§‘μ€‘ν•œ μ½”λ“œ μž‘μ„±μ΄ κ°€λŠ₯ν•΄μ§€κ³ , loop λ‚˜ 쑰건문 λ“±μ˜ κ΅¬ν˜„ 세뢀사항은 숨겨짐.

  • λ©±λ“±μ„± 및 λ©€ν‹°μŠ€λ ˆλ“œ ν™œμš© : λžŒλ‹€λ‘œ μ „λ‹¬λ˜λŠ” ν•¨μˆ˜λŠ” λΆ€μž‘μš©μ΄ 없도둝 μž‘μ„±λ˜λŠ” 것이 ꢌμž₯λ˜λŠ”λ°, 이런 νŠΉμ„± 덕뢄에 μŠ€νŠΈλ¦Όμ—μ„œ 병렬 처리 λ₯Ό ν•  λ•Œλ„ μ•ˆμ „ν•˜κ²Œ μ μš©ν•  수 있음. λ˜ν•œ 병렬 슀트림 등을 μ‚¬μš©ν•  λ•Œ λ³„λ„μ˜ μŠ€λ ˆλ“œ 관리 μ½”λ“œ 없이도 λ©€ν‹°μ½”μ–΄ ν™œμš©μ΄ κ°€λŠ₯해짐.

  • ν‘œμ€€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ ν™œμš© : μžλ°” 8 μ—μ„œλŠ” java.util.function νŒ¨ν‚€μ§€μ— λ‹€μ–‘ν•œ μš©λ„μ˜ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€(Consumer, Function, Predicate λ“±) κ°€ μ œκ³΅λ˜μ–΄ μžˆμ–΄, λžŒλ‹€λ₯Ό μ‚¬μš©ν•œ ν‘œμ€€ν™”λœ ν”„λ‘œκ·Έλž˜λ° μŠ€νƒ€μΌμ„ ν™œμš©ν•  수 있음. μ΄λŠ” API 섀꼐 및 μ‚¬μš© μΈ‘λ©΄μ—μ„œ 일관성을 뢀여함.

단점

  • 초기 가독성 μ €ν•˜ : λžŒλ‹€ 문법이 μ΅μˆ™ν•˜μ§€ μ•Šμ€ κ°œλ°œμžμ—κ²ŒλŠ” 였히렀 μ½”λ“œμ˜ 의미λ₯Ό νŒŒμ•…ν•˜κΈ° μ–΄λ €μšΈ 수 있음. 읡λͺ… ν΄λž˜μŠ€μ— λΉ„ν•΄ μ½”λ“œμ˜ λͺ…μ‹œμ„±μ΄ λ–¨μ–΄μ§ˆ 수 μžˆλ‹€ λŠ” 지적도 있으며, μ–΄λŠ μΈν„°νŽ˜μ΄μŠ€μ˜ μ–΄λ–€ λ©”μ„œλ“œλ₯Ό κ΅¬ν˜„ν•œ 것인지 λ°”λ‘œ μ•ŒκΈ° μ–΄λ €μ›Œ μ²˜μŒμ—” ν˜Όλž€μ„ 쀄 수 있음.

  • 디버깅 어렀움 : λžŒλ‹€ ν‘œν˜„μ‹ μžμ²΄μ—λŠ” 이름이 μ—†κ³  읡λͺ… ν•¨μˆ˜ ν˜•νƒœλ‘œ μ‹€ν–‰λ˜κΈ° λ•Œλ¬Έμ—, λ””λ²„κ±°λ‘œ 좔적할 λ•Œ μŠ€νƒ νŠΈλ ˆμ΄μŠ€κ°€ 직관적이지 μ•Šμ„ 수 있고, λžŒλ‹€ λ‚΄λΆ€μ—μ„œ μ˜ˆμ™Έ λ°œμƒ μ‹œ μ–΄λŠ 지점인지 νŒŒμ•…μ΄ λ‹€μ†Œ κΉŒλ‹€λ‘œμšΈ 수 있음. λ˜ν•œ λžŒλ‹€ λ‚΄ μ½”λ“œλŠ” ν•˜λ‚˜μ˜ ν΄λ‘œμ €(Closure) 둜 μ·¨κΈ‰λ˜λ―€λ‘œ, 쀑간에 λ³€μˆ˜ 값을 μ°μ–΄λ³΄κ±°λ‚˜ ν•˜κΈ°κ°€ 전톡적인 루프에 λΉ„ν•΄ λ²ˆκ±°λ‘œμ›€.

  • μ œν•œ 사항 : λžŒλ‹€λŠ” 였직 ν•˜λ‚˜μ˜ 좔상 λ©”μ„œλ“œλ§Œμ„ κ°€μ§„ μΈν„°νŽ˜μ΄μŠ€ 에 λŒ€ν•΄μ„œλ§Œ μ‚¬μš©ν•  수 μžˆμœΌλ―€λ‘œ (@FunctionalInterface ), 기쑴의 μ—¬λŸ¬ λ©”μ„œλ“œλ₯Ό κ°€μ§„ νƒ€μž…μ„ λžŒλ‹€λ‘œ 직접 κ΅¬ν˜„ν•  μˆ˜λŠ” μ—†μŒ. λ˜ν•œ λžŒλ‹€ λ³Έλ¬Έμ—μ„œ checked μ˜ˆμ™Έ λ₯Ό λ˜μ§€λ €λ©΄ ν•΄λ‹Ή μΈν„°νŽ˜μ΄μŠ€μ— κ·Έ μ˜ˆμ™Έκ°€ μ„ μ–Έλ˜μ–΄ μžˆμ–΄μ•Ό ν•˜λŠ” λ“±μ˜ μ˜ˆμ™Έ 처리 μ œν•œμ΄ 있음.

  • μ™ΈλΆ€ μƒνƒœ λ³€κ²½μ˜ μ œν•œ : λžŒλ‹€ λ‚΄λΆ€μ—μ„œλŠ” μ™ΈλΆ€ μ§€μ—­ λ³€μˆ˜λ₯Ό λ³€κ²½ν•  수 μ—†μŒ. (ν•΄λ‹Ή λ³€μˆ˜λŠ” effectively final 이어야 함.) λ”°λΌμ„œ λžŒλ‹€μ‹ λ‚΄λΆ€μ—μ„œ μ™ΈλΆ€ μƒνƒœλ₯Ό λ³€κ²½ν•˜λŠ” λ‘œμ§μ€ 컴파일 νƒ€μž„μ— μ œν•œλ˜λ©°, μ΄λŸ¬ν•œ μ„€κ³„λŠ” λΆ€μž‘μš©μ„ λ°©μ§€ν•˜μ§€λ§Œ λ•Œλ‘œλŠ” λΆˆνŽΈν•¨μœΌλ‘œ 느껴질 수 있음.(AtomicInteger λ‚˜ λ°°μ—΄ λ“±μœΌλ‘œ 우회 κ°€λŠ₯ν•˜μ§€λ§Œ ꢌμž₯λ˜μ§€λŠ” μ•ŠμŒ.)

  • μ„±λŠ₯ 및 컴파일 μ˜€λ²„ν—€λ“œ : λžŒλ‹€ μžμ²΄λŠ” μžλ°” μ»΄νŒŒμΌλŸ¬κ°€ λ‚΄λΆ€μ μœΌλ‘œ invokedynamic 기반으둜 κ΅¬ν˜„ν•˜κ±°λ‚˜ μˆ¨κ²¨μ§„ 클래슀 νŒŒμΌμ„ μƒμ„±ν•˜μ—¬ μ²˜λ¦¬ν•¨. 일반적으둜 이둜 μΈν•œ μ‹€ν–‰ μ„±λŠ₯ λΆ€ν•˜κ°€ 크지 μ•Šμ§€λ§Œ, μžλ°” 8 μ΄ˆκΈ°μ—λŠ” λžŒλ‹€ μ‚¬μš© μ‹œ 첫 ν˜ΈμΆœμ— μ•½κ°„μ˜ 지연이 μžˆλ‹€λŠ” 보고도 μžˆμ—ˆμŒ. ν•˜μ§€λ§Œ JIT μ΅œμ ν™”λ‘œ λŒ€λΆ€λΆ„ μƒμ‡„λ˜λ©°, λžŒλ‹€ ν‘œν˜„μ‹ κ·Έ 자체둜 큰 μ„±λŠ₯μƒμ˜ 단점은 μ—†μŒ ( 주둜 슀트림 μ‚¬μš© μ‹œμ˜ μ˜€λ²„ν—€λ“œκ°€ 이슈)

Stream API

Stream 은 μžλ°” 8 μ—μ„œ μ»¬λ ‰μ…˜ λ“±μ˜ 데이터λ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄ λ„μž…λœ ν•¨μˆ˜ν˜• API μž„. μŠ€νŠΈλ¦Όμ„ μ‚¬μš©ν•˜λ©΄ μ„ μ–Έν˜•(declarative) λ°©μ‹μœΌλ‘œ μ»¬λ ‰μ…˜μ˜ μš”μ†Œλ“€μ„ λ‹€λ£° 수 있으며, λ³΅μž‘ν•œ 데이터 μ²˜λ¦¬λ„ λ©”μ„œλ“œ 체이닝을 톡해 νŒŒμ΄ν”„λΌμΈ ν˜•νƒœλ‘œ κ΅¬ν˜„ν•  수 있음. μŠ€νŠΈλ¦Όμ€ ν•œλ§ˆλ””λ‘œ 데이터 μš”μ†Œλ“€μ˜ 연속적인 흐름 μœΌλ‘œμ„œ, 이에 λŒ€ν•΄ 일련의 쀑간 μ—°μ‚°κ³Ό μ΅œμ’… 연산을 μ μš©ν•˜μ—¬ μ›ν•˜λŠ” κ²°κ³Όλ₯Ό μ–»λŠ” 것을 κ°€λŠ₯μΌ€ 함. μ΄λŸ¬ν•œ μ ‘κ·Ό 방식은 전톡적인 λ°˜λ³΅λ¬Έμ— λΉ„ν•΄ κ°„κ²°ν•˜κ³  μ˜λ„μ— μ§‘μ€‘λœ μ½”λ“œ λ₯Ό μž‘μ„±ν•  수 있게 ν•΄μ£Όλ©°, λ‚΄λΆ€ λ°˜λ³΅μ„ 톡해 μ΅œμ ν™” μ—¬μ§€λ₯Ό λ‚¨κ²¨λ‘κ±°λ‚˜ μ†μ‰½κ²Œ 병렬 처리둜 μ „ν™˜ν•  수 μžˆλ‹€λŠ” μž₯점이 있음.

슀트림 API 의 λ„μž… λ°°κ²½μ—λŠ” μ—¬λŸ¬ κ°€μ§€ μ΄μœ κ°€ 있음.

첫째, λŒ€λŸ‰ 데이터 처리의 ν•„μš”μ„± μž„. λ©€ν‹°μ½”μ–΄ μ‹œλŒ€μ— 효과적으둜 μ»¬λ ‰μ…˜μ„ μ²˜λ¦¬ν•˜λ €λ©΄, κ°œλ°œμžκ°€ 일일이 μ“°λ ˆλ“œλ₯Ό κ΄€λ¦¬ν•˜μ§€ μ•Šκ³ λ„ 데이터 처리λ₯Ό 병렬화할 수 μžˆλŠ” κ³ μˆ˜μ€€μ˜ 좔상화가 μš”κ΅¬λ˜μ—ˆμŒ. μŠ€νŠΈλ¦Όμ€ parallelStream() λ©”μ„œλ“œλ₯Ό 톡해 κ°„λ‹¨νžˆ 데이터 병렬 처리λ₯Ό κ΅¬ν˜„ν•  수 있게 ν•΄μ€Œ.

λ‘˜μ§Έ, 가독성과 μœ μ§€λ³΄μˆ˜μ„± κ°œμ„  μž„. μŠ€νŠΈλ¦Όμ„ μ‚¬μš©ν•˜λ©΄ 루프와 쑰건문이 λ’€μ„žμΈ μ½”λ“œλ³΄λ‹€ μ˜λ„κ°€ λͺ…ν™•ν•œ νŒŒμ΄ν”„λΌμΈμ„ ꡬ성할 수 있고, 이λ₯Ό 톡해 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ μΌκ΄€λœ ν˜•νƒœλ‘œ ν‘œν˜„ ν•  수 있음.

λ§ˆμ§€λ§‰μœΌλ‘œ, ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ˜ κ°œλ…μ„ λ„μž…ν•¨μœΌλ‘œμ¨ λΆ€μž‘μš© μ—†λŠ” 처리 λ₯Ό μ§€ν–₯ν•˜κ³ , 필터링, λ§€ν•‘, μ •λ ¬, κ·Έλ£Ήν•‘ λ“± 곡톡 연산을 μž¬μ‚¬μš© κ°€λŠ₯ν•˜κ²Œ ν‘œμ€€ν™” ν•˜κ³ μž ν•œ μ˜λ„κ°€ 있음. 예λ₯Ό λ“€μ–΄ κ³Όκ±°μ—λŠ” 반볡문과 쑰건검사λ₯Ό 톡해 직접 κ΅¬ν˜„ν•΄μ•Ό ν–ˆλ˜ λ‘œμ§λ“€μ„ μ΄μ œλŠ” filter , map , collect λ“±μ˜ μž¬μ‚¬μš© κ°€λŠ₯ν•œ μ—°μ‚°μœΌλ‘œ ν•œμ€„μ”© ν‘œν˜„ν•  수 있음.

슀트림 ꡬ쑰와 μ£Όμš” μ—°μ‚°

슀트림 API 의 μ‚¬μš© 방법은 데이터 μ†ŒμŠ€ λ‘œλΆ€ν„° 슀트림 객체λ₯Ό μƒμ„±ν•˜κ³ , μ—¬λŸ¬ 쀑간 μ—°μ‚° (Intermediate Operation) 을 μ—°μ†μœΌλ‘œ μ μš©ν•œ λ’€, μ΅œμ’… μ—°μ‚° (Terminal Operation) 으둜 κ²°κ³Όλ₯Ό μ–»λŠ” νŒ¨ν„΄μœΌλ‘œ μš”μ•½λ¨. μ΄λ•Œ 쀑간 연산듀은 μŠ€νŠΈλ¦Όμ„ λ¦¬ν„΄ν•˜μ—¬ λ‹€μŒ μ—°μ‚°κ³Ό μ²΄μ΄λ‹λ˜λ©°, μ‹€μ œ 처리(load) λŠ” μ΅œμ’… 연산이 호좜될 λ•Œ λΉ„λ‘œμ†Œ μΌμ–΄λ‚˜λŠ” μ§€μ—° 평가(lazy evaluation) νŠΉμ„±μ„ 가짐. 슀트림의 전체적인 κ΅¬μ„±μš”μ†ŒλŠ” λ‹€μŒκ³Ό κ°™μŒ.

  • 데이터 μ†ŒμŠ€(Data Source) : 슀트림의 좜발점이 λ˜λŠ” μš”μ†Œλ“€μ˜ λͺ¨μž„μž„. 예λ₯Ό λ“€μ–΄ μ»¬λ ‰μ…˜μ˜ stream() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜κ±°λ‚˜, 배열에 Arrays.stream(array) λ₯Ό μ‚¬μš©ν•˜κ±°λ‚˜, 파일 I/O μ—μ„œ Files.lines(path) 둜 μŠ€νŠΈλ¦Όμ„ 생성할 수 있음.

  • 쀑간 μ—°μ‚°(Intermediate Operation) : 슀트림의 데이터λ₯Ό ν•„ν„°λ§ν•˜κ±°λ‚˜ λ³€ν™˜ν•˜λŠ” μ—°μ‚°λ“€μž„. λŒ€ν‘œμ μœΌλ‘œ filter(Predicate) , map(Function) , sorted() , distinct() , limit() 등이 있으며, μ—¬λŸ¬ 쀑간 연산을 νŒŒμ΄ν”„λΌμΈ ν˜•νƒœ 둜 μ—°κ²°ν•  수 있음. 쀑간 μ—°γ……λ‚˜μ€ lazy ν•˜κ²Œ λ™μž‘ν•˜μ—¬, λ‹¨λ…μœΌλ‘œλŠ” μ‹€ν–‰λ˜μ§€ μ•Šκ³  결과도 λ°”λ‘œ 얻을 수 μ—†μŒ. 쀑간 μ—°μ‚°μ˜ κ²°κ³ΌλŠ” μ—¬μ „νžˆ μŠ€νŠΈλ¦Όμ΄λ―€λ‘œ, μ΄μ–΄μ„œ λ‹€μŒ 연산을 μ μš©ν•  수 있음.

  • μ΅œμ’… μ—°μ‚°(Terminal Operation) : 슀트림 νŒŒμ΄ν”„λΌμΈμ˜ 끝을 λ§ΊλŠ” μ—°μ‚°μœΌλ‘œ, μ΅œμ’… 연산이 호좜될 λ•Œ κ·Έμ œμ„œμ•Ό μ΄μ „κΉŒμ§€μ˜ λͺ¨λ“  쀑간 연산이 μ μš©λ˜λ©΄μ„œ μ‹€μ œ 처리 κ°€ μˆ˜ν–‰λ˜κ³  κ²°κ³Όκ°€ 생성됨. μ΅œμ’… μ—°μ‚°μ—λŠ” 슀트림 μš”μ†Œλ₯Ό μ†Œλͺ¨ν•˜μ—¬ κ²°κ³Όλ₯Ό μ–»λŠ” collect() , count() , reduce() λ‚˜, λΆ€μž‘μš©μ„ λ°œμƒμ‹œν‚€λŠ” forEach() 등이 있음. μ΅œμ’…μ—°μ‚°μ„ ν˜ΈμΆœν•˜λ©΄ ν•΄λ‹Ή μŠ€νŠΈλ¦Όμ€ μž¬μ‚¬μš©ν•  수 μ—†κ²Œ(μ†Œλͺ¨λœ μƒνƒœλ‘œ) 됨.

예제

λ¬Έμžμ—΄ 리슀트 μ—μ„œ νŠΉμ • 쑰건에 λ§žλŠ” λ¬Έμžμ—΄λ§Œ ν•„ν„°λ§ν•˜μ—¬ λŒ€λ¬Έμžλ‘œ λ³€ν™˜ν•œ λ’€ μ •λ ¬ν•˜μ—¬ κ²°κ³Ό 리슀트λ₯Ό μ–»λŠ” μž‘μ—…μ„, κΈ°μ‘΄ 방식과 μŠ€νŠΈλ¦Όμ„ ν™œμš©ν•œ λ°©μ‹μœΌλ‘œ λΉ„κ΅ν•˜λŠ” μ˜ˆμ œμž„.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Anna", "Alex");
List<String> resultList = new ArrayList<>();

// κΈ°μ‘΄ 방식: 반볡문 μ‚¬μš©
for(String name : names) {
    if(name.startWith("A")) {
        resultList.add(name,toUpperCase());
    }
}
Collections.sort(resultList); // μ •λ ¬
System.out.println(resultList); // result : [ALEX, ALICE, ANNA]

//슀트림 μ‚¬μš© : νŒŒμ΄ν”„λΌμΈ ꡬ성
List<String> resultList2 = names.stream()
    .filter(n -> n.startWith("A"))
    .map(String::toUpperCase)
    .sorted()
    .collect(Collectors.toList());
System.out.println(resultList2);

μœ„ μ˜ˆμ œμ—μ„œ μ•Œ 수 μžˆλ“―μ΄, μŠ€νŠΈλ¦Όμ„ μ‚¬μš©ν•˜λ©΄ 데이터 처리 κ³Όμ • 을 마치 SQL의 질의문 처럼 μ„ μ–Έμ μœΌλ‘œ μž‘μ„±ν•  수 있음. names.stream() 으둜 λ¦¬μŠ€νŠΈμ— λŒ€ν•œ μŠ€νŠΈλ¦Όμ„ 얻은 λ’€, filter 둜 "A" 둜 μ‹œμž‘ν•˜λŠ” μ΄λ¦„λ§Œ κ±ΈλŸ¬λ‚΄κ³ , map 으둜 λŒ€λ¬Έμž λ³€ν™˜, sorted 둜 μ •λ ¬, λ§ˆμ§€λ§‰μ— collect 둜 리슀트둜 λͺ¨μœΌλŠ” 일련의 과정을 λ©”μ„œλ“œ 체이닝 으둜 ν‘œν˜„ν–ˆμŒ. κΈ°μ‘΄ 방식과 λΉ„κ΅ν•˜λ©΄ μ½”λ“œμ˜ ν–‰ μˆ˜κ°€ 쀄어듀고, 각 λ‹¨κ³„μ˜ μ˜λ„κ°€ μ½”λ“œμ— λͺ…ν™•νžˆ λ“œλŸ¬λ‚˜λŠ” 것을 λ³Ό 수 있음.

λ˜ν•œ 슀트림의 μ§€μ—° μ‹€ν–‰ 덕뢄에, λ§Œμ•½ μœ„ νŒŒμ΄ν”„λΌμΈμ—μ„œ filter ν›„ λ°”λ‘œ 첫 번째 λ§€μΉ­ μš”μ†Œλ§Œ μ°ΎλŠ” μ—°μ‚°(예: findFirst() ) 을 μ΅œμ’… μ—°μ‚°μœΌλ‘œ μ‚¬μš©ν–ˆλ‹€λ©΄ 쑰건에 λ§žλŠ” λ‚˜λ¨Έμ§€ μš”μ†Œλ“€μ€ ꡳ이 λŒ€λ¬Έμž λ³€ν™˜μ΄λ‚˜ 정렬을 μˆ˜ν–‰ν•˜μ§€ μ•Šκ³ λ„ 처리λ₯Ό 마칠 수 있음. μ΄λŸ¬ν•œ lazy νŠΉμ„± 은 λΆˆν•„μš”ν•œ 연산을 쀄여 μ„±λŠ₯을 높일 수 μžˆλŠ” μš”μ†Œμž„.

λ§ˆμ§€λ§‰μœΌλ‘œ μŠ€νŠΈλ¦Όμ—λŠ” κΈ°λ³Έν˜• νŠΉν™” 슀트림 (IntStream , LongStream , DoubleStream ) 도 제곡됨. 이λ₯Ό ν™œμš©ν•˜λ©΄ λ°•μ‹±(boxing)/μ–Έλ°•μ‹± 없이 κΈ°λ³Έ νƒ€μž…μ˜ λŒ€λŸ‰ 데이터도 효율적으둜 μ²˜λ¦¬ν•  수 있음. 예λ₯Ό λ“€μ–΄, IntStream.range(1,100) 은 1 λΆ€ν„° 99κΉŒμ§€μ˜ μ •μˆ˜ μŠ€νŠΈλ¦Όμ„ μƒμ„±ν•˜λ©°, mapToObj λ‚˜ mapToInt λ“±μ˜ λ©”μ„œλ“œλ₯Ό 톡해 객체 슀트림과 κΈ°λ³Έν˜• 슀트림 κ°„ μ „ν™˜λ„ κ°€λŠ₯함.

슀트림의 μž₯점

  • μ½”λ“œ μ„ μ–Έμ„± & 간결함 : μŠ€νŠΈλ¦Όμ„ μ‚¬μš©ν•˜λ©΄ 자료 μ²˜λ¦¬μ— λŒ€ν•œ μ˜λ„λ₯Ό μ½”λ“œμ— ν‘œν˜„ν•˜κΈ° 쉬움. 무엇을 ν•˜κ³ μž ν•˜λŠ”μ§€λ₯Ό λ©”μ„œλ“œ 호좜 체인으둜 λ³΄μ—¬μ£Όλ―€λ‘œ, for-loop 등에 λΉ„ν•΄ μ½”λ“œκ°€ κ°„κ²°ν•˜κ³  λ…Όλ¦¬μ˜ 흐름이 λΆ„λͺ…함 . 특히 닀단계 처리 (필터링 -> λ§€ν•‘ -> μ •λ ¬ -> 집계 λ“±) λ₯Ό 쀑첩 루프 없이 νŒŒμ΄ν”„λΌμΈμœΌλ‘œ ν‘œν˜„ν•  수 μžˆμ–΄, λ³΅μž‘ν•œ μ²˜λ¦¬λ„ 비ꡐ적 읽기 μ‰½κ²Œ μž‘μ„±ν•  수 있음.

  • μž¬μ‚¬μš© κ°€λŠ₯ν•œ μ—°μ‚° : filter , map , reduce , collect λ“± 슀트림이 μ œκ³΅ν•˜λŠ” λ§Žμ€ 연산은 이미 μ΅œμ ν™”λ˜μ–΄ 있고 λ²”μš©μ μœΌλ‘œ μ“Έ 수 μžˆλŠ” κ³ μˆ˜μ€€ ν•¨μˆ˜λ“€μž„. 이λ₯Ό ν™œμš©ν•˜λ©΄ κ°œλ°œμžκ°€ μ €μˆ˜μ€€μ—μ„œ 일일이 μž‘μ„±ν•΄μ•Ό ν–ˆλ˜ λ‘œμ§μ„ 쀄이고 생산성 을 높일 수 있음.

  • λΆˆλ³€μ„±κ³Ό λΆ€μž‘μš© μ΅œμ†Œν™” : 슀트림 연산은 원본 데이터λ₯Ό λ³€κ²½ν•˜μ§€ μ•Šκ³  μƒˆλ‘œμš΄ κ²°κ³Όλ₯Ό μž‘μ„±ν•¨. λ˜ν•œ 쀑간 연산듀은 순수 ν•¨μˆ˜ν˜•μœΌλ‘œ λ™μž‘ν•˜λ„λ‘ ꢌμž₯λ˜λ―€λ‘œ(μ™ΈλΆ€ μƒνƒœλ₯Ό λ³€κ²½ν•˜μ§€ μ•ŠλŠ” λžŒλ‹€), ν”„λ‘œκ·Έλž¨μ˜ λΆ€μž‘μš©(side effect) 을 쀄이고 버그λ₯Ό μ˜ˆλ°©ν•˜λŠ” 데 도움이 됨. 이런 νŠΉμ„±μ€ μ½”λ“œμ˜ ν…ŒμŠ€νŠΈ μš©μ΄μ„±κ³Ό 예츑 κ°€λŠ₯성도 ν–₯μƒμ‹œν‚΄.

  • Lazy μ—°μ‚°μœΌλ‘œ μΈν•œ μ΅œμ ν™” : μ•žμ„œ μ„€λͺ…ν•œ λŒ€λ‘œ, μŠ€νŠΈλ¦Όμ€ μ§€μ—° 평가λ₯Ό 톡해 ν•„μš”ν•  λ•Œλ§Œ 연산을 μ‹€ν–‰ν•˜λ―€λ‘œ μ„±λŠ₯ μ΅œμ ν™” 에 도움이 됨. 예λ₯Ό λ“€μ–΄ μ—¬λŸ¬ λ‹¨κ³„μ˜ 쀑간 연산이 μžˆλ”λΌλ„, μ΅œμ’… μ—°γ……λ‚˜μ΄ findFirst λ‚˜ anyMatch 처럼 μΌλΆ€λ§Œ ν•„μš”λ‘œ ν•˜λŠ” μž‘μ—…μ΄λ©΄ 전체 μš”μ†Œλ₯Ό λκΉŒμ§€ μ²˜λ¦¬ν•˜μ§€ μ•ŠμŒ. λ˜ν•œ νŒŒμ΄ν”„λΌμΈ λ‚΄λΆ€μ—μ„œ 연산듀이 루프 퓨전(loop fusion) λ˜μ–΄ ν•œ 번의 순회둜 처리될 μˆ˜λ„ 있음.

  • 병렬 처리 용이 : 슀트림의 κ°€μž₯ 큰 νŠΉμ§• 쀑 ν•˜λ‚˜λŠ” μ†μ‰¬μš΄ λ³‘λ ¬ν™”μž„. stream() λŒ€μ‹  parallelStream() 을 ν˜ΈμΆœν•˜λ©΄ λ‚΄λΆ€μ μœΌλ‘œ Fork/Join ν”„λ ˆμž„μ›Œν¬λ₯Ό ν™œμš©ν•˜μ—¬ μ—¬λŸ¬ 코어에 μž‘μ—…μ„ 뢄배함. 큰 μ»¬λ ‰μ…˜μ— λŒ€ν•΄ CPU μ½”μ–΄λ₯Ό λͺ¨λ‘ ν™œμš©ν•¨μœΌλ‘œμ¨ μ„±λŠ₯ ν–₯상을 κΈ°λŒ€ν•  수 있으며, 이λ₯Ό κ΅¬ν˜„ν•˜κΈ° μœ„ν•œ λ³΅μž‘ν•œ λ©€ν‹°μŠ€λ ˆλ“œ μ½”λ“œλ₯Ό 직접 μž‘μ„±ν•  ν•„μš”κ°€ μ—†μŒ.

  • λ‹€μ–‘ν•œ 데이터 μ†ŒμŠ€ 처리 : μ»¬λ ‰μ…˜ 뿐만 μ•„λ‹ˆλΌ λ°°μ—΄, 파일 , I/O 채널 λ“± λ‹€μ–‘ν•œ μ†ŒμŠ€λ‘œλΆ€ν„° μŠ€νŠΈλ¦Όμ„ μƒμ„±ν•˜μ—¬ κ³΅ν†΅λœ λ°©μ‹μœΌλ‘œ μ²˜λ¦¬ν•  수 μž‡μŒ. 예λ₯Ό λ“€μ–΄ Files.lines() 둜 파일의 각 쀄을 슀트림으둜 μ–»μ–΄ μ²˜λ¦¬ν•˜κ±°λ‚˜, Pattern.compile(...).splitAsStream() 으둜 λ¬Έμžμ—΄μ„ 슀트림으둜 λ‹€λ£¨λŠ” λ“± μ‘μš© λ²”μœ„κ°€ λ„“μŒ.

슀트림의 단점

  • μ†ŒλŸ‰ 데이터에 λŒ€ν•œ μ˜€λ²„ν—€λ“œ : μŠ€νŠΈλ¦Όμ„ μƒμ„±ν•˜κ³  λžŒλ‹€λ₯Ό ν˜ΈμΆœν•˜λ©° μ—¬λŸ¬ 객체λ₯Ό μƒμ„±ν•˜λŠ” λΉ„μš© λ•Œλ¬Έμ—, μ•„μ£Ό λ‹¨μˆœν•œ λ°˜λ³΅μ΄λ‚˜ μ†ŒλŸ‰μ˜ 데아터 μ²˜λ¦¬μ—λŠ” 였히렀 전톡적인 루프보닀 느릴 수 있음 . 예컨데 λ‹¨μˆœνžˆ 리슀트의 λ‚΄μš©μ„ 좜λ ₯ν•˜λŠ” κ²½μš°μ—λ„ names.stream().forEach(...) λ³΄λ‹€λŠ” κ°•ν™”λœ forλ¬Έ(for(String name : names) ) 이 μ„±λŠ₯상 μœ λ¦¬ν•  수 있음. μž‘μ€ μž‘μ—…μ— μΌκ΄„μ μœΌλ‘œ μŠ€νŠΈλ¦Όμ„ μ μš©ν•˜λŠ” 것은 ν”Όν•˜λŠ” 것이 μ’‹μŒ.

  • 디버깅 및 좔적 어렀움 : λžŒλ‹€μ™€ λ§ˆμ°¬κ°€μ§€λ‘œ 슀트림 νŒŒμ΄ν”„λΌμΈμ€ μ½”λ“œμ˜ 흐름이 μ—°μ‡„μ μœΌλ‘œ μ΄μ–΄μ§€λ―€λ‘œ, 쀑간 λ‹¨κ³„μ—μ„œ 값을 눈으둜 ν™•μΈν•˜κ±°λ‚˜ λ””λ²„κΉ…ν•˜λŠ” 것이 어렀움. λ””λ²„κ±°λ‘œλŠ” λžŒλ‹€ λ‚΄λΆ€λ₯Ό 일일이 λ“€μ—¬λ‹€ 봐야 ν•˜κ³ , μ½”λ“œμƒμœΌλ‘œλŠ” peek() 같은 λ””λ²„κΉ…μš© 연산을 μΆ”κ°€ν•΄μ•Ό 쀑간값을 λ³Ό 수 있음. λ³΅μž‘ν•œ 슀트림 νŒŒμ΄ν”„λΌμΈμ€ μœ μ§€λ³΄μˆ˜ μ‹œμ— μ΄ν•΄ν•˜λŠ” 데 μ‹œκ°„μ΄ 걸릴 수 있음.

  • μž¬μ‚¬μš© λΆˆκ°€ 및 ν•œκ³„ : 일단 μ΅œμ’… 연산을 톡해 ν•œ 번 μ†ŒλΉ„λœ μŠ€νŠΈλ¦Όμ€ λ‹€μ‹œ μ‚¬μš©ν•  수 μ—†μŒ. ν•„μš”ν•œ 경우 μƒˆλ‘œμš΄ μŠ€νŠΈλ¦Όμ„ λ§Œλ“€μ–΄μ•Ό ν•˜λ―€λ‘œ, λ™μΌν•œ 데이터λ₯Ό 두 번 μˆœνšŒν•΄μ•Ό ν•œλ‹€λ©΄ 차라리 μ²˜μŒλΆ€ν„° κ·Έ 처리λ₯Ό ν†΅ν•©ν•˜κ±°λ‚˜ κ²°κ³Όλ₯Ό μ»¬λ ‰μ…˜μ— λͺ¨μ€ ν›„ μž¬μ‚¬μš©ν•˜λŠ” 방법을 κ³ λ €ν•΄μ•Ό 함. λ˜ν•œ μŠ€νŠΈλ¦Όμ€ 본질적으둜 순차적인 처리 좔상화 에 가깝기 λ•Œλ¬Έμ—, νŠΉμ • μΌ€μ΄μŠ€ (예 : μš”μ†Œλ₯Ό ν•˜λ‚˜ μ²˜λ¦¬ν•˜λ‹€κ°€ μ™ΈλΆ€ 저건에 따라 루프λ₯Ό 전체λ₯Ό 쀑단해야 ν•˜λŠ” 경우 λ“±) μ—μ„œλŠ” 슀트림만으둜 κ΅¬ν˜„μ΄ κΉŒλ‹€λ‘­κ±°λ‚˜ 뢀적합 ν•  수 있음.

  • 병렬 슀트림 μ£Όμ˜μ‚¬ν•­ : 병렬 μŠ€νŠΈλ¦Όμ„ μ‚¬μš©ν•  λ•ŒλŠ” 곡유 μƒνƒœ λ³€κ²½μ΄λ‚˜ μŠ€λ ˆλ“œ μ•ˆμ •μ„± 에 μœ μ˜ν•΄μ•Όν•¨. 잘λͺ»ν•˜λ©΄ 경쟁 쑰건 (race condition) 이 λ°œμƒν•˜κ±°λ‚˜, κΈ°λŒ€ν•˜μ§€ μ•Šμ€ κ²°κ³Όκ°€ λ‚˜μ˜¬ 수 있음. λ˜ν•œ 병렬 처리 자체의 μ˜€λ²„ν—€λ“œ λ•Œλ¬Έμ—, λ°μ΄ν„°λŸ‰μ΄ μΆ©λΆ„νžˆ 크지 μ•ŠμœΌλ©΄ 병렬화가 μ—­ν™”λ₯Ό λ‚Ό 수 있음.

  • λ©”λͺ¨λ¦¬ μ†ŒλΉ„ : μŠ€νŠΈλ¦Όμ€ 원본 데이터λ₯Ό λ³€κ²½ν•˜μ§€ μ•Šκ³  μƒˆλ‘œ 처리 κ²°κ³Όλ₯Ό λ§Œλ“€μ–΄λ‚΄λŠ” νŒ¨ν„΄μ΄λ―€λ‘œ, ν•„ν„°λ§μ΄λ‚˜ λ§€ν•‘ κ²°κ³Όλ₯Ό μƒˆλ‘œμš΄ μ»¬λ ‰μ…˜μœΌλ‘œ μˆ˜μ§‘ν•˜λ©΄ 그만큼 λ©”λͺ¨λ¦¬λ₯Ό μ‚¬μš©ν•¨. 일반적인 λ£¨ν”„μ—μ„œ μ œμžλ¦¬μ—μ„œ μˆ˜μ •(in-place) ν•˜λŠ” 것과 달리, ν•„μš”μ— 따라 μΆ”κ°€ λ©”λͺ¨λ¦¬ 할당이 일어날 수 있음. 특히 λ¬΄ν•œ 슀트림 λ˜λŠ” 맀우 큰 μŠ€νŠΈλ¦Όμ„ 잘λͺ» μ‚¬μš©ν•  경우 λ©”λͺ¨λ¦¬ 뢀쑱에 μ£Όμ˜ν•΄μ•Όν•¨.

Last updated

Was this helpful?