Skip to main content Link Menu Expand (external link) Document Search Copy Copied

JAVA Stream API ํŠน์ง•

Table of contents

  1. Stream ์ด๋ž€!
  2. ์ŠคํŠธ๋ฆผ์€ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค.
  3. ์ŠคํŠธ๋ฆผ์€ ์ผํšŒ์šฉ์ด๋‹ค.
  4. ์ŠคํŠธ๋ฆผ์€ ์ž‘์—…์„ ๋‚ด๋ถ€ ๋ฐ˜๋ณต์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.
  5. ์ง€์—ฐ ์—ฐ์‚ฐ
  6. ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ


Stream API ํ•ต์‹ฌ!

Java8์— ์ถ”๊ฐ€๋œ Stream API๋Š” ๋‹ค๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋‚˜ ์†์‰ฌ์šด ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด์กŒ๋‹ค.

Stream API๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” Collection์˜ ๊ฐœ๋…์ด ์•„๋‹ˆ๋ผ ์–ด๋–ค ์‹œํ€€์Šค ์š”์†Œ๋“ค์˜ ์ˆœ์ฐจ ๋ฐ ๋ณ‘๋ ฌ ์ง‘๊ณ„ ์ž‘์—…์„ ์ง€์›ํ•ด์ฃผ๋Š” API์ด๋‹ค.

ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ์ŠคํŠธ๋ฆผ์ด ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ์ดํ„ฐ์†Œ์Šค๋Š” ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค.(์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ํ›ผ์†ํ•˜์ง€ ์•Š๋Š”๋‹ค.)
  • ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ์ดํ„ฐ๋Š” ์˜ค์ง ํ•œ ๋ฒˆ๋งŒ ์ฒ˜๋ฆฌ๋œ๋‹ค.
  • ์ตœ์ข… ์—ฐ์‚ฐ์ด ์ˆ˜ํ–‰๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์ค‘๊ฐ„ ์—ฐ์‚ฐ์ด ์ˆ˜ํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.
  • ์†์‰ฌ์šด ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ์ง€์›ํ•œ๋‹ค.


Stream ์ด๋ž€!

๋งŽ์€ ์ˆ˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ, ์ปฌ๋ ‰์…˜์ด๋‚˜ ๋ฐฐ์—ด์— ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๊ณ 

์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ์œ„ํ•ด for๋ฌธ๊ณผ Iterator๋ฅผ ์ด์šฉํ•ด์„œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์™”๋‹ค.

์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์ž‘์„ฑ๋œ ์ฝ”๋“œ๋Š” ๋„ˆ๋ฌด ๊ธธ๊ณ  ์•Œ์•„๋ณด๊ธฐ ์–ด๋ ต๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์žฌ์‚ฌ์šฉ์„ฑ๋„ ๋–จ์–ด์ง„๋‹ค.

๋ฐฐ์—ด์„ ์ •๋ ฌํ•  ๋•Œ๋Š”, Arrays.sort()

List๋ฅผ ์ •๋ ฌํ•  ๋•Œ๋Š”, Collections.sort()

๋˜ํ•œ, ๋ฐ์ดํ„ฐ ์†Œ์Šค๋งˆ๋‹ค ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๋‹ค๋ค„์•ผ ํ•œ๋‹ค๋Š” ์ ๋„ ์žˆ๋‹ค.


// String ๋ฐฐ์—ด์ด ์žˆ์„ ๋•Œ, ์ •๋ ฌํ•œ ๋’ค ์›์†Œ๋ฅผ ์ถœ๋ ฅํ•ด์•ผ ํ• ๋•Œ
String [] strArr = {"aaa","ddd","ccc"}

// 1. ์ผ๋ฐ˜์ ์ธ ๋ฐฉ์‹
Arrays.sort(strArr);
for(String str : strArr){
	System.out.println(str)
}

// 2. ์ŠคํŠธ๋ฆผ ๋ฐฉ์‹
Arrays.stream(strArr).sorted().forEach(System.out::println)

์ŠคํŠธ๋ฆผ์€ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ์ถ”์ƒํ™”ํ•˜๊ณ , ์ถ”์ƒํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š”๋ฐ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”์„œ๋“œ๋“ค์„ ์ •์˜ํ•ด๋†“์•˜๋‹ค.

๋ฐ์ดํ„ฐ ์†Œ์Šค๊ฐ€ ๋ฌด์—‡์ด๋˜ ๊ฐ„์— ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋งŒ๋“ค์–ด๋†“๊ธฐ๋งŒ ํ•˜๋ฉด, ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์–ด ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์•„์ง€๊ณ , ์ฝ”๋“œ ๊ฐ€๋…์„ฑ๋„ ๋†’์•„์ง„๋‹ค.

๋˜ํ•œ ์ŠคํŠธ๋ฆผ์—์„œ ์ •์˜ํ•œ ๋ฉ”์„œ๋“œ ๋Œ€๋กœ ๋ถˆํ•„์š”ํ•œ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ๊ณผ์ •์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์–ด, ๋ฉ”๋ชจ๋ฆฌ ๊ด€์ ์—์„œ ํšจ์œจ์ ์ธ ๋ฌธ๋ฒ•์ด๋‹ค.


์ŠคํŠธ๋ฆผ์€ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ŠคํŠธ๋ฆผ์€ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋‹จ์ ์ธ ์˜ˆ๋กœ,

Arrays.stream(strArr).sorted().forEach(System.out::println)

์œ„ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค๊ณ  ํ•ด์„œ, strArr ๋ฐฐ์—ด์— ๋ณ€ํ™”๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.


List<String> collect = Arrays.stream(strArr).sorted().collect(Collectors.toList());

์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€๊ฒฝ์„ ์‹œํ‚จ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด, ์œ„์™€ ๊ฐ™์ด .collect(Collectors.toList()) ์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.


์ŠคํŠธ๋ฆผ์€ ์ผํšŒ์šฉ์ด๋‹ค.

public class Test {
    public static void main(String[] args) {
        String[] strArr = {"aaa", "ddd", "ccc"};
        Stream<String> stream = Arrays.stream(strArr);
        stream.forEach(System.out::println);

        //2๋ฒˆ์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
        stream.forEach(System.out::println);
    }
}

์œ„์™€ ๊ฐ™์ด ์ฒซ๋ฒˆ์งธ forEach() ๋Š” ๋™์ž‘์„ ํ•˜์ง€๋งŒ,

๋‘๋ฒˆ์งธ๋ถ€ํ„ฐ๋Š” ์ด๋ฏธ ์‚ฌ์šฉํ–ˆ๋˜ stream์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.


์ŠคํŠธ๋ฆผ์€ ์ž‘์—…์„ ๋‚ด๋ถ€ ๋ฐ˜๋ณต์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.

๋ฐ˜๋ณต๋ฌธ์„ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์— ์ˆจ๊ธธ ์ˆ˜ ์žˆ์–ด ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

EX) stream().forEach()

void forEach(Consumer<? super T> action){
    Objects.requireNonNull(action);

    for(T t : src){
        action.accpet(T)
    }
}

์ˆ˜ํ–‰ํ•  ์ž‘์—…์„ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์˜ ํ˜•ํƒœ๋กœ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ๋™์ž‘์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„ ์—ฐ์†์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.


์ง€์—ฐ ์—ฐ์‚ฐ

public class Test {
    public static void main(String[] args) {
        Integer[] arr = {1, 2, 3};

        Arrays.stream(arr)
                .peek((i)->System.out.println(i+"์‹คํ–‰"))
                .forEach((i) -> System.out.println(i+"์™„๋ฃŒ"));
    }
}

์œ„ ์ฝ”๋“œ์˜ ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋Š” ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?


1์‹คํ–‰
2์‹คํ–‰
3์‹คํ–‰
1์™„๋ฃŒ
2์™„๋ฃŒ
3์™„๋ฃŒ

์ค‘๊ฐ„ ์—ฐ์‚ฐ๋งˆ๋‹ค ๋ชจ๋“  ์š”์†Œ๋ฅผ ์ˆœํšŒํ•ด์„œ ์—ฐ์‚ฐ์„ ๋งˆ์นœํ›„ ๋‹ค์Œ ์—ฐ์‚ฐ์„ ๋„˜๊ธฐ๋Š” ๋ฐฉ์‹์ธ

์œ„์™€ ๊ฐ™์ด ์‹คํ–‰๋  ๊ฒƒ ๊ฐ™์ง€๋งŒ

1์‹คํ–‰
1์™„๋ฃŒ
2์‹คํ–‰
2์™„๋ฃŒ
3์‹คํ–‰
3์™„๋ฃŒ

์œ„ ๊ฒฐ๊ณผ ์ฒ˜๋Ÿผ, ๊ฐ ์š”์†Œ๋ฅผ ์ตœ์ข…์—ฐ์‚ฐ๊นŒ์ง€ ์ง„ํ–‰ํ•œ๋‹ค.


์–ด๋–ค ๊ฒƒ์ด ํšจ์œจ์ ์ผ์ง€ ์ƒ๊ฐํ•ด๋ณด์ž

for(Integer i : arr){
	print(i)
}

for(Intger i : arr){
	System.out.println(i+"์™„๋ฃŒ")
}

//์ถœ๋ ฅ ๊ฒฐ๊ณผ
1์‹คํ–‰
2์‹คํ–‰
3์‹คํ–‰
1์™„๋ฃŒ
2์™„๋ฃŒ
3์™„๋ฃŒ

for(Integer i : arr){
	print(i)
	System.out.println(i+"์™„๋ฃŒ")
}

//์ถœ๋ ฅ ๊ฒฐ๊ณผ
1์‹คํ–‰
1์™„๋ฃŒ
2์‹คํ–‰
2์™„๋ฃŒ
3์‹คํ–‰
3์™„๋ฃŒ

for๋ฌธ์œผ๋กœ ํ’€์–ด์„œ ์ƒ๊ฐํ•ด๋ณด๋ฉด, ์ฒซ๋ฒˆ์งธ ์ผ€์ด์Šค์˜ ๊ฒฝ์šฐ for๋ฌธ์„ 2๋ฒˆ ๋Œ์ง€๋งŒ, ๋‘๋ฒˆ์งธ ์ผ€์ด์Šค์˜ ๊ฒฝ์šฐ for๋ฌธ์„ 1๋ฒˆ๋งŒ ๋Œ์•„๋„ ๋œ๋‹ค.


public class Test {
    public static void main(String[] args) {
        Integer[] arr = {3, 2, 1};

        Arrays.stream(arr)
                .peek((i)->System.out.println(i+"์‹คํ–‰"))
                .sorted()
                .forEach((i) -> System.out.println(i+"์™„๋ฃŒ"));
    }
}

//์ถœ๋ ฅ๊ฒฐ๊ณผ
3์‹คํ–‰
2์‹คํ–‰
1์‹คํ–‰
//์—ฌ๊ธฐ์„œ sorted์ž‘์—…์ด ์ง„ํ–‰๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ for๋ฌธ์ด ๋ถ„๋ฆฌ๋จ
1์™„๋ฃŒ
2์™„๋ฃŒ
3์™„๋ฃŒ

๐Ÿ“Œ statefulํ•œ ์ค‘๊ฐ„ ์—ฐ์‚ฐ

  • stateful (์ด์ „ ์ƒํƒœ๋ฅผ ์ฐธ์กฐํ•ด์•ผํ•˜๋Š” ์—ฐ์‚ฐ) : distinct, sortedโ€ฆ
  • stateless (์ด์ „ ์ƒํƒœ๋ฅผ ์ฐธ์กฐํ•˜์ง€ ์•Š๋Š” ์—ฐ์‚ฐ) : filter, map, limit, skipโ€ฆ

sorted์™€ ๊ฐ™์€ statefulํ•œ ์—ฐ์‚ฐ์˜ ๊ฒฝ์šฐ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ์ฃผ์–ด์ ธ์•ผ ์—ฐ์‚ฐ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค์ง€๋งŒ, filter์™€ ๊ฐ™์€ statelessํ•œ ์—ฐ์‚ฐ์˜ ๊ฒฝ์šฐ, ํ•œ ์š”์†Œ๋งˆ๋‹ค ๊ฒฐ๊ณผ๋ฅผ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋‹ค.


์œ„์™€ ๊ฐ™์€ ์›๋ฆฌ๋กœ, ์ค‘๊ฐ„ ์—ฐ์‚ฐ์˜ ํ˜•ํƒœ์— ๋”ฐ๋ผ ์—ฐ์‚ฐ ์ˆœ์„œ๊ฐ€ ์ •ํ•ด์ง€๊ณ , forEach()์™€ ๊ฐ™์€ ์ตœ์ข… ์—ฐ์‚ฐ์„ ๋งŒ๋‚˜๊ฒŒ ๋˜๋ฉด ์ค‘๊ฐ„ ์—ฐ์‚ฐ์ด ์‹คํ–‰๋œ๋‹ค.

Arrays.stream(arr)
                .peek((i)->System.out.println(i+"์‹คํ–‰"))
                .sorted();

์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๋Š” ์ตœ์ข… ์—ฐ์‚ฐ ๋ฉ”์„œ๋“œ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.


image-20230404145814820


๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ

์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋ฉด ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๊ฐ€ ์‰ฝ๋‹ค.

์ŠคํŠธ๋ฆผ์— parallel() ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ณ‘๋ ฌ๋กœ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.


// ์ผ๋ฐ˜์ ์ธ ์ฒ˜๋ฆฌ (squential ์ƒ๋žต ๊ฐ€๋Šฅ)
Arrays.stream(arr).sequential().sorted()
                .toArray();

// ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ๋ช…์‹œ์  ์ง€์‹œ
Arrays.stream(arr).parallel().sorted()
                .toArray();

๋ณ‘๋ ฌ์ฒ˜๋ฆฌ์˜ ๊ฒฝ์šฐ ์ž‘์—…์„ ๋‚˜๋ˆ„๊ณ  ๋‹ค์‹œ ํ•ฉ์น˜๋Š” ์‹œ๊ฐ„์ด ํ•„์š”ํ•˜๋ฏ€๋กœ ํ•ญ์ƒ ๋” ๋น ๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

์ŠคํŠธ๋ฆผ ์†Œ์Šค์ธ Collections์ด splitํ•˜๊ธฐ ์‰ฌ์šด ์ž๋ฃŒ๊ตฌ์กฐ์ด์–ด์•ผ ํ•˜๋ฉฐ, ์—ฐ์‚ฐ์ด stateful ํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.

๐Ÿ“Œ LinkedList vs ArrayList

LikedList๋Š” next()๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ์ผ์ผ์ด ์ฐธ์กฐํ•ด์•ผํ•˜๋Š”๋ฐ, ArryList๋Š” index๋ฅผ ํ†ตํ•ด List ๊ฐ’์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด ์ž‘์—…์„ split()ํ•˜๋Š”๋ฐ ๋น„์šฉ์ด ์ ๊ฒŒ ๋“ ๋‹ค.

LikedList ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋‹ค๋ฃฐ๋•, for-loop ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋น ๋ฅด๋‹ค.

๋”ฐ๋ผ์„œ, ํ…Œ์ŠคํŠธ ํ•ด๋ณด๊ณ  ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.


์ฐธ๊ณ ํ•œ ๋ธ”๋กœ๊ทธ

  1. https://bugoverdose.github.io/development/stream-operations/
  2. https://velog.io/@lecharl/JAVA409