Language/Java

[Java] Stream

LightSource 2022. 5. 19. 21:09

Stream : 데이터 가공

*모든 예문에는 lombok이 사용되었습니다

Stream

  • 스트림은 컬렉션의 저장요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해주는 반복자
  • 중간처리 메서드 : Stream을 리턴
  • 최종처리 메서드 : int형, String형 ......
  • 중간처리 메서드가 Stream을 리턴하기 때문에 메서드 체이닝을 통해 데이터 가공이 가능하다.
  • 메서드 체이닝한 모습을 스트림의 파이프라인이라고 표현한다.
  • 합계,평균값,카운팅,최대값,최소값 등의 최종처리를 파이프라인으로 해결

Stream 생성하기

  1. 컬렉션으로 부터 스트림 얻기
import java.util.stream.*;
import java.util.*;
import lombok.*;
class Main{
    public static void main(String args[]){
        List<Person> list1=Arrays.asList(
            new Person("홍길동",25),
            new Person("김길동",28),
            new Person("박길동",23)
        );
        List<Person> list2=new ArrayList<>();
        list2.add(new Person("송길동",21));
        list2.add(new Person("이길동",29));

        Stream<Person> s1=list1.stream();           //리스트를 Person형인 Stream으로 변경
        Stream<Person> s2=list2.stream();           //리스트를 Person형인 Stream으로 변경
        s1.forEach( System.out::println );          //Stream의 최종 처리 메서드인 forEach를 
        s2.forEach( System.out::println );          //사용해서 list의 데이터들을 출력
    }
}
@Data
@AllArgsConstructor
class Person{
    String name;
    int age;
}
  • 컬렉션.Stream() 으로 Stream을 생성한다.
  1. 배열로부터 스트림 얻기
import java.util.stream.*;
import java.util.*;
import lombok.*;
class Main{
    public static void main(String args[]){
        int[] a1={1,2,3};
        String[] a2={"aa","bb","cc"};
        Person[] a3={
            new Person("홍길동",25),
            new Person("김길동",28),
            new Person("박길동",23)
        };
        IntStream s1=Arrays.stream(a1);       // 자료형이 Int인 배열의 Stream객체를 생성
        Stream<String> s2=Arrays.stream(a2);    // 자료형이 String인 배열의 Stream객체를 생성
        Stream<Person> s3=Arrays.stream(a3);  // 자료형이 Person인 배열의 Stream객체를 생성
        s1.forEach( System.out::println );    //Stream의 최종 처리 메서드인 forEach를 
        s2.forEach( System.out::println );    //사용해서 배열의 데이터들을 출력
        s3.forEach( System.out::println );
    }
}
@Data
@AllArgsConstructor
class Person{
    String name;
    int age;
}
  • Arrays.stream(배열) 으로 Stream을 생성한다.
  • Int[]형인 배열은 IntStream으로 생성한다.
  1. 숫자 범위로부터 스트림 얻기
import java.util.stream.*;
class Main{
    public static void main(String args[]){
        System.out.println(
            IntStream.rangeClosed(1,10).sum()       //55
        );
    }
}
  • IntStream을 생성
  • 메서드 체이닝을 통해 중간처리 메서드인 rangeClosed(start int, end int)과
  • 최종 처리메서드인 sum()을 통해서 1부터 10까지의 합을 출력한다.

필터링 : 조건을 통해서 원하는 자료로 정제

Stream filter(Predicate<? super T> predicate) : 조건필터링

Stream distinct() : 중복제거

import java.util.*;
import lombok.*;
class Main{
    public static void main(String args[]){
        List<Person> list=Arrays.asList(
            new Person("홍길동",20,"F"),
            new Person("홍길동",20,"F"),
            new Person("홍길동",20,"M"),
            new Person("김길동",35,"M"),
            new Person("이길동",40,"F"),
            new Person("김길동",40,"F"),
            new Person("박길동",50,"M")
        );
        list.stream()
            .distinct()
            .filter( p->p.getGender()=="F" )
            .forEach( System.out::println );
    }
}
@AllArgsConstructor
@Data
class Person{
    private String name;
    private int age;
    private String gender;
  • distinct() : 중간처리 메서드, 중복되는 자료(new Person("홍길동",20,"F"))를 제거
  • filter()
    • 중간처리 메서드
    • 조건을 필터링 해주는 메서드
    • 매개변수 Predicate : true 또는 false를 리턴하는 boolean 형이 들어가야 한다.

매핑 : 스트림의 요소를 다른 요소로 대체하는 작업

Stream map(Function<? super T,? extends R> mapper) : T에서 R로 변경

  • map() 메서드
import java.util.stream.*;
class Main{
    public static void main(String args[]){
        Stream<String> names=Stream.of("fsaf","fdsafsa","dsa");
        names.map( str-> str.length() )
                .forEach( size->System.out.println("문자열의길이:"+size) );
    }
}

import java.util.stream.*;
class Main{                                          //람다식을 메서드 참조형으로 바꾼형태
    public static void main(String args[]){
        Stream<String> names=Stream.of("fsaf","fdsafsa","dsa");
        names.map( String::length )    
                .forEach( size->System.out.println("문자열의길이:"+size) );
    }
}
  • Stream.of(생성하려는 객체) : of에 매개변수로 객채를 입력하면 스트림객체로 생성해줌
  • String형인 Stream요소를 map을 이용해서 Stream의 요소를 str.length()로 바꿈
  • .map( str-> str.length() )
  • .map( String::length )

IntStream mapToInt(ToIntFunction<? super T> mapper) : T를 int형으로 변경

  • mapToInt() 메서드
import java.util.function.*;
import java.util.*;
import lombok.*;
class Main{
    public static void main(String args[]){
        List<Student> list=Arrays.asList(
            new Student("홍길동",50),
            new Student("김길동",90),
            new Student("박길동",100),
            new Student("송길동",70)
        );
        System.out.println(
            list.stream()
                .mapToInt( Student::getScore )
                .sum()
        );
    }
}
@AllArgsConstructor
@Getter
class Student{
    String name;
    int score;
}
  • mapToInt형을 이용해서 list의 요소인 Student들을 int 형인 Student.getscore로 변경
  • mapToInt( stu -> stu.getScore )
  • mapToInt( Student::getScore )

Stream flatMap(Function<? super T,? extends Stream<? extends R>> mapper) : Stream의 요소가 복수의 배열일 경우 배열의 요소를 다 가지는 새로운 Stream객체를 생성한다.
flatMap() 메서드

import java.util.*;
import java.util.stream.*;
class A{
    public static void main(String args[]){
        String[] a={"aa","bb","cc"};
        String[] b={"dd","ee"};
        Stream<String[]> s1=Stream.of(a,b);
        s1.forEach(System.out::println);
        Stream<String> s2=Stream.of(a,b).flatMap(Arrays::stream);
        s2.forEach(System.out::println);
    }
}
  • String[] a와 String[] b가 Stream의 요소
  • flatMap 매서드를 이용해서 a와 b의 요소를 가지는 새로운 Stream을 생성해서 forEach메서드로 요소를 출력

정렬 : Stream의 요소들을 정렬

Stream sorted()

sorted() 메서드

import java.util.stream.*;
class Main{
    public static void main(String args[]){
        Stream<String> names=Stream.of("홍길동","김길동","박길동","송길동","이길동");
        names.sorted()
                .forEach( System.out::println );
    }
}
  • sorted() 메서드를 이용해서 “x길동” 의 이름을 글자순으로 정렬 할 수있다.

 

Stream sorted(Comparator<? super T> comparator) : sorted메서드에 매개변수로 Comparator를 넘길수 있다.

  • sorted메서드에 매개변수로 Comparator를 넘길수 있다.
import java.util.Comparator;
import java.util.stream.*;

class Main {
   public static void main(String args[]) {
      Stream<String> names = Stream.of("홍길동", "김길동", "박길동", "송길동", "이길동");
      names.sorted(new Descending())             //Sorted(Comparator)
            .forEach(System.out::println);
   }
}

class Descending implements Comparator<String> {
   public int compare(String o1, String o2) {
      return o2.codePointAt(0) - o1.codePointAt(0);

   }
}
  • 비교하는 연산자인 Comparator의 compare메서드를 오버라이딩
  • compare메서드는 원래 o1 - o2 = 음수 또는 양수 를 이용해서 정렬 → 오름차순 정렬
  • o2 - o1 으로 변경 및 codePointAt 메서드로 한글의 내림차순으로 compare메서드를 오버라이딩
반응형