2014년 3월 18일 Java 8가 릴리즈가 되었습니다.(참고 : https://en.wikipedia.org/wiki/Java_version_history#Java_SE_8)
자바 8에서 제가 관심있는 부분은 JVM 메모리 모델에서 Permanent generation이 없어지고 metaspace가 도입된 것과 functional programming style 지원을 위해 람다, Functional interface, Stream이 도입되고, Jodatime의 개념이 JSR 310에 녹아들었던 점입니다.
안드로이드에서는 RetroLambda로 Lambda expression을 사용할 수 있지만, Android는 N부터 Lamba expression, stream을 지원하고 있습니다. 안드로이드 개발자 태생이라 발등에 떨어진 불을 끄기 위해 늦게나마 lambda expression, stream, functional interface를 공부하여 이를 좀 정리해 보려합니다.
우선 첫번째 제가 정리하고 싶은 부분은 java.util.function에 정의된 Functional Interface와 Labmda expression, method reference간의 상호 매핑입니다.
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | package com.jayjaylab.test.testjava.java8; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.function.*; /** * Created by jjkim on 2016. 3. 18.. */ public class TestFunction { public static void main(String ...args) { TestFunction testFunction = new TestFunction(); String hello = "Hello, World!" ; // Consumer function System.out.println( "consumer function" ); testFunction.<String>tryConsumer( s -> System.out.println(s), hello); testFunction.<String>tryConsumer(System.out::println, hello); System.out.println(); // Predicate function System.out.println( "predicate function" ); System.out.println( testFunction.<String>tryPredicate((s) -> s.startsWith( "a" ), hello)); System.out.println( testFunction.<String>tryPredicate(hello::startsWith, "a" )); System.out.println(); // Function function System.out.println( "function function" ); System.out.println( testFunction.<String, String>tryFunction((s) -> { return s + " means nothing" ; }, hello) ); System.out.println( testFunction.<String, String>tryFunction(s -> s + " means nothing" , hello) ); System.out.println( testFunction.<String, String>tryFunction(TestFunction::fillSuffix, hello) ); System.out.println(); // Supplier function System.out.println( "supplier function" ); System.out.println(testFunction.<List>trySupplier(() -> new ArrayList())); System.out.println(testFunction.<List>trySupplier(ArrayList:: new )); System.out.println(); // Unary Operator System.out.println( "unary operator" ); System.out.println(testFunction.<BigInteger>tryUnaryOperator( (i) -> i.add(BigInteger.TEN), BigInteger.ONE)); System.out.println(testFunction.<BigInteger>tryUnaryOperator( TestFunction::addTen, BigInteger.ONE)); System.out.println(); // BiFunction System.out.println( "BiFunction" ); System.out.println(testFunction.<BigDecimal, BigDecimal, String>tryBiFunction( (t, u) -> t.add(u).toPlainString(), BigDecimal.ONE, BigDecimal.TEN) ); System.out.println(testFunction.<BigDecimal, BigDecimal, String>tryBiFunction( testFunction::addAndReturnString, BigDecimal.ONE, BigDecimal.TEN )); System.out.println(); // Binary Operator System.out.println( "binary operator" ); System.out.println(testFunction.<String>tryBinaryOperator( (a, b) -> a + " and " + b, "cat" , "dog" )); System.out.println(testFunction.<String>tryBinaryOperator( testFunction::concatenate, "cat" , "dog" )); System.out.println(); } public static BigInteger addTen(BigInteger number) { return number.add(BigInteger.TEN); } public static String fillSuffix(String msg) { return msg + " means nothing" ; } public String addAndReturnString(BigDecimal a, BigDecimal b) { return a.add(b).toPlainString(); } public String concatenate(String a, String b) { return a + " and " + b; } // Typed parameters and return values public <T> void tryConsumer(Consumer<T> consumer, T t) { consumer.accept(t); } public <T> boolean tryPredicate(Predicate<T> predicate, T t) { return predicate.test(t); } public <T, R> R tryFunction(Function<T, R> function, T t) { return function.apply(t); } public <R> R trySupplier(Supplier<R> supplier) { return supplier.get(); } public <T> T tryUnaryOperator(UnaryOperator<T> operator, T t) { return operator.apply(t); } public <T, U, R> R tryBiFunction(BiFunction<T, U, R> function, T t, U u) { return function.apply(t, u); } public <T> T tryBinaryOperator(BinaryOperator<T> operator, T t, T u) { return operator.apply(t, u); } } |
위 소스를 보시면 com.util.function의 대표적인 7개의 functional interface가 그에 대응하는 람다 표현식과 method reference 바인딩 하는 예제인데요. 우선 type parameter를 사용하는 인터페이스를 가지고 놀았는데, 다음에는 primitive type에 관한 functional interface와 그에 대응하는 람다 표현식, 메소드 참조를 가지고 놀아보겠습니다.
'java' 카테고리의 다른 글
단순한 Dependency Injector를 구현해 써보자 #2 (0) | 2016.05.29 |
---|---|
JAVA 8 Fuctional Inteface, Method reference and Lambda expression #2 (0) | 2016.05.04 |
추상화(Abstraction) 이해의 중요성 #3 (0) | 2016.03.27 |
benchmarking 코드를 작성해 보자 #1 (1) | 2016.03.15 |
추상화(Abstraction) 이해의 중요성 #2 (0) | 2016.03.06 |