한 걸음 두 걸음

자바 JAVA ] 컬렉션 스트림 Stream / 스트림함수 / Optional 본문

Language/Java

자바 JAVA ] 컬렉션 스트림 Stream / 스트림함수 / Optional

언제나 변함없이 2019. 11. 22. 14:51
반응형

스트림이란?

JAVA8부터 업데이트 되었습니다. 람다식을 활용하여 element를 처리할 수 있는 반복자입니다. 입출력 스트림과 다른 스트림을 설명합니다

  1. 스트림방식

    String[] words = ~;
    int count = words.stream()
                  .filter(w -> w.length() > 10 )
                 .count(); 
  2. 병렬처리 스트림

    String[] words = ~;
    int count = words.parallelStream()
                  .filter(w -> w.length() > 10 )
                 .count(); 

파이프라인에 따라 중간연산(filter등)이 모두 연결되어 스트림이 되고(중간연산을 지날 때마다 스트림이 변화합니다.) 이는 최종연산(count)로 전달되어 한번에 처리됩니다.

스트림 특징

컬렉션과 스트림은 모두 연속된 데이터를 처리하고 순차적으로 요소에 접근합니다. 하지만 대부분의 데이터는 컬렉션으로 다뤄지는데 이처럼 스트림을 도입해서 사용하는 이유는
컬렉션은 계산식을 만날 때마다 데이터가 계산되는 등의 비효율이 있는 반면 스트림은 최종 연산이 실행될 때 데이터가 계산되기 때문입니다.

 //list menu ~; 요리 리스트가 들어있는 list객체 
 menu.stream()  // .() .() .()메소드체이닝기법
 ,filter(d -> d.getCalories() > 300) //300칼로리가 넘는 것
 .map(Dish::getName) //300칼로리가 넘는 요소의 이름만 뽑아서 Dish에 저장 
 .limit(3) //3개만 추출 
 .collect(Collectors.toList());

컬렉션은 데이터를 직접 접근하고 변경하고 읽는 등의 일을 주로 하는 반면 스트림은 filter, map등을 활용하여 자료를 람다식으로 표현하기를 좋아합니다.
컬렉션은 메모리에 모든 요소를 올리고(eagerloading) iterator를 사용하여 처리하기때문에 메모리 사용량이 많은 반면 스트림은 계산 시 메모리에 올리면서 처리하므로 메모리 사용량이 줄어듭니다.(한 번에 모든 영상을 다 다운받은 후 플레이할 수 있는 것이 아닌 실시간 스트리밍 등을 생각하시면 좋습니다.)

스트림 종류

java.util패키지에 있는 Stream은 제네릭을 지원하지만, int long double처럼 기본형에 대한 Stream을 만들어 기본자료형에 대한 Stream을 별도로 지원하여 데이터 처리를 돕습니다.
BaseStream - Stream, IntStream, LongStream, DoubleStream

스트림 생성

Collection객체.stream()
Collection객체.parallelStream()
Stream<String> Files.lines()
Arrays.stream()
Random.double() / Random.int() / Random.long()

Stream<String> s = Stream.of("a","b","cc");
Stream<Integer> value = Stream.of(1,2,3);

//무한 스트림
Stream<Double> = Stream.gererate( ()->Math.random() );

//Int[]를 IntStream으로 변환
int[] num = {1,2,3};
IntStream i = Arrays.stream(num);

// iterate사용하여 만든 무한 스트림
Stream<Integer> i = Stream.iterate(0, n-> n+2);

스트림함수

중간연산 함수
filter() : Predicate를 매개변수로 받아 true에 해당하는 요소를 모두 반환합니다.
distinct() : 넘어오는 스트림 중 중복되는 요소를 제거하고 유일한 요소들 반환합니다.
limit(num) : num개 만큼의 요소만 반환합니다. 앞에서부터 3개를 뽑아요.
map(): 들어오는 연산에 매핑되는 value으로 변화시켜줍니다.

최종연산 함수
collect : 최종적으로 온 Stream을 List<>로 만들어서 반환해줍니다.(toList(), toSet(), toMap()등으로 다른 자료구조도 가능합니다. )
foreach : 각 요소에 대해 출력하는 등의 일을 할때 많이 쓴다.
reduce : reduce( (prev,curr) -> prev + curr)인경우, 인접한 데이터간 합을 int로 반환합니다. 이처럼 어떤 연산 수행 후 결과값을 반환합니다.

Optional

Optional Class 사용하기
NullPointException때문에 검사 대상이 Null값인지 확인하는 과정이 필요합니다. 이를 보다 수월하게 사용하기 위해 optional을 사용합니다. java8부터 지원하며, 제네릭 사용 가능합니다.
Optional<클래스이름> o = Optional.of(new 클래스이름() ); //Null을 허용하지 않는 Optional
ifPresent() //NULL이 아닐 때만 실행되는 코드를 만들 때 사용.
람다 함수에서는 널이 아닐 경우객체.orElse();가 실행되도록 만듭니다.

A a = new A();
if( a != null && a.getName().equal("name")){
    System.out.println("OK");
}

->

Optional<A> a = Optional.of(new A());
a.filter( u -> u.getName().equal("name");
 .ifPresent( (u)-> System.out.println("OK"));

이처럼 Null 가능성이 있는 코드에 대해 Optional를 사용합니다.

// orElse(데이터가 없는 경우 실행~ ifPresent(데이터가 있는 경우 실행~)


Stream<String>으로 바꿀 때 Files.lines(객체);를 사용합니다.

반응형