public class FuntionalInterfaceExamples {
public static void main(String[] args) {
Integer value = toInt("100"); //100
}
static Integer toInt(String str) {
return Integer.parseInt(str);
}
}
String을 Integer로 캐스팅 하는 함수를 만들었다.
1. Function
import java.util.function.Function;
public class FuntionalInterfaceExamples {
final Function<String,Integer> toInt = new Function<String,Integer>() {
@Override
public Integer apply(String str) {
return Integer.parseInt(str);
}
};
int value2 = toInt.apply("100");
}
Function객체는 하나의 타입을 받아 다른 타입으로 리턴하는 apply를 가진 객체이다.
Function<T,R> 에서
T는 파라미터로 받을 타입 R는 리턴할 타입이다.
그리고 apply메소드 이외의 어떤 메소드도 가지고 있지 않다, 그말은 즉슨 람다식으로 풀어 쓸수 있다.
import java.util.function.Function;
public class FuntionalInterfaceExamples {
final Function<String,Integer> toInt = str -> Integer.parseInt(str);
int value3 = toInt.apply("100");
}
훨씬 간결해졌다.
2. Consumer
import java.util.function.Consumer;
public class FuntionalInterfaceExamples {
public static void main(String[] args) {
final Consumer<String> greetings = value -> System.out.println("Hello "+value);
greetings.accept("Tom");
}
}
만약 하나의 타입을 받지만 아무것도 리턴하지 않는 경우를 원할 수도 있다.
이럴 때는 Consumer객체를 이용한다.
Consumer의 메소드는 accept
3. Predicate
하나의 타입을 받아 boolean을 리턴할 때는 Predicate의 test를 이용한다.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class FuntionalInterfaceExamples {
public static void main(String[] args) {
List<Integer> preList = Arrays.asList(-5,-4,-3,-2,-1,0,1,2,3,4,5);
List<Integer> afterList = new ArrayList<>();
for(Integer value : preList) {
if(validation(value)) {
afterList.add(value);
}
}
System.out.println(afterList.toString());
}
public static boolean validation(Integer number) {
if(number>0) {
return true;
}
return false;
}
}
해당 코드는 양수만 출력하는 코드이다.
(주제와는 벗어났지만, for문의 조건문에 List가 들어 갈 시에 remove() 메소드와 같이 List가 변경되는 메소드를 사용할 수 없다. 뿐만 아니라, preList와 같은 경우는 읽기 전용(정확한 타입이 정해져 있지 않음)이기 때문에 수정할 수 도 없다.)
이를 Predicate를 이용하면 다음과 같이 사용한다.
public class FuntionalInterfaceExamples {
public static void main(String[] args) {
Predicate<Integer> validation = i -> i > 0;
List<Integer> preList = Arrays.asList(-5,-4,-3,-2,-1,0,1,2,3,4,5);
List<Integer> afterList = new ArrayList<>();
for(Integer value : preList) {
if(validation.test(value)) {
afterList.add(value);
}
}
System.out.println(afterList.toString());
}
}
다음은 람다식을 이용하지 않고 구체화 한 객체이다.
public class FuntionalInterfaceExamples {
public static void main(String[] args) {
List<Integer> preList = Arrays.asList(-5,-4,-3,-2,-1,0,1,2,3,4,5);
List<Integer> afterList = new ArrayList<>();
for(Integer value : preList) {
if(new validation().test(value)) {
afterList.add(value);
}
}
System.out.println(afterList.toString());
}
}
class validation implements Predicate<Integer>{
@Override
public boolean test(Integer i) {
return i>0;
}
}
마지막으로 다음과 같이 Predicate 역시 파라미터로 제공하여 리스트를 반환하는 제네릭 메소드를 만들었다.
public class FuntionalInterfaceExamples {
public static void main(String[] args) {
List<Integer> preList = Arrays.asList(-5,-4,-3,-2,-1,0,1,2,3,4,5);
List<Integer> afterList = filter(preList, i->i>0);
System.out.println(afterList.toString());
}
public static <T> List<T> filter(List<T> list, Predicate<T> filter){
List<T> result = new ArrayList<>();
for(T input : list) {
if(filter.test(input)) {
result.add(input);
}
}
return result;
}
}
4. Supplier
자바스크립트에서 비동기 관련해서 이런 것을 했던거 같은데... 어렵지만 한 번 보자
Supplier는 아무것도 받지 않고 어떤 타입을 리턴할 때 사용한다.
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
public class SupplierExamples {
public static void main(final String[] args) {
//1. 문자열을 리턴하는 예시
supplierExamples();
//2. Supplier를 사용하지 않을 떄의 예시
System.out.println("\nSupplier 사용하지 않고 시간 오래 걸리는 메소드 호출");
callingExpensiveMethodWithoutSupplier();
System.out.println("\nSupplier 사용해서 시간 오래 걸리는 메소드 호출");
callingExpensiveMethodWithSupplier();
}
// 1. 문자열을 리턴하는 예시
private static void supplierExamples() {
System.out.println("SupplierExamples.supplierExamples()");
final Supplier<String> helloSupplier = () -> "Hello "; // Hello를 받아
System.out.println(helloSupplier.get() + "world"); // 리턴한다.
}
//2. Supplier를 사용하지 않을 떄의 예시
private static void callingExpensiveMethodWithoutSupplier() {
System.out.println("SupplierExamples.callingExpensiveMethodWithoutSupplier()");
final long start = System.currentTimeMillis();
printIfValidIndex(0, getVeryExpensiveValue());
printIfValidIndex(-1, getVeryExpensiveValue());
printIfValidIndex(-2, getVeryExpensiveValue());
System.out.println("It took " + ((System.currentTimeMillis() - start) / 1000) + " seconds."); // 9초
}
//3. Supplier를 사용 했을 때의 예시
private static void callingExpensiveMethodWithSupplier() {
System.out.println("SupplierExamples.callingExpensiveMethodWithSupplier()");
final long start = System.currentTimeMillis();
printIfValidIndex(0, () -> getVeryExpensiveValue());
printIfValidIndex(-1, () -> getVeryExpensiveValue());
printIfValidIndex(-2, () -> getVeryExpensiveValue());
System.out.println("It took " + ((System.currentTimeMillis() - start) / 1000) + " seconds."); // 3초
}
private static String getVeryExpensiveValue() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Kevin";
}
private static void printIfValidIndex(final int number, final String value) {
if (number >= 0) {
System.out.println("The value is " + value + ".");
} else {
System.out.println("Invalid");
}
}
private static void printIfValidIndex(final int number, final Supplier<String> valueSupplier) {
if (number >= 0) {
System.out.println("The value is " + valueSupplier.get() + ".");
} else {
System.out.println("Invalid");
}
}
}
2 번을 보자
2번은 printIfValidIndex 실행시에 Validation이 0일 때 getVergetVeryExpensiveValue 이 실행되며 3초간 TimeUnit에 의해 쓰레드가 잠들고, 이는 -1 과 -2일때도 똑같다.
하지만 -1과 -2의 경우에는 사실 Invalid한 값이기 때문에 getVergetVeryExpensiveValue 이 실행할 이유가 없다.
이때 3번과 같이 Supplier를 이용한다면
Validation이 조건에 충족할 경우에만 getVergetVeryExpensiveValue 이 실행되기 때문에
원하는 대로 작동하게 할 수 있다.
'Language > Java' 카테고리의 다른 글
Stream Lombok 연습 예제 (0) | 2019.04.17 |
---|---|
[Java8] 커스텀 인터페이스 및 제네릭 메소드 만들어 보자. (0) | 2019.04.14 |
[Java8] Strategy Pattern, FP, 1급 객체 (0) | 2019.04.14 |
[Java]Collection 객체 응용(2) (0) | 2019.04.14 |
[Java]Comparable, Comparator (0) | 2019.04.14 |