Java

[Java] Stream

Dev_Fuji 2024. 6. 12. 00:23

Stream

  • 컬렉션(List,Set) 및 배열의 요소를 반복 처리하기 위해 스트림을 사용할 수 있다.
public static void main(String[] args) {
    Set<String> set = new HashSet<>();
            set.add("Kim");
    set.add("jong");
    set.add("hong");
    Stream<String> stream = set.stream(); //stream 얻기
    stream.forEach(name-> System.out.println(name)); // 람다 처리
}
  • 내부 반복자로 처리속도가 빠르고 병렬처리에 효율적이다. 컬렉션 내부로 스트림을 주입시킨다.
    => for iterator는 외부 반복자로 바깥쪽에서 반복해서 객체를 가져와야 한다.
  • 람다식으로 다양한 요소 처리를 정의할 수 있다.
  • 한 번만 사용할 수 있고 내부 데이터를 변경시키지 않는다.
  • 중간 처리와 최종 처리를 수행하도록 파이프 라인을 형성할 수 있다.
    => 최종 처리하는 부분이 없으면 중간 처리는 실행하지 않는다
public static void main(String[] args) {
    Person p1 = new Person(40,"Kim");
    Person p2 = new Person(30,"Hong");
    Person p3 = new Person(50,"Jong");
    ArrayList<Person> arrayList = new ArrayList<>();
    arrayList.add(p1);
    arrayList.add(p2);
    arrayList.add(p3);
    Stream<Person> stream = arrayList.stream();
    IntStream intStream = stream.mapToInt(person->person.getAge()); // 중간 처리, 파이프 라인 구조, 객체를 int값으로 매핑
    double avg = intStream.average().getAsDouble();  // 최종 처리, 요소들의 평균값 계산
    System.out.println(avg);
}

> Task :Main.main()
40.0
import java.util.*;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person(40,"Kim");
        Person p2 = new Person(30,"Hong");
        Person p3 = new Person(50,"Jong");
        Person p4 = new Person(60,"Jong");
        Person p5 = new Person(70,"Jong");
        Person p6 = new Person(80,"Cong");
        Person p7 = new Person(90,"Dong");
        Person p8 = new Person(100,"Fong");
        ArrayList<Person> arrayList = new ArrayList<>();
        arrayList.add(p1);
        arrayList.add(p2);
        arrayList.add(p3);
        arrayList.add(p4);
        arrayList.add(p5);
        arrayList.add(p6);
        arrayList.add(p7);
        arrayList.add(p8);
        arrayList.stream()
                .distinct()
                .filter(person->person.age>=40).filter(person -> person.name.startsWith("J")).forEach(person -> System.out.println(person.age+" "+person.name));
    }

}

> Task :Main.main()
50 Jong
60 Jong
70 Jong

 

Stream 기본 사용

리턴 타입 메소드 설명
long count() 요소의 개수
Optional findFirst() 첫 번째 요소
Optional max() 최대 요소
Optional min() 최소 요소
OptionalDouble average() 요소  평균
int, long, double sum() 요소 합

 

Stream 매핑(요소 변환)

  • 스트림의 요소를 다른 요소로 변환하는 중간 처리
리턴타입 메소드(매개변수) 요소 -> 변환요소
Stream<R> map(function<T.R>) T->R
IntStream
LongStream
DoubleStream
mapToInt (function<T>)
mapTolong (function<T> )
mapToDouble (function<T> )
T->int
T->long
T->double
Stream<U> mapToObj (function<U>)
mapToObj  (function<U> )
mapToObj  (function<U> )
int->U
long->U
double->U
UserBookingDtoList(bookingRepository.findPresentBooking(userNumber)
                .stream()
                .map(UserBookingDto::entityToDto) // UserBookingDto의 entityToDto 함수에 stream을 넣는다
                .collect(Collectors.toList())) ; //리스트로 변환 한다.
                
UserBookingDtoList(bookingRepository.findPresentBooking(userNumber)
                .stream()
                .map(dto=> new UserBookingDto.entityToDto(dto))
                .collect(Collectors.toList())) ;
  • 정렬 시 comparator or comparable 인스턴스를 재정의한 객체가 필요하다.
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Comparator<Person> comp = new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o2.age-o1.age;
            }
        };
        Person p1 = new Person(40,"Kim");
        Person p2 = new Person(30,"Hong");
        Person p3 = new Person(50,"Jong");
        Person p4 = new Person(60,"Jong");
        Person p5 = new Person(70,"Jong");
        Person p6 = new Person(80,"Cong");
        Person p7 = new Person(90,"Dong");
        Person p8 = new Person(100,"Fong");
        Person p9 = new Person(110,"Gong");
        Person p10 = new Person(120,"Hong");
        Person p11= new Person(130,"Long");
        Person p12 = new Person(140,"Iong");
        ArrayList<Person> arrayList = new ArrayList<>();
        arrayList.add(p1);
        arrayList.add(p2);
        arrayList.add(p3);
        arrayList.add(p4);
        arrayList.add(p5);
        arrayList.add(p6);
        arrayList.add(p7);
        arrayList.add(p8);
        arrayList.add(p9);
        arrayList.add(p10);
        arrayList.add(p11);
        arrayList.add(p12);
        arrayList.stream()
                .distinct()
                .sorted(comp)
        .forEach(person -> System.out.println(person.age+" "+person.name));
        //위와 동일
        arrayList.stream()
                .distinct()
                .sorted((s1,s2)-> Integer.compare(s2.age,s1.age))
        .forEach(person -> System.out.println(person.age+" "+person.name));
        //Person에 Comparable을 재정의하면 sorted에 comparator 를 재정의하지 않아도 된다.
         arrayList.stream()
                .distinct()
                .sorted()
        .forEach(person -> System.out.println(person.age+" "+person.name));
    }

}


> Task :Main.main()
140 Iong
130 Long
120 Hong
110 Gong
100 Fong
90 Dong
80 Cong
70 Jong
60 Jong
50 Jong
40 Kim
30 Hong

 

Stream 요소 수집

  • 최종 처리 메소드인 collect를 통해 제공한다.
리턴타입 메소드 인터페이스
R collect(Collector<T,A,R> collector)
T= 요소, A= 누적기,
R=요소가 저장될 컬렉션
collect(Collector.toList())
Stream
arrayList.stream()
                .distinct()
                .sorted((s1,s2)-> Integer.compare(s2.age,s1.age))
        		.toList();
// 위와 동일
arrayList.stream()
                .distinct()
                .sorted((s1,s2)-> Integer.compare(s2.age,s1.age))
                .collect(Collectors.toList());