스트림

컨테이너·2025년 11월 5일

JAVA

목록 보기
7/9
post-thumbnail

스트림은 내부 반복자가 있어서 병렬처리가 가능하며, 이를 통해 간결하게 Java를 표현하고자 하여 사용됨을 배웠다.

Stream 1회성

스트림은 1회용으로만 사용할 수 있다. 최종 연산(ex. forEach) 등이 수행된 스트림은 재사용할 수 없다. 재사용하면 java.lang.IllegalStateException 이 발생한다.

Unmobidiable List : 수정 불가 전용 리스트-불변성 보장

/*Unmodifiable List*/
List<String> unmodifiableList = Collections.unmodifiableList(flatList);
System.out.println("unmodifiableList = " + unmodifiableList);
List<String> unmodifiableList2 = List.of("A", "B", "C");
List<String> unmodifiableList3 = Stream.of("A", "B", "C");
//전부 .add() 가 불가능하다.
  • 얘네를 돌리면 에러난다.

Stream 병렬처리

Thread , currentThread()

Thread: 카카오톡의 기능은 채팅. 이는 하나의 기능, 곧 Thread다. Single Thread라고할 때 한 번에 하나 밖에 동작을 못한다. 누군가 채팅을 하는 중 다른 작업을 덮어쓰면 채팅을 못할 것. → 별도로 작업을 할 수 있게끔 Multi Thread 로 여러 작업을 할 수 있게 하였다.

CurrentThread : 현재 어떤 Thread인지 출력해주는 것

void print(s)

private static void print(String str) {
    System.out.println(str + " : " + Thread.currentThread().getName());
}

결과 -> 모든 작업은 기본적으로 main Thread에서 사용된다.

java : main
mariadb : main
html : main
css : main
mybatis : main

main() : 노멀 쓰레드로→ Stream()으로 돌리면 얘도 전부 메인에서 돌아간다.

System.out.println("Normal Stream ================"
list.stream().forEach(Application2::print);//메소드참조

결과

Normal Stream ================
java : main
mariadb : main
html : main
css : main
mybatis : main

maain()에서 parallelStream() 병렬 처리로 사용하면

System.out.println("parallel stream ==============");
list.parallelStream().forEach(Application2::print);
	list.parallelStream().forEach(Application2::print);

아래와 같이 나온다.

parallel stream ==============
html : main
mybatis : main
css : main
mariadb : ForkJoinPool.commonPool-worker-1
java : main
html : main
java : ForkJoinPool.commonPool-worker-1
mariadb : ForkJoinPool.commonPool-worker-3
mybatis : ForkJoinPool.commonPool-worker-2
css : main

Stream 가공


중계연산

중계 연산은 최종 연산 수행 전까지 여러 번 수행할 수 있으며 먼저 일어난 중계 연산의 결과가 파이프라인을 통해 다음 연산으로 전달된다.

  • 예제
IntStream intStream = IntStream.range(1,5);
intStream.filter(i -> (i%2)==0).forEach(i->System.out.print(i+ " "));
  • 결과
    ```java
    0 2 4 6 8 
    ```
    상세 역할메소드
    필터링filter(), distinct()
    변환map(), flatMap()
    제한limit(), skip()
    정렬sorted()
    결과 확인peek()

MAP 예제

  • map → 들어오는 객체/자료형 하나하나 가공을 걸쳐놓음. python의 맵과 비슷
IntStream intStream = IntStream.range(0,10);
intStream
        .filter(i -> (i%2)==0) //짝수 .filter() : 0 2 4 6 8
        //forEach로 넘겨받은 값들이 여기에서 걸려서 Map()에서 하나하나씩 연산을 수행한다.파이썬의 map과 가장 유사하네
        .map(i -> i*5) // 0 20 40 60 80
        .forEach( i -> System.out.print(i + " "));
  • 결과
    0 10 20 30 40 

flatMap

List<List<String>> 이중 중첩 List

List<List<String>> list = Arrays.asList(
        Arrays.asList("JAVA", "SPRING", "SPRINGBOOT"),
        Arrays.asList("java", "spring", "springboot")
);
System.out.println("list = " + list);

flatMap으로 위 두 개의 배열을 합쳐주기

List<String> flatList = list.stream()
        .flatMap(Collection::stream)
        .collect(Collectors.toList());
System.out.println("flatList = " + flatList);
  • 결과
    list = [[JAVA, SPRING, SPRINGBOOT], [java, spring, springboot]]
    
    flatMap->
    
    flatList = [JAVA, SPRING, SPRINGBOOT, java, spring, springboot]

.asList()로 하는 법

List<String> sentence = Arrays.asList(
        "Hello world",
        "Java Stream API",
        "flatMap Example"
);
System.out.println("sentence = " + sentence);
/*잘랐다가 다시 붙이기*/
List<String> words = sentence.stream()
        .flatMap(sentence2 -> Arrays.stream(sentence2.split(" "))) // 자르기
        .toList(); //얘가 다시 list로 바뀐다.
System.out.println("words = " + words);
  • 결과
    words = [Hello, world, Java, Stream, API, flatMap, Example]

sorting

List<Integer> intList = IntStream.of(5,1,3,4,2,6)
      .boxed() //wrapper Class
      .sorted() //기본(오름차순)정렬 -> .sorted((a , b) -> b - a)
      .collect(Collectors.toList()); // list로 변경
System.out.println("intList = " + intList);
  • 결과
    intList = [1, 2, 3, 4, 5, 6]

Calculating

public static void main(String[] args) {

    long count = IntStream.range(1, 10).count(); // 9
    long sum = IntStream.range(1, 10).sum();     // sum : 45

    OptionalInt max = IntStream.range(1, 10).max(); // max = OptionalInt[9]
    OptionalInt min = IntStream.range(1, 10).min(); // min = O[1]

    int OddSum = IntStream.range(1, 10)
            .filter(i -> i % 2 == 1)
            .sum();    // 홀수 합계 25
} 
  • OptionalInt : 결과 없음을 나타내는 명확한 요구가 있는 메소드의 반환 형식으로 사용

reduce()

return의 생략

OptionalInt reduceOneParam =
        IntStream.range(1, 10)
                .reduce((a, b)-> {
                    return Integer.sum(a,b);
                });
  • 위 코드에서 return와 {}을 생략하면 아래와 같이된다.
OptionalInt reduceOneParam =
        IntStream.range(1, 10)
                .reduce((a, b)-> Integer.sum(a,b));
  • Stream 내의 요소들은 [1,2,3,4,5,6,7,8,9]의 내용들을 들고 들어오는 것을 의미함.

    인자가 2개인 경우

int reduceTwoParam = IntStream.range(1,10).reduce(100, Integer::sum);
reduce : 100의 내용과 Integer::sum(45) 의 내용을 모두 더한 것.
System.out.println("reduceTwoparam : " + reduceTwoParam);

결과 : return을 하지 않도록 줄여줌.?

145 -> 100을 이전 값 45에 더해줌.

인자가 3개인 경우

Integer reduceThreeParam = Stream.of(1,2,3,4,5,6,7,8,9,10)
                .parallel().reduce(
                100, Integer::sum, (x,y)->x + y
);
        
System.out.println("reduceThreeParam = " + reduceThreeParam);

결과

reduceThreeParam = 1055
  • .parallel() : 병렬 처리이다. 세 가지의 인자부터는 병렬처리 과정이 필요하게 된다.
  • 위 결과에 대한 이유는 한 번 100이 더해진게 아니라, 각 Integer::sum 마다 하나씩 100을 더해주어, 100 이 총 10번, 55에 1000이 더해진 상태이다.

Matching

1. anyMatch(Predicate<? super T> predicate); : 하나의 조건이라도 만족하는 값이 있는지

List<String> stringList = Arrays.asList("Java", "Spring", "SpringBoot");
boolean anyMatch = stringList.stream().anyMatch(str -> str.contains("z"));
System.out.println("anyMatch = " + anyMatch);

하나라도 매치되는 값이 있는지 찾고, 있으면 true, 없으면 false반환

2. allMatch(...); : 모든게 조건에 부합한가?

boolean allMatch = stringList.stream().allMatch(str -> str.length() > 4);
System.out.println("allMatch = " + allMatch); // stringList에 있는 문자열의 길이가 4보다 큰가? X

3. noneMatch(..); : 모든 조건을 만족하지 않는가?

boolean noneMatch = stringList.stream().noneMatch(str -> str.contains("a"));
System.out.println("noneMatch = " + noneMatch);
profile
백엔드

0개의 댓글