#### Lambda에대해서
#### Lambda(λ) 란?
.각종프로그래밍언어의Lambda function 은논리수리학, 컴퓨터공학의Lambda 대수에서차용해온개념입니다.
.흔히Lambda 를표현하는문자λ은그리스문자로,알파벳의L 과같습니다.
.Lambda 대수는변수, 추상화, 적용이라는개념이있는데, 주로선언되는양식은(변수..) .{추상화단계} 형태이며, anObject.someFunction(lamdaFunction);
과같이함수의일반적호출형태를통해‘적용’하게됩니다.
.함수대신에, 추상화라는개념이들어간다는점에서는Lambda를지원하는언어의공통점입니다.
.Java 8 이전에,가장흔히접해보았을Lambda와유사한문법으로는Javascript의anonymous function 이있습니다.
#### Lambda 의특성과장점
.선언(추상화) 관점에서, 함수보다간결한syntax 를제공합니다.
.비슷한여러개의logic 을위해, 여러개의function 을선언할필요가없습니다.
.언어가문법적으로inline-function 을지원하지않더라도유사하게활용할수있습니다.
.Lambda function 을인자로하는함수/ lambda function 의경우, 일부개념을구분하여구현하는데도움이됩니다.
.Lambda function 을인자로하게되면, 사용자가내부로직일부를customize
할수있는기능을부여할수있습니다.
#### Lambda활용예시-Javascript
:: Javascript
varpower = function(x) {
return function(n) {
return Math.pow(n, x);
}
};
// cubic 은세제곱을구하는함수가됨
varcubic = power(3);
// sqrt 는x의제곱근을구하는함수가됨varsqrt = power(0.5);
console.log(cubic(5)); // 125
console.log(sqrt(64)); // 8
:: Javascript(ES2015 이후)
varpower = x => n => Math.pow(n, x);
// cubic 은세제곱을구하는함수가됨
varcubic = power(3);
// sqrt 는x의제곱근을구하는함수가됨varsqrt = power(0.5);
console.log(cubic(5)); // 125
console.log(sqrt(64)); // 8
:: Lambda활용예시.Python
def power(x):
return lambda n: pow(n, x)
cubic = power(3)
sqrt = power(1/2)
print(cubic(5)) #### 125
print(sqrt(64)) #### 8
#### Java 에서의Lambda
.기존Java 1.7 이하에는없던Function variable 에대한개념이생겼습니다.
(Document 참조java.util.function)
.Java 내에서는개념적으로Function, Supplier, Consumer, Operator, Predicate
로구분하고있고, 인자수에따라Bi-(2개), Unary-(1개) 등으로도구분합니다.
.Lambda 함수는주로Java Stream API, Optional API 에쓰이고있습니다.
#### Java Lambda function 의종류
.Function: T 타입인자를받아서R 타입으로변환하여반환합니다.
R Apply(T t);
.Supplier: T 타입객체를새로만들어반환합니다.
T get();
.Consumer: T 타입인자를받아서처리합니다.
void accept(T t);
.UnaryOperator: T 타입인자를받아서처리하고, T 타입객체를반환합니다.
T apply(T t);
.BinaryOperator: T 타입인자를두개받아서처리하고, 결과로T 타입객체를반환합니다.
T apply(T t1, T t2);
.Predicate: T 타입인자를받아서true/false 를반환합니다. (검증등에사용)
Boolean test(T t);
#### JavaStream API
.Stream API 자체는값을가지고있는개념이아니며, A 에서B 로연결되는과정(pipelining)을기술한것으로이해하시면됩니다.
.Stream API 를적용하기위해기존의List, Map 등에서stream() 혹은parallelStream() 을호출하여stream API 를사용할수있습니다.
.Stream 관련세부구현(customize)을사용자에게Lambda function 을통해구현하도록허용하고, 실제구현(sort, count…) 는최적화된Java logic 을이용하게하는구조입니다.
.Stream API 내에서는동일block 내의변수를참조하게할수는있으나, 이변수는final 이거나이에준하는(동함수내에서는변화없음) 변수이어야합니다.
(그렇지않은경우Compile 불가)
.숫자Stream(DoubleStream, IntStream..) 은각각의summaryStatistics함수를호출해서간단한통계를낼수도있습니다.
#### 주요JavaStream Functions
..collect(): 이전stream 결과를변환하고, 제공된Lambda 결과에맞는Collection(List, Set..) 혹은Map 등의형태로반환합니다.
..forEach(): 이전stream 각객체하나를인자로lambdafunction 로직을수행합니다.
(for 구문과유사)
..map(): 이전stream 각객체를lambda function 을수행한후의객체로변환(mapping) 하고, 해당type 의stream 을반환합니다.
..reduce():이전stream 객체전체로lambda function 을차례로수행하여하나의객체로도출해반환합니다.
..filter(): 이전stream 중조건에해당하는요소만골라stream 을반환합니다.
..count(): 이전stream 의결과개수를반환합니다.
..distinct(): 이전stream 결과중중복요소를제거하여stream 을반환합니다.
..sorted(): 이전stream 내에서lambda function 의결과값순서로정렬하고결과stream 을반환합니다.
#### JavaStream사용예
:: 인자에Lambda 직접사용
public void printValidEntityNameList() {
List list = repo.findAll();
list.stream()
.filter(Objects::nonNull)
.filter(entity -> entity.getSeq() != null)
.filter(entity -> entity.getName() != null)
.forEach(entity ->
System.out.println(“Seq: ” + entity.getSeq());
);
}
:: 선언해서사용하기
public void printValidEntityNameList() {
List list = repo.findAll();
// 함수내에서직접생성이가능하며// 이경우함수block 내effectively final 한변수를접근가능Consumer printEntity= entity ->
System.out.println(“Seq: ” + entity.getSeq());
list.stream().filter(validateEntity).forEach(printEntity);
}
publicPredicate validateEntity() {
// 선언(추상화)가한줄로표현가능하면중괄호를생략가능return entity ->
entity != null &&
entity.getSeq() != null &&
entity.getName() != null);
}
#### JavaOptional API
.Nullability 를검사하고대처하는새로운API 입니다.
.Haskell 등다른언어의로직을많이참고하였다고합니다.
.If-else 구문을사용하는것보다유연하게대처할수가있고, 표현적으로구문작성이가능합니다.
.Optional 이제공하는check, consume, predicate 로직을활용할수있고, 이를통해non-null 여부를담보할수있습니다.
.일부Stream API 의terminal operation(결과로stream 을반환하지않는함수)
결과로사용되어, stream API 와도연결하여사용할수있습니다.
#### JavaOptional API 사용예
:: Old-style null check
function (String aString, Double aDouble) {
if(aString== null) {
System.out.println("String is null.");
}
if(aDouble== null) {
aDouble= 0d;
}
Double sqrt = Math.sqrt(aDouble);
}
:: Using Optional
function (String aString, Double aDouble) {
Optional oString= Optional.of(aString);
Optional oDouble= Optional.of(aDouble);
oString.orElse(() -> {
System.out.println("String is null.");
});
Double sqrt = Math.sqrt(oDouble.orElseGet(0d));
}
#### JavaStream& optional 사용예
#### Filter .Map
public List getValidEntityNameList() {
List list = repo.findAll();
return list.stream()
.filter(Objects::nonNull)
.filter(entity -> entity.getSeq() != null)
.filter(entity -> entity.getName() != null)
.map(entity -> entity.getName())
.collect(Collectors.toList());
}
#### Sort .Find first
public Entity findFirstSeqEntity(List list) {
Optional oEntity= list.stream()
.filter(Objects::nonNull)
.filter(entity -> entity.getSeq() != null)
.sort((e1, e2) -> e1.getSeq().compareTo(e2.getSeq()))
.findFirst();
return oEntity.orElseGet(() -> repo.findTopByOrderBySeq());
}
댓글