ν‹°μŠ€ν† λ¦¬ λ·°

πŸ”Ž Stream

μžλ°” 8μ—μ„œ μΆ”κ°€λœ 슀트림(Stream)은 λžŒλ‹€λ₯Ό ν™œμš©ν•  수 μžˆλŠ” 기술 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€.

μžλ°” 8 μ΄μ „μ—λŠ” λ°°μ—΄ λ˜λŠ” μ»¬λ ‰μ…˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ‹€λ£¨λŠ” 방법은 for λ˜λŠ” foreach 문을 λŒλ©΄μ„œ μš”μ†Œ ν•˜λ‚˜μ”©μ„ κΊΌλ‚΄μ„œ λ‹€λ£¨λŠ” λ°©λ²•μ΄μ—ˆμŠ΅λ‹ˆλ‹€.

κ°„λ‹¨ν•œ 경우라면 μƒκ΄€μ—†μ§€λ§Œ 둜직이 λ³΅μž‘ν•΄μ§ˆμˆ˜λ‘ μ½”λ“œμ˜ 양이 λ§Žμ•„μ Έ μ—¬λŸ¬ 둜직이 μ„žμ΄κ²Œ 되고, λ©”μ†Œλ“œλ₯Ό λ‚˜λˆŒ 경우 루프λ₯Ό μ—¬λŸ¬ 번 λ„λŠ” κ²½μš°κ°€ λ°œμƒν•©λ‹ˆλ‹€.

 

μŠ€νŠΈλ¦Όμ€ 'λ°μ΄ν„°μ˜ 흐름' μž…λ‹ˆλ‹€.

λ°°μ—΄ λ˜λŠ” μ»¬λ ‰μ…˜ μΈμŠ€ν„΄μŠ€μ— λ©”μ†Œλ“œ μ—¬λŸ¬ 개λ₯Ό μ‘°ν•©ν•΄μ„œ μ›ν•˜λŠ” κ²°κ³Όλ₯Ό ν•„ν„°λ§ν•˜κ±°λ‚˜ κ°€κ³΅λœ κ²°κ³Όλ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

λ˜ν•œ λžŒλ‹€(Lambda)λ₯Ό μ΄μš©ν•΄μ„œ μ½”λ“œμ˜ 양을 쀄이고 κ°„κ²°ν•˜κ²Œ ν‘œν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

즉, λ°°μ—΄κ³Ό μ»¬λ ‰μ…˜μ„ ν•¨μˆ˜ν˜•μœΌλ‘œ μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

πŸ“Œ Iterator와 Stream의 μ½”λ“œ 비ꡐ

μžλ°” 6 μ΄μ „κΉŒμ§€λŠ” ArrayListμ—μ„œ μš”μ†Œλ₯Ό 순차적으둜 μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄ IteratorλΌλŠ” 반볡자λ₯Ό μ•„λž˜μ™€ 같이 μ‚¬μš©ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
Iterator<Integer> iter = list.iterator();
while(iter.hasNext()) {
    int num = iter.next();
    System.out.prinln("κ°’: " + num);
}

ν•˜μ§€λ§Œ μžλ°” 8λΆ€ν„° μΆ”κ°€λœ μŠ€νŠΈλ¦Όμ„ μ‚¬μš©ν•˜λ©΄ 훨씬 λ‹¨μˆœν•˜κ²Œ μ½”λ”©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μžλ°” 8 이후에 μž‘μ„±λœ μ½”λ“œμ—μ„œλŠ” λžŒλ‹€μ‹μœΌλ‘œ 기술된 λΆ€λΆ„μ—μ„œλŠ” κΌ­ Stream이 λ“€μ–΄κ°€λŠ” 뢀뢄이 λ§Žμ€λ°μš”.

μ•„λž˜μ—μ„œλŠ” stream() λ©”μ†Œλ“œλ‘œ 슀트림 객체λ₯Ό 얻은 ν›„

foreach() λ©”μ†Œλ“œλ₯Ό 톡해 ArrayList에 μžˆλŠ” μš”μ†Œλ“€μ„ ν•˜λ‚˜μ”© 좜λ ₯ν•©λ‹ˆλ‹€.

ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
list.stream().forEach(num -> System.out.println("κ°’: " + num));

μ½”λ“œκ°€ ꡉμž₯히 짧아지죠..?

 

❓ 슀트림(Stream) μ‚¬μš©λ²•

1. λ°°μ—΄μ—μ„œμ˜ 슀트림 ν™œμš©

// String λ°°μ—΄
String[] strArray = {"홍길동", "μ΄μˆœμ‹ ", "강감찬"};
Stream<String> strStream = Arrays.stream(strArray);
strStream.forEach(e -> System.out.println(e + ","));

// int λ°°μ—΄
int[] intArray = {1, 2, 3, 4, ,5};
IntStream intStream = Arrays.stream(intArray);
intStream.forEach(e -> System.out.println(e + ","));

 

 

2. ArrayListμ—μ„œμ˜ 슀트림 ν™œμš©

ArrayList νƒ€μž…μ—μ„œλŠ” λ°”λ‘œ stream()μ΄λΌλŠ” λ©”μ†Œλ“œλ₯Ό 톡해 stream νƒ€μž…μœΌλ‘œ λ°”κΏ”μ£Όμ–΄ λ°”λ‘œ stream의 λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

ArrayList<Integer> datas = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));
datas.stream().forEach(e -> System.out.println(e));

 

❓ 슀트림(Stream) λŒ€ν‘œ λ©”μ†Œλ“œ

1. forEach() : 값을 ν•˜λ‚˜μ”© κ°€μ Έμ˜¨λ‹€

forEach() λ©”μ†Œλ“œλ₯Ό ν†΅ν•΄μ„œ ArrayList에 λ‹΄μ•„λ‘μ—ˆλ˜ μ•„μ΄ν…œμ„ ν•˜λ‚˜μ”© κ°€μ Έμ˜€κ²Œ λ©λ‹ˆλ‹€.

이 μ•„μ΄ν…œμ„ ν•˜λ‚˜μ”© κ°€μ Έμ˜¨λ‹€κ³  μƒκ°ν•˜κ³  μ•„μ΄ν…œμ„ μ²˜λ¦¬ν•΄ μ£Όλ©΄ λ©λ‹ˆλ‹€.

ArrayList<Integer> datas = new ArrayList<Integer>(Arrays.asList(10, 20, 30, 40, 50));
datas.stream().forEach(data -> System.out.println(data));

// forEach()λŠ” stream을 μƒλž΅ν•˜κ³  λ°”λ‘œ μ‚¬μš© κ°€λŠ₯
datas.forEach(data -> System.out.println(data));

 

βž• 클래슀의 λ©”μ†Œλ“œ μ°Έμ‘°

μžλ°”μ—μ„œλŠ” 클래슀λ₯Ό μ‚¬μš©ν•΄μ„œ 직접 λ©”μ†Œλ“œλ₯Ό μ°Έμ‘°μ‹œμΌœ λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ΄λ•Œ "::"기호λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

예λ₯Ό λ“€λ©΄

System.out.println -> System.out::println

처럼 μ‚¬μš©μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€.

λ‹¨μˆœ 반볡문 좜λ ₯으둜 μ˜ˆμ‹œ μ½”λ“œλ₯Ό μž‘μ„±ν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

ArrayList<Integer> datas = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));
datas.forEach(System.out::println);

λ©”μ†Œλ“œμ˜ μ°Έμ‘°λŠ” κ°€μ Έμ˜¨ 값을 λ°”λ‘œ μ΄μš©ν•  λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.

μœ„μ™€ 같은 κ²½μš°μ—λ„ forEachλ₯Ό 톡해 μ•„μ΄ν…œμ„ κ°€μ Έμ˜€μžλ§ˆμž λ°”λ‘œ System.out.println ν•  κ²ƒμ΄μ—ˆκΈ° λ•Œλ¬Έμ— μœ„μ™€ 같이 μ°Έμ‘°ν˜•μœΌλ‘œ μ‚¬μš©μ΄ κ°€λŠ₯ν–ˆλ˜ κ²ƒμž…λ‹ˆλ‹€.

 

μ΄μ–΄μ§€λŠ” Stream λ©”μ†Œλ“œ μ˜ˆμ œμ—μ„œ 계속 μ‚¬μš©ν•  μ˜ˆμ •μ΄λ‹ˆ μ°Έκ³ ν•˜μ‹œλ©΄ μ’‹κ² μŠ΅λ‹ˆλ‹€ :)

 

2. map() : κΈ°μ‘΄ κ°’ μ‘°μž‘

forEach()와 같이 μ•„μ΄ν…œμ„ ν•˜λ‚˜μ”© κ°€μ Έμ˜€λŠ”λ° λ°˜ν™˜μ„ ν•  수 μžˆμ–΄ 값을 μ‘°μž‘ν•  λ•Œ 자주 μ‚¬μš©λ˜λŠ” λ©”μ†Œλ“œμž…λ‹ˆλ‹€.

μ•„λž˜ μ½”λ“œλŠ” 기쑴에 μžˆλŠ” 값에 2배인 값을 좜λ ₯ν•˜λŠ” μ˜ˆμ œμž…λ‹ˆλ‹€.

ArrayList<Integer> datas = new ArrayList<Integer>(Arrays.asList(10, 20, 30, 40, 50));
datas.stream().map(data -> data*2).forEach(System.out::println);

 

3. IntStream.range(inclusive, exclusive), IntStream.rangeClosed(inclusive, inclusive) : λ²”μœ„λ₯Ό λ§Œλ“€μ–΄λ‚Έλ‹€

range() λ©”μ†Œλ“œλŠ” μš°λ¦¬κ°€ 일일이 for문에 μΈλ±μŠ€κ°’μ„ λ„£κ³  λŒλ €μ„œ μ‚¬μš©ν•  것없이

λ°”λ‘œ ν•œ 쀄이면 μ§€μ •ν•œ λ²”μœ„λŒ€λ‘œ stream 객체λ₯Ό λ§Œλ“­λ‹ˆλ‹€.

μ•„λž˜ μ˜ˆμ œλŠ” 1~10κΉŒμ§€λ₯Ό ArrayList에 λ‹΄λŠ” μ˜ˆμ œμž…λ‹ˆλ‹€.

ArrayList<Integer> datas = new ArrayList<Integer>();
IntStream.rangeClosed(1, 10).forEach(datas::add);

 

4. String.chars() : λ¬Έμžμ—΄μ€ IntStream으둜 λ³€ν™˜(μ•„μŠ€ν‚€μ½”λ“œκ°’μœΌλ‘œ 듀어감)

chars()λŠ” μ£Όμ˜ν•΄μ„œ 써야 ν•˜λŠ” 것이 λ¬Έμžμ—΄μ—μ„œ char ν•˜λ‚˜ν•˜λ‚˜λ₯Ό IntStream으둜 λ¦¬ν„΄ν•˜κΈ° λ•Œλ¬Έμ—

λ“€μ–΄κ°€λŠ” 값이 char 이더라도 λ§ˆμ§€λ§‰μ— λ‹€μ‹œ κ°•μ œ ν˜•λ³€ν™˜μ„ ν•΄μ€˜μ•Ό ν•©λ‹ˆλ‹€.

String data = "ABC";
System.out.println(data.chars());

좜λ ₯ κ²°κ³Ό

λ‹€μŒ μ˜ˆμ œλŠ” λ“€μ–΄μ˜¨ λ¬Έμžμ—΄μ„ ν•˜λ‚˜ν•˜λ‚˜μ˜ char둜 좜λ ₯ν•˜λŠ” μ˜ˆμ œμž…λ‹ˆλ‹€. (λ§ˆμ§€λ§‰μ— κ°•μ œ ν˜•λ³€ν™˜μ„ ν•΄μ•Όν•˜λŠ” 것을 μžŠμ§€λ§™μ‹œλ‹€!)

String data = "ABC";
data.chars().forEach(c -> System.out.println((char)c));

좜λ ₯κ²°κ³Ό

 

5. filter() : 쑰건식이 true일 λ•Œλ§Œ μΆ”μΆœ(리턴)

filter() λ©”μ†Œλ“œ μ•ˆμ—λŠ” 쑰건식을 μž‘μ„±ν•΄μ„œ ν•˜λ‚˜μ”© λ“€μ–΄μ˜€λŠ” 값이 쑰건식에 true일 κ²½μš°μ—λ§Œ λ‹€μŒμœΌλ‘œ λ„˜μ–΄κ°‘λ‹ˆλ‹€.

쑰건식에 false인 κ²½μš°μ—λŠ” λ‹€μŒμœΌλ‘œ λ„˜μ–΄κ°€μ§€ λͺ»ν•©λ‹ˆλ‹€.

λ‹€μŒ μ˜ˆμ œλŠ” 0~9κΉŒμ§€μ˜ 숫자 쀑 μ§μˆ˜λ§Œμ„ 좜λ ₯ν•˜λŠ” μ˜ˆμ œμž…λ‹ˆλ‹€.

IntStream.range(0, 10).filter(e -> e%2==0).forEach(System.out::println);

 

6. sorted() : μ •λ ¬

sorted() λ©”μ†Œλ“œλŠ” 정렬을 ν•΄μ€λ‹ˆλ‹€.

κ·Έλ ‡μ§€λ§Œ 원본을 κ±΄λ“œλ¦¬μ§€ μ•ŠλŠ”λ‹€λŠ” 점을 κΌ­ μ•Œκ³  μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€!

ArrayList<Integer> datas = new ArrayList<Integer>(Arrays.asList(1, 6, 5, 7, 2));
datas.stream().sorted().forEach(System.out::print); // 12567

// 원본을 κ±΄λ“œλ¦¬μ§€ μ•ŠμŒ
System.out.println(datas); // [1, 6, 5, 7, 2]

 

7. collect() : κ²°κ³Όλ₯Ό λ‹€μ–‘ν•œ νƒ€μž…μœΌλ‘œ 리턴해쀀닀

μ—¬λŸ¬ 가지 μ˜ˆμ œκ°€ μžˆκ² μ§€λ§Œ, μ•„λž˜ μ˜ˆμ œλŠ” μ‹œ, λΆ„, μ΄ˆκ°€ ArrayList둜 μ£Όμ–΄μ‘Œμ„ λ•Œ 이 μ•„μ΄ν…œλ“€μ„ μ‘°ν•©ν•΄μ„œ μ‹œ:λΆ„:초 λ¬Έμžμ—΄λ‘œ λ§Œλ“œλŠ” μ˜ˆμ œμž…λ‹ˆλ‹€.

ArrayList<Integer> datas = new ArrayList<Integer>(Arrays.asList(10:30:15));
System.out.println(datas.stream().map(String::valueOf).collect(Collectors.joining(":"))); // 10:30:15

βž• String.valueOf() : λ“€μ–΄μ˜€λŠ” 객체λ₯Ό String 객체둜 λ³€ν™˜ν•˜λŠ” 역할을 ν•©λ‹ˆλ‹€.

 

 

728x90
LIST