Programming/JAVA

[JAVA] Stream API

RosyPark 2022. 4. 29. 08:01

Stream 

- Stream  이란 ?  Collection Builder , 람다를 활용할 수 있는 기술 중 하나이다. 이전에는 for문과 foreach문을 돌 때 로직이 복잡해지면서 복잡한 경우가 발생한다. 스트림은 즉, 데이터의 흐름이기 때문에 배열 또는 컬렉션에 함수를 사용하여 원하는 결과를 필터링 할 수 있다는 장점이 있다. 즉 함수형으로 처리할 수 있다. 

 

- Functional Program에는 null을 직접적으로 다루지 않는다. 

 Functional Program 이 더 안전하고 원하는 것을 더욱 더 쉽게 다룰 수 있다. 

 

 

(1) InStream

- java.util.stream 패키지 내에 스트림관련 API존재

 

 

1
2
3
IntStream.range(1,10).forEach(i -> System.out.println(i + "")); // 1 2 3 4 5 6 7 8 9
IntStream.rangeClosed(1,10).forEach(i-> System.out.println(i + " ")); // 1 2 3 4 5 6 7 8 9 10
IntStream.iterate(1, i-> i+1).forEach(i -> System.out.println(i + " ")); // 숫자 계속 증가
cs

 


 

(2) Stream 

 

1
2
Stream.iterate(BigInteger.ONE, i-> i.add(BigInteger.ONE))
        .forEach(i -> System.out.println(i + " ")); // 무한대의 Integer 
cs

- 메모리가 허락하는한 무한대의 Integer을 가짐  
- Functional Programming 처럼 무한대의 Integer가짐  

 

1
2
Stream.of(1,2,3,4,5,6)
            .forEach(i -> System.out.println( i + " ")); // 1 2 3 4 5 6
cs

 

 

 

 

* Imperative Programming과 Functional Programming 차이 

- Stream Builder는 굉장히 게으른 Collection Builder.

- 아무 일도 안함 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
final List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
//final List<Integer> result = new ArrayList<>();
Integer result = null;
for(final Integer number : numbers){
    if(number > 3 && number < 9){
        final Integer newNumber = number * 2 ;
        if(newNumber > 10 ){
            result = newNumber;
            break;
        }
 
    }
}
 
System.out.println("Imperative Result : " + result);  // 12
 
System.out.println("Functional Result :  "  +
numbers.stream()
        .filter(number -> number > 3 )
        .filter(number -> number < 9 )
        .map(number -> number *2 )
        .filter(number -> number > 10)
        .findFirst()
); //12 
 
cs

 

다른식으로도 표현할 수 있지만 가장 좋은 표현방식은 위와 같은 표현방식이다. 

하단과 같이 표현하는 것은 불필요한 표현방식이다. 

1
2
3
4
5
6
final List<Integer> greaterThan3 = filter(numbers, i -> i>3);
final List<Integer> lessThan9 = filter(greaterThan3, i -> i<9);
final List<Integer> doubled = map(lessThan9, i -> i*2);
final List<Integer> greaterThan10 = filter(doubled, i -> i>10);
System.out.println(greaterThan10.get(0));
 
cs

 

 

 

다음은 가독성이 좋지 않다. 

1
2
final List<Integer> myOwnMethodResult = filter(map(filter(filter(numbers, i-> i>3), i-> i<9), i-> i*2 ), i-> i>10);
System.out.println(myOwnMethodResult);
cs

 

<filter, map Generic> 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static <T> List<T> filter(List<T> list, Predicate<super T> predicate){
    final List<T> result = new ArrayList<>();
    for(final T t : list){
        if(predicate.test(t)){
            result.add(t);
        }
    }
    return result;
}
 
private static <T,R> List<R> map(List<T> list, Function<T,R> mapper){
    final List<R> result = new ArrayList<>();
    for(final T t : list){
        result.add(mapper.apply(t));
    }
    return result;
}
cs

 

 

<시작하기전에 - 참고 > 

1
2
3
4
5
final int minInt = Math.abs(Integer.MIN_VALUE);
final int maxInt = Math.abs(Integer.MAX_VALUE);
 
System.out.println("maxInt  " + maxInt); // 2147483647
System.out.println("minInt  " + minInt); // -2147483648
cs

 

 

<1> Indentity Function 

- 같은 타입을 리턴하는 것 , 함수 하는일은? 입력값을 받아서 그대로 리턴하는 것을 의미함 

- 타입 매개 변수 종류 -->  E - Element / K - Key / N - Number / T - Type / V - Value 

 

1
2
3
4
5
6
7
8
9
10
11
12
... 
final List<Integer> numbers = Arrays.asList(1,2,3,4,5);
System.out.println(map(numbers, i-> i*2)); // [2, 4, 6, 8, 10]
}
 
private static <T,R> List<R> map(List<T> list, Function<T,R> mapper){
    final List<R> result = new ArrayList<>();
    for(final T t : list){
        result.add(mapper.apply(t));
    }
    return result;
}
cs

 

..

 

System.out.println(map(numbers, i-> i)); //1,2,3,4,5
System.out.println(map(numbers, Function.identity())); //1,2,3,4,5

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static <T, R> List<R> map(final List<T> list, final Function<T,R> mapper){
 
    final Function<T,R> function;
    if(mapper != null){
        function = mapper;
    }else{
        function = t-> (R) t;
    }
 
    final List<R> result = new ArrayList<>();
    for(final T t : list){
        result.add(function.apply(t));
    }
 
    return result;
}
cs

 

Lazy

- Intermediate Operation Method

- Terminal Operation Method 

 

 

 

 

 

 

<출처> 

1. knight76.tistory.com/entry/IntStream-LongStream%EC%9D%98-%EB%B2%94%EC%9C%84-range-rangeClose-%EC%B0%A8%EC%9D%B4-%EB%B0%8F-%EC%98%88%EC%A0%9C

2. 유투브 kevin TV - 모던자바