람다 표현식을 쓸 수 있는 인터페이스는 오직 public 메서드 하나만 가지고 있는 인터페이스여야 한다. 자바 8에서 이러한 인터페이스를 특별히 함수형 인터페이스라고 부르고, 함수형 인터페이스에서 제공하는 단 하나의 추상 메서드를 함수형 메서드라고 부른다.
하지만 프레임워크나 API를 개발해야하는 개발자 입장에서는 람다 표현식을 사용할 수 있도록 메서드가 하나뿐인 인터페이스를 제공해야 하는 번거로움이 생길 수 있다. 이러한 번거로움을 해결하고자 자바 8에서는 일상적인 프로그래밍에서 많이 사용할 법한 패턴을 정리해서 함수형 인터페이스로 만들고 이를 java.util.function 패키지로 제공하고 있다.
forEach문
package functionalInterface;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
class MyConsumer implements Consumer<String>{
@Override
public void accept(String s) {
System.out.println(s);
}
}
public class ConsumerTest {
public static void main(String[] args) {
String[] myArr = {"A","C","B","D"};
List<String> list = (List) Arrays.asList(myArr);
/*반복자를 얻어 Collection을 순회
Iterator<String> iter = list.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
*/
// Consumer 인터페이스를 구현한 클래스를 new후 forEach에 사용
// list.forEach(new MyConsumer());
/* 익명클래스를 통해 accept 추상메소드를 구현
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
// 람다식
//list.forEach(s -> System.out.println(s));
// 메서드 참조
list.forEach(System.out::println);
}
}
실행 결과는 모두 다음과 같다.
A
C
B
D
Predicate : 하나의 매개변수를 주는 boolean형을 반환하는 test 메소드가 있다.
public interface Predicate{ boolean test(T t);}
Predicate p = str -> str.isEmpty();
Boolean b = p.test("ojc, asia"); // false
Consumer : 하나의 매개변수를 주는 void 형 accept 메소드가 있다.
public interface Consumer< T > { void accept(T t);}
Consumer< String > c = (s) -> System.out.println(s);
c.accept("ojc.asia"); // ojc.asia
Function: T 타입의 인수를 취하고 R 타입의 결과를 반환하는 추상 메소드 apply가 있다.
public interface Function<T, R> { R.apply(T t);}
Function<String, boolean> f = s -> s.isEmpty();
boolean b = f.apply("ojc.asia"); // false
Supplier: 메소드 인자는 없고 T유형의 결과를 반환하는 추상메소드 get이 있다.
public interface Supplier< T > { T get(); }
Supplier s = () -> "ojc.asia";
String res = s.get(); // ojc.asia
UnaryOperator: 하나의 인자와 리턴타입을 가진다 T -> T
UnaryOperator < String > u = (s) -> "hello~ " + s;
System.out.println(u.apply("ojc.asia")); // hello~ ojc.asia
BinaryOperator: 두개의 인수, 동일한 타입의 결과를 반환하는 추상메소드 apply가 있다.
BinaryOpeator: A binary opeartor from (T,T) -> T
BinaryOpeartor bo = (s1,s2) -> s1 + " , " + s2;
System.out.println(bo.apply("Hello~","ojc.asia");// Hello~ , ojc.asia
package functionalInterface;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class FiTest2 {
public static void main(String[] args) {
List<String> cities = Arrays.asList("Seoul", "Busan", "Daegu", "Gwangju", "Inchoen");
// 하나의 매개변수를 주는 boolean 형을 반환하는 test 메소드가 있다.
Predicate<String> p = (s) -> s.startsWith("S");
for (String s : cities) {
if (p.test(s)) {
System.out.println("1. Predicate: S로 시작: " + s);
}
}
// 하나의 매개변수를 주는 void 형 accept 메소드가 있다.
Consumer<String> c = (s) -> {
if (s.startsWith("S")) {
System.out.println("2. Consumer: S로 시작: " + s);
}
};
cities.forEach(c);
// 메소드 인자는 없고 T 유형의 결과를 반환하는 추상메소드 get이 있다.
Supplier<String> s = () -> cities.toString();
System.out.println("3. Supplier: " + s.get());
// T 유형의 인수를 취하고 R 유형의 결과를 반환하는 추상 메소드 apply가 있다.
Function<String, Boolean> f = str -> str.startsWith("S");
for (String str : cities) {
if (f.apply(str)) {
System.out.println("4. Function: S로 시작:" + str);
}
}
}
}