[Java] Stream을 생성하는 다양한 방법

Jerry·2021년 9월 14일
0

language & framework study

목록 보기
27/28

1. 배열 스트림

Arrays.stream을 이용하여 배열을 스트림으로 변환

참조타입 배열을 변환

제네릭으로 참조타입 T의 배열을 파라미터로 받아서 Stream으로 변환 후 리턴

  • static Stream stream(T[] array)

  • [유사 매소드] static Stream stream(T[] array, int startInclusive, int endExclusive)

    배열의 index가 startInclusive <=index<endExclusive 인 원소들로만 stream 생성

int, long, double(primitive 타입 중 일부) 배열을 변환

autoboxing 하지 않고 원시타입을 다루는 스트림으로 반환

  • static DoubleStream stream(double[] array)
  • static IntStream stream(int[] array)
  • static LongStream stream(long[] array)

예제 - 배열의 스트림 변환

System.out.println("-- 참조타입(String) 스트림 변환 -- ");
String[] strs={"abc","def","ghi","jkl"};
Stream<String> stream= Arrays.stream(strs);
stream.forEach(System.out::println);

System.out.println("-- 기본타입(int) 스트림 변환 -- ");
int[] nums={0,1,2,3};
IntStream intStream= Arrays.stream(nums);
intStream.forEach(System.out::println);

[output]

-- 참조타입(String) 스트림 변환 --
abc
def
ghi
jkl
-- 기본타입(int) 스트림 변환 --
0
1
2
3

2. 컬렉션 스트림

Java 8에서 Stream이 도입되면서 Collection 인터페이스에 데이터를 stream으로 변환하는 default 매소드가 추가되었습니다.

Collection을 구현한 객체이면 .stream() 매소드를 호출하여 원소들의 스트림을 만들 수 있습니다.

package java.util;

public interface Collection<E> extends Iterable<E> {
  ...
  default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
  }  
  ...
}

Collection 하위 인터페이스, 구현 클래스

Collection

  • List
    • ArrayList, LinkedList, AbstractList, AbstractSequentialList, AttributeList, CopyOnWriteArrayList, RoleList, RoleUnresolvedList, Stack, Vector
  • Set
    • LinkedHashSet, TreeSet, EnumSet, HashSet, AbstractSet, ConcurrentHashMap.KeySetView, ConcurrentSkipListSet, CopyOnWriteArraySet , JobStateReasons
  • Queue
    • PriorityQueue, LinkedList, AbstractQueue, ArrayBlockingQueue, ArrayDeque, ConcurrentLinkedDeque, ConcurrentLinkedQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, LinkedTransferQueue, PriorityBlockingQueue, SynchronousQueue

3. 빈 스트림

요소가 없을 때 null 대신 빈 스트림을 생성할 수 있습니다.

  • static Stream empty()
Stream<String> stream= Stream.empty();
Stream<Integer> stream2=Stream.empty();

4. Stream.builder() / Stream.generate() / Stream.iterate()

Stream.builder()

Builder 객체를 이용하여 Stream을 생성

public interface Stream<T> extends BaseStream<T, Stream<T>> {
  ...
  public static<T> Builder<T> builder() {
        return new Streams.StreamBuilderImpl<>();
  }  
  ...
  static final class StreamBuilderImpl<T>
            extends AbstractStreamBuilderImpl<T, Spliterator<T>>
            implements Stream.Builder<T> {
    
    public Stream.Builder<T> add(T t) {
            accept(t);
            return this;
        }
    ...
    @Override
        public void accept(T t) {
      ...
    }
     @Override
        public Stream<T> build() {
        ...  
     }
  }
}
예제 - Stream.builder()를 이용한 스트림 생성
Stream<String> stream= Stream.<String>builder() // Streams.StreamBuilderImpl<>();를 호출하여 StreamBuilderImpl<T>객체를 생성하여 리턴
                      .add("kim") // StreamBuilderImpl.add(T t) 호출 후 StreamBuilderImpl<T>을 인터페이스 타입(Stream.Builder<T>)으로 반환 
                      .add("jerry")
                      .add("lee")
                      .add("park")
                      .build(); // 스트림 생성
String result=stream.collect(Collectors.joining(" | "));
System.out.println(result);

[output]
kim | jerry | lee | park

Stream.generate()

함수형 인터페이스를 이용해 Stream 생성

System.out.println("1. 문자열 생성");
Stream<String> stream= Stream.generate(()->"element").limit(3);
String result=stream.collect(Collectors.joining(", "));
System.out.println(result);
System.out.println("2. 난수 생성");
DoubleStream stream2= DoubleStream.generate(()->Math.random()).limit(3);
stream2.forEach(System.out::println);

[output]

1.문자열 생성
element, element, element

2.난수 생성
0.0849717297401511
0.99566851930398
0.22473096887789168

Stream.iterate()

초기값과 이전 요소의 값을 인자로 함수형 인터페이스를 활용해 반복적으로 요소 생성

  System.out.println("1. 제네릭 스트림 사용");
Stream<Integer> stream= Stream.iterate(5, val -> val + 5).limit(10);
// 5: 초기값, val: 이전 요소값
OptionalInt sum=stream.mapToInt(Integer::intValue)
  .reduce((acc,val)->acc+val);
System.out.println(sum.isPresent()?sum.getAsInt() : -1);

System.out.println("2. primitive int를 다루는 IntStream 사용");
IntStream primitiveStream = IntStream.iterate(5,val->val+5).limit(10);
int primitiveSum =primitiveStream.sum();
System.out.println(primitiveSum);

[참고]

futurecreator - Java 스트림 총정리

oracle docs jdk 11

profile
제리하이웨이

0개의 댓글