Java8 스트림(Stream) API
JAVA/Java 8

Java8 스트림(Stream) API

반응형

Java8의 람다식, 인터페이스의 변화에 이어서

더 좋은 기능이 바로 스트림이다.

스트림(Stream) 정의

- 스트림이란 리눅스에서 사용되는 파이프 라인 처럼 한번에    만들어지는 연속적인 데이터 항목들의 모임이다.
Ex) ps -ef | grep pnp | grep -v drop
 
조금  자세히 설명하면집계 연산을 지원하는 요소의 순서(a sequence of elements from a source that supports aggregate operations라고 소개 되어 있다.

- Stream은 정의된 엘리먼트의 속성에 따라서 처리할 수 있는 인터페이스를 제공하지만 실제 엘리먼트들을 저장하지 않고 계산하는 데만 쓰인다.

- 스트림은 컬렉션배열, I/O 리소스 등에서 제공받은 데이터를 가지고 작업을 처리 한다.
Stream 함수형 프로그래밍 같은 처리 방법도 지원한다. (filter, map, reduce, find, match, sorted )
 
기존의 Collection 처리 방법과 Stream 처리방식과 구분되는 기본적인 특징이 두가지가 있다
Internal iteration : 명시적으로 반복작업을 수행해야 되는 Collection과 비교 하면 Stream 작업은 내부에서 처리된다

Pipelining : 많은 Stream 기능들이 Stream 자기 자신을 리턴 한다이 방식은 처리 작업이 체인처럼 연결되어 큰 파이프라인처럼 동작 하도록 한다이를 통해 앞에 연산 동작이 종료  후에야 다음 동작이 진행 되도록 하는 laziness 방식을 이용하여 효율적인 방식으로 코딩을   있다.



스트림(Stream) 소개와 Collection 단점
 
Java 8에서 스트림이 나오기 전에 Collection 이용하여 자료를 데이터를 만들고 처리하는데 사용하였다.
 
극단적인 예를 들어 현재 과일 상품들의 가격을 정렬하여 보고 싶을 경우 기존의 경우에는 Collection 사용하여 다음과 같이
 
많은 작업이 필요했다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String args[]) {        
        WedulObject[] temp = {
            new WedulObject("kim"1"manage"), new WedulObject("jung"2"insa"), new WedulObject("jun"3"dev")
        };
        
        List<WedulObject> objects = Arrays.asList(temp);
        
        // 기존의 방식
        Collections.sort(objects, new Comparator<Object>() {
            @Override
            public int compare(Object obj1, Object obj2) {
                WedulObject ob1 = (WedulObject) obj1;
                WedulObject ob2 = (WedulObject) obj2;
                return ob1.getName().compareTo(ob2.getName());
            }
        });
        
        for (WedulObject obj : objects) {
            System.out.println(obj.getName());
        }
    }
cs




그러나 java8에서 스트림을 통해 편리하게 작업을 진행   있다.



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
26
public static void main(String args[]) {
        
        WedulObject[] temp = {
            new WedulObject("kim"1"manage"), new WedulObject("jung"2"insa"), new WedulObject("jun"3"dev")
        };
        
        List<WedulObject> objects = Arrays.asList(temp);
        
        // 기존의 방식
        Collections.sort(objects, new Comparator<Object>() {
            @Override
            public int compare(Object obj1, Object obj2) {
                WedulObject ob1 = (WedulObject) obj1;
                WedulObject ob2 = (WedulObject) obj2;
                return ob1.getName().compareTo(ob2.getName());
            }
        });
        
        for (WedulObject obj : objects) {
            System.out.println(obj.getName());
        }
        
        //strem을 이용한 정렬, 추출, 반환 
        List rare = objects.stream().sorted(Comparator.comparing(WedulObject::getAge)).map(WedulObject::getName).collect(Collectors.toList());
        rare.stream().forEach(System.out::println);
}
cs



품목(content)로 부터 stream()메서드를 사용해서 stream을 가져오고 그 다음에 여러가지 기능(sortedmap, collect)를 체인 처럼 엮어서 데이터를 처리하여 Collection 사용할  보다 더욱 간편하게 데이터를 처리   있게 되었다





또한 기존의 Collection 이용할 때의
 
기존의 코드는  못된 점은 없지만 코드의 병렬화가 어렵다는 한계점이 있다.

그러나 stream()에서는 
 
stream() parallelStream()으로 변경함으로써 병렬처리가 가능하게 된다. Stream API는 내부적으로 멀티코어로 동작하도록 처리하고 있다.







이런 스트림 문장을 생성하는 규칙이 존재한다.
 
Stream 처리는 중개 연산(intermediate operations)라고 불리는 것을 통해 서로 연결 될 수 있다이들의 리턴 타입은 stream이기 때문에 서로 연결될 수 있다. 
 
위의 예시로 보여줬던 Stream 보면 sorted, map 통해 전달 받는 Stream값을 이용하여 서로 값을 전달 하는 것을   있다.
 
  작업은 종단 연산(terminal operations) 통해 작업을 종료할  있다처리된 결과를 List, Integer void 형태 등으로 받을  있다.
 
 단계의 스트림은 요소들을 보관하지 않고 필요할  생성하며제공 받은 데이터를 변경하는 것이 아니라 연산으로 부터 생성된 스트림을 반환한다.





중계연산 메소드 소개
Filter
->  주어진 조건값을 충족하는  만을 추출하고자   사용되는 메서드 이다.
옵션 :
- distinct : 중복을 제거한 유니크 엘리먼트를 리턴 한다.
- limit(n) : 주어진 사이즈(n)에 까지의 stream을 리턴 한다. (filter 걸러진 데이터 중에 지정한 개수
                만큼만 출력)
- skip(n) : 주어진 엘리먼트 길이 까지 제외한 stream을 리턴 한다.(처음 나온 데이터 3개를 제외하고 
                출력)






Mapping
Map : 전달받은 스트림의 값을 특정 방식으로 변경하고 싶을  사용한다
-> 입력 받은 String Stream 값을 소문자로 변경  출력 




Reduction 메소드(종단 연산)
-> 중단 연산을 통해 데이터를 생성하고 변환하였다면종단 연산을 통해 변형되고 추출된 데이터를 통해 결과 데이터를 얻을  있게 해준다.
 
종단연산을 통해서 void, boolean, list, Optional<T> 형태의 데이터를 추출   있다.
 
Optional<T> 데이터 형식
기존의 데이터가 없음을 표시할  많이 사용되던 Null NPE(Null Point Exception)오류를 발생 시켜Runtime Exception 일으키는 경우가 많이 발생한다.
Null값인 데이터를 접근해서 발생하는 이유가  다수지만 null 자체의 모호함으로 인해 발생되는 경우도 있다.


1
2
3
4
Map<String, String> map = new HashMap<String, String>();
map.put("hello", null);
map.get("hello");   // "hello" key의 value인 null을 return
map.get("nice");    // "nice" key가 없으므로 null을 return
cs



위의 경우를 보면 key에 대한 value가 null인지, key가 없어서 null을 return 한건지 return 받은 null 값을 가지고는 그 의미가 모호해져 버그를 발생시킬 때도 있다.
  
그래서 java8에서 나온 Optional 클래스는 nullable T non-null 값으로 대체시키기 위해 포함된 방법이다.

, Optional 객체는 명시적으로 null 값을 갖지 않는다.

Optional 상태
– absent : 아무 것도 포함하고 있지 않은 상태
– present : non-null 값을 갖은 상태

Optional.of(T)
– T로 받은 non-null 값을 포함하는 Optional 객체 반환, T가 null 일 경우 NPE 발생







Optional.empty()
– 아무것도 포함하고 있지 않는 absent Optional 객체 반환
Optional.ofNullable(T)
– T로 받은 값이 non-null일 경우 present로, null일 경우 absent로 처리한 Optional 객체 반환
-> 값이 null 경우 비어 있는 Optional 객체를 반환하기 때문에 NPE 오류를 예방할  있다.




boolean isPresent()
– Optional 객체가 non-null 인스턴스를 포함할 경우 true 반환




T get()
– Optional 객체가 present 일 경우 포함하고 있는 인스턴스를 반환, absent일 경우 NoSuchElementException발생




T orElse(T)
– Optional 객체의 present 값을 반환만일 값이 없을 경우 명시한 T 반환 (기본값)



반응형