본문 바로가기

JAVA/기본

Stream 스트림

Stream 스트림 

// 기본타입 stream : IntStream, LongStream, DoubleStream
// 참조타입 stream : Stream<T>


List<String> list = List.of("java", "spring", "css", "react");

// stream 알기 전 반복문
for(String item : list){
    System.out.println(item);
}

// stream 사용
Stream<String> stream = list.stream();

// 메소드
// 중간연산 : intermediate operation, 중간에 여러번
// 최종연산 : terminal operation, 마지막에 한번

// 특징
// 최종연산 후 stream 재사용 불가
stream.count(); 
stream.count(); // 최종 연산 두번 하면 오류 발생

// 다시 만들어서 사용해야함
Stream<String> stream2 = list.stream();
stream2.count();

// 최종연산 시 중간연산을 같이 처리함
stream.limit(5); // Ctrl + Q(api문서) 눌러보면 중간연산 intermediate operation 인지 확인
stream.count(); // 최종연산


// 이게 stream 방식
list.stream()
        .map(e -> e+e) // 중간연산
        .filter(e -> e.length() > 1) // 중간연산
        .count(); // 최종연산

// 풀어쓰면 이런모양
Stream<String> stream = list.stream();
Stream<String> stream1 = stream.map(e -> e + e); // 중간연산
Stream<String> stream2 = stream1.filter(e -> e.length() > 1); // 중간연산
Long count = stream.count(); // 최종연산

중간연산 메소드

distinct() - 중복 된 수를 하나만 남기고 제거

ist<Integer> list = List.of(3,5,3,9,3,13,15);

// distinct() : 중복 된 수를 하나만 남기고 제거
Long cnt = list.stream()
        .distinct()
        .count();

System.out.println(cnt); // 5

 

sorted() - 내림차순 정렬

List<Integer> list = List.of(3,5,3,9,3,13,15);

// sorted : 내림차순 정렬
list.stream()
        .sorted()
        .forEach(System.out::println);

 

limit() - 앞에서 부터 원하는 순서 까지 짜르기

var list = List.of(3,5,10,13,1,0,-3);

// limit : 앞쪽에 몇 개만 짜른다
list.stream()
        .limit(3)
        .forEach(System.out::println); // 3, 5, 10

 

skip() - 건너뛰는 메소드

// skip : 몇 개를 건너 뛸건지
list.stream()
        .skip(3)
        .forEach(System.out::println);

 

filter() - true 다음 stream 으로 넘겨줌 / false 다음 stream으로 안넘김

// filter : true인 경우 다음 stream으로 넘긴다, false면 안넘김
list.stream()
        .filter(e -> e%2 == 0)          // 짝수인 경우에 다음 stream으로 넘긴다
        .forEach(System.out::println);

 

map(매핑)  - 어떤 요소를 어떤 요소로 변환

// map(mapping / NOT interface Map!) : 뭔가를 넣어서 뭔가로 받을때 
list.stream()
        .map(x -> 10)
        .forEach(System.out::println);

System.out.println("음수로 바꿔서 출력");
list.stream()
        .map(x -> -x)
        .forEach(System.out::println);

System.out.println("두배한 값으로 출력");
list.stream()
        .map(x -> x*2)
        .forEach(System.out::println);

System.out.println("제곱값 출력");
list.stream()
        .map(x -> x*x)
        .forEach(System.out::println);

최종연산

 

forEach() - 람다식으로 안에 반복적으로 수행할 코드 작성

// forEach : 람다식으로 안에 반복해서 수행할 코드 작성 
// 지금은 안에 값을 하나씩 출력
list.stream()
        .forEach(System.out::println);

 

reduce - 가지고 있는 원소를 하나로 압축(합계, 평균, String 문자열 연결 등등)

var list = List.of(5,1,3);

// reduce : 여러원소를 하나로 압축
// 보통 합계, 평균, String 문자열 연결 등에 사용됨
list.stream()
        .reduce(0,(r,e)-> 0); // 0(시작 값) (reduce 된 값, 매개변수의 값)


System.out.println("모든 값 더하기");
Integer reduce1 = list.stream()
        .reduce(0,(r,e)-> r+e); 
System.out.println(reduce1); //9
//작동 방식
//r e
//0,5 / 첫번째만 r = 초기값(0)
//5,1
//6,3
//9

reduce 예제

System.out.println("최대값 구하기");
Integer reduce2 = list.stream()
        .reduce(Integer.MIN_VALUE, (r, e) -> Math.max(r,e));
System.out.println(reduce2);

System.out.println("최소값 구하기");
Integer reduce3 = list.stream()
        .reduce(Integer.MAX_VALUE, (r,e)-> Math.min(r,e));
System.out.println(reduce3);

System.out.println("문자열 이어붙이기");
var list2 = List.of("ja","va"," is ", "g", "ood");
String reduce4 = list2.stream()
        .reduce("", (r,e) -> r.concat(e));
System.out.println(reduce4);

 

Collect - 최종연산으로 Collection 타입으로 변환

List<String> list = List.of("java", "spring", "css", "html");

// collect : 마지막으로 값을 List, Set, Map 등 Collection 타입으로 변환

// list의 문자열 길이를 List로 변환
List<Integer> res2 = list.stream()
        .map(String::length)
        .collect(Collectors.toList());
System.out.println("List변환: " + res2);

// list의 문자열 길이를 Set으로 변환
Set<Integer> res3 = list.stream()
        .map(String::length)
        .collect(Collectors.toSet());
System.out.println("Set변환: " + res3);

// list의 문자열 길이를 Map으로 변환
// 예시) java(K) : 4(V)
Map<String, Integer> res4 = list.stream()
        .collect(Collectors.toMap(x -> x, String::length)); // 매개변수를 받아 왼쪽이 Key, 오른쪽이 Value
System.out.println("Map변환: " + res4);

Collectors.groupingBy - Map형태로 Key의 따른 Value분류

List<String> list = List.of(
        "java",
        "css",
        "spring",
        "html",
        "jsp",
        "vue",
        "jquery"
);

// grouping : 예를 들어 위 list들을 구분하고 싶은데 list.length 기준으로 구분하고 싶다
// K  :  V
// 3 이면 css, jsp, vue
// 4 이면 java, html
// 타입은 Map<T,List<T>> 형태로 리턴됨
Map<Integer, List<String>> collect = list.stream()
        // Collectors.groupingBy() 괄호안에 들어갈 값은 Key 기준으로 할 값이다.
        .collect(Collectors.groupingBy(String::length));  // Key 기준을 원소의 길이로 하겠다

System.out.println(collect);

// map의 각 key 와 value를 보고 싶으면 enrtySet과 stream을 이용해 출력
collect.entrySet().stream()
        .forEach(e -> System.out.println(e.getKey() + " : " + e.getValue()));

Collectors.groupingBy - Value 값을 reduce한 형태 (Map <K,V>) 

// Value 값을 List형태가 아닌 reduce 된 형태로 받을 수 있음
Map<Integer, Long> collect = list.stream()
        // Key를 입력하고 Value 쪽에 Collectors.메소드 입력하면 reduce된 Value 값을 얻을 수 있음
        .collect(Collectors.groupingBy(String::length, Collectors.counting()));

collect.entrySet().stream()
        .forEach(e -> System.out.println(e.getKey() + " : " + e.getValue()));
    // 3 : 3
    // 6 : 2
    // 4 : 2
    
    
    
//다른 예제

List<Student> list = new ArrayList<>();
  
list.add(new Student("홍길동", "남", 92));
list.add(new Student("김수영", "여", 87));
list.add(new Student("감자바", "남", 95));
list.add(new Student("오해영", "여", 93));

// 성별에 따른 평균 구하기
Map<String, Double> map = list.stream()
        .collect(Collectors.groupingBy(s->s.getSex(), Collectors.averagingDouble(s->s.getScore())));

System.out.println(map);

그 외 메소드

 

반응형