본문 바로가기
WEB/JSP Servlet

표현언어 : 람다식, 스트림 API

by 노랑파랑 2016. 11. 4.
반응형





람다식

* Lambda Expression

* 함수처럼 파라미터를 가진 코드 블록으로 익명 함수를 지칭하는 용어이다.

* 일종의 함수처럼 사용이 가능하다. (호출, 재귀)


1) 람다식 형식

( 파라미터1, 파라미터2) -> EL식

* 예1) a가 b보다 큰 경우 true를 리턴하고, 크지 않다면 false를 리턴하는 람다식

( a, b) -> a>b ? true : false

* 예2) 람다식을 EL에서 사용

${ greaterEx = (a, b)-> a>b ? true : false ; " }

* 람다식을 greaterEx 변수에 할당하는 코드이다. 책의 예제는 결과를 출력하지 않기 위해 세미콜론 연산자를 사용했다.

* 람다식은 일종의 함수로, 위 처럼 할당한 변수를 함수처럼 호출할 수 있다. 또한 병수에 할당하지 않고 바로 사용도 가능하다.





스트림 API

* EL3.0버전에서 반복문을 제공하지 않기때문에 컬렉션 객체를 위한 스트림 API가 추가되었다. 

* 예) 합 구하기

<c:set var="data" value="<%= java.util.Arrays.asList(1,2,3,4) %>" />

<c:set var="sum" value=" ${data.stream().sum()}" />

* 예) 세미콜론 연산자와 할당 연산자를 이용해 EL만으로 계산 결과를 sum 변수에 할당

${ data = [1, 2, 3, 4]; sum = data.stream().sum() ; "}



1) 기본

* 기본 형태

* 스트림 생성 뒤 스트림은 다음 연산으로 원소를 차례대로 제공한다.

* 스트림 객체의 중간 연산 메소드는 변환 과정을 거친 뒤 새로운 스트림 객체를 생성한다. (생략 가능)

* 최종 연산은 스트림에 있는 데이터를 읽어와 최종 결과를 생성한다. 


2) 스트림 생성

* 스트림 메소드를 이용한 스트림 객체를 생성 : 객체.stream()

* 스트림 생성 뒤 중간 연산과 최종 영산을 거쳐 새로운 결과를 생성한다.

* EL은 Map타입의 stream()을 제공하지 않는다. 아래는 EL에서의 stream()사용 방법이다.

<%     java.util.Map<String, String> map = new java.util.HashMap<>();     map.put("color1","빨간색");     map.put("color2","파란색");     request.setAttribute("map", map); %>      ${map.entrySet().stream().map(entry-> entry.value).toList()}

* entrySet()을 사용해서 Map에 collection 객체를 생성한 뒤 그 객체에 stream() 메소드를 사용한다.



3) filter() 

* 람다식을 파라미터로 갖고, 값을 걸러낼 때 사용한다.

* 람다식은 한 개의 파라미터를 갖고 결과로 boolean타입을 리턴한다.

* 스트림의 각 원소에 람다식을 실행하고 그 결과인 boolean타입이 True인 원소를 반환한 새로운 스트림을 생성한다.



4) map()

* 람다식을 파라미터로 갖고, 각 원소를 변환한 새로운 스트림을 생성한다.

* 람다식은 한개의 파라미터를 갖고 결과로 파라미터를 변환한 새로운 원소를 리턴한다.

* 즉, 스트림의 각 원소에 람다식을 셀행하고 그 결과로 구성된 새로운 스트림을 생성한다.

* map() 메소드는 Collection에 포함된 원소에서 특정 값을 추출하는 용도에 적합하다. 

* map()과 filter()를 사용해서 나이가 20세 이상인 회원들의 평균나이를 알아보고 싶다면,

${ mamber.stream().filter(m-> m.age >= 20).map(m->m.age).average().get() }



5) sorted()

* 스트림을 정렬한다.

* 기본 사용

${ 리스트 이름 = [ 원소 ] ;

변수 이름 = 리스트 이름.stream().sorted().toList() }

* sorted() 메소드는 Comparable 인터페이스에 정의된 기능을 사용하기 때문에, 이 인터페이스를 구현하지 않은 타입의 원소는

정렬할 수 없다. 

* Comparable 인터페이스를 구현하고 있지 않거나, 오름차순이 아닌 다른 순서로 정렬하고 싶은 경우에는 람다식을 이용한다.

// 내림차순 예

$ { vals= [20, 17, 10, 1, 25, 3];

sortedVals = vals.stream( ( x, y) -> x < y ? 1 : -1 ).toList() }

* srted()의 람다식은 두 개의 파라미터를 갖는다. 첫 번째 파라미터가 정렬 순서 상 앞이면 음수, 뒤이면 양수, 같으면 0을 리턴한다.




6) limit()

* 지정한 개수를 갖는 새로운 스트림을 생성한다.

* sorted()와 limit()을 함께 사용하면 값을 정렬한 결과 중에서 앞에 n개만 출력할 수 있다.

${ num.stream().sorted().limit(3).toList() }




7) toList() | toArray()

* 결과 생성 방법을 제공한다.

* toList() : 자바 리스트 객체를 만든다.

* toArray() : 자바 배열 객체를 만든다.

${ List = member.stream().map( m -> m.name).toList() ;" }

${ Array = member.stream().map( m -> m.age).toArray() ;" }

* List 타입은 각 원소의 값을 문자열로 변환한 후 출력한다.

* Array 타입은 배열 객체의 문자열 표현을 출력한다.



8) count()

* 스트림의 원소 개수를 리턴한다.

${ member.stream().count() } 




9) Optional 타입

* 메소드의 결과 값이 존재하거나 존재하지 않을 경우 사용하는 타입이다.


1] 제공 메소드

▷ get() : 값이 존재할 경우 해당 값을 리턴한다. 값이 존재하지 않으면 ELException을 발생한다.

▷ orElse(other) : 값이 존재하면 해당 값을 리턴하고, 값이 존재하지 않으면 other를 리턴한다.

▷ orElseGet( ( ( )->T ) other ) : 값이 존재하면 해당 값을 리턴하고, 값이 존재하지 않으면 람다식 other을 실행한 결과를 리턴한다.

▷ ifPresent( ( (x) -> void) consumer ) : 값이 존재하면 람다식 consumer를 실행하고, 존재하는 값을 람다식의 파라미터로 전달한다.

// ifPresent 예제

${ minVal = '-' ; }     // minVal변수에 '-'를 할당한다.

${ [1,2,3].stream().min().ifPresent( x -> (minVal = x) ) }    // min() 메소드의 실행 결과가 존재하면 minVal 변수에 결과 값을 할당한다.

최소값은 {$minVal}입니다.    // 메소드의 결과 값이 존재하면 해당 값을 출력하고, 존재 하지 않으면 '-'를 출력한다.




10) sum() | average()

* sum() : 숫자로 구성된 스트림의 합을 구한다.

* average() : 숫자로 구성된 스트림의 평균을 구한다.

* 결과값이 없을 경우 Optional 타입을 리턴한다.



11) min() | max()

* 최소값과 최대값을 구할 수 있다.

* 스트림 원소가 Long이나 String같은 Comparable을 구현하고 있어야 한다.

${ LongVals.stream().min().get() }

* Optional 타입을 리턴한다. 

* 람다식을 사용할 수 있다.

// age 프로퍼티 값이 가장 큰 값

${ maxAge = member.stream().max( (m1, m2) -> m1.age.compareTo(m2.age) );" }




12) anyMatch() | allMatch() | noneMatch()

* anyMatch() : 스트림의 조건을 충족하는 요소가 존재하는지 겁사

▷ 조건을 충족하는지 검사하기 위한 방법으로 (S) -> boolean 람다식을 사용한다.

▷ 원소 중 하나라도 조건을 충족하면 true값을 갖는 Optional을 리턴한다. 

▷ 값이 없을 경우가 있다면 orElse()나 ifPresent()를 사용해야 한다.

▷  사용 예

${ List = [1, 2, 3, 4, 5 ] ; " }


// 4보다 큰 원소가 있는지 검사

${ matchOpt = List.stream().anyMatch( v -> v > 4) ; " }

${ matchOpt.get() }    // true 리턴


* allMatch() : 스트림의 모든 원소가 조건을 충족할 때 true를 값으로 갖는 Optional을 리턴한다.

* noneMatch() : 모두 빈 스트림에 대해 값이 없는 Optional을 리턴한다.

▷ 값이 없을 경우가 있다면 orElse()나 ifPresent()를 사용해야 한다.


반응형

'WEB > JSP Servlet' 카테고리의 다른 글

JDBC : 기초  (0) 2016.11.05
표현언어(EL) 비활성화 방법  (0) 2016.11.05
표현언어 : 기초, 연산자  (0) 2016.11.02
JSTL : 함수  (0) 2016.10.30
JSTL : 국제화 태그  (0) 2016.10.30