Functional Interface
μλ°μμ μ 곡λλ νμ€ API μμ ν κ°μ μΆμλ©μλλ₯Ό κ°μ§λ μΈν°νμ΄μ€λ€μ λͺ¨λ λλ€μμ μ΄μ©νμ¬ μ΅λͺ
ꡬν κ°μ²΄λ‘ ννμ΄ κ°λ₯νλ€.
μλ₯Ό λ€λ©΄ μ€λ λ μμ
μ μ μνλ Runnable
μΈν°νμ΄μ€λ 맀κ°λ³μμ 리ν΄κ°μ΄ μλ run()
λ©μλλ§ μ‘°μ¬νκΈ° λλ¬Έμ λ€λ¦κ³Ό κ°μ΄ λλ€μμ μ΄μ©ν Runnable
μΈμ€ν΄μ€λ₯Ό μμ±μν¬μ μλ€.
public static void main(String[] args) {
Runnable runnable = () -> {
for (int i = 0; i < 10; ++i) {
System.out.println(i);
}
};
Thread thread = new Thread(runnable);
thread.start();
}
@FunctionalInterface
λͺ¨λ μΈν°νμ΄μ€λ₯Ό λλ€μμ νκ² νμ μΌλ‘ μ¬μ©ν μ μλ€.
λλ€μμ΄ νλμ λ©μλλ₯Ό μ μνκΈ° λλ¬Έμ λκ° μ΄μμ μΆμλ©μλκ° μ μΈλ μΈν°νμ΄μ€λ λλ€μμ μ΄μ©νμ ꡬν κ°μ²΄λ₯Ό μμ±ν μ μλ€.
νλμ abstract method λ§μ΄ μ μΈ λ μΈν°νμ΄μ€ λ§μ΄ lamda μμ Target Type μ΄ λ μ μλ€.
FunctionalInterface
λ₯Ό μμ±ν λ @FunctionalInterface
μ΄λ
Έν
μ΄μ
μ λΆμ¬μ£Όλ©΄ λͺ
μμ μΌλ‘ FunctionalInterface
μ΄λΌλ κ²μ μμ μμΌλ©° λν λκ°μ΄μμ μΆμ λ©μλκ° μ μΈλμ§ μλλ‘ μ»΄νμΌλ¬κ° μ²΄ν¬ λ₯Ό νλ€.
μλμ κ°μ΄ λκ° μ΄μμ λ©μλλ₯Ό μ μΈν FunctionalInterface
μ μ»΄νμΌ μλ¬κ° λλ€.
@FunctionalInterface
public interface MyFunctionalInterface {
public void method();
public void otherMethod(); // Compile Error
}
μλμ κ°μ΄ κ°λ¨ν λ§λ€μ΄ μ¬μ©κ°λ₯νλ€.
맀κ°λ³μκ° μλ ν¨μν μΈν°νμ΄μ€
@FunctionalInterface
public interface MyFuncInterface {
public int method(int x, int y);
}
public static void main(String[] args) {
MyFuncInterface func = (x, y) => {
return x + y;
};
int result = func(3, 5);
System.out.println(result);
}
5
μ°Έκ³ μλ£
Java SE 8 λΆν°λ λΉλ²νκ² μ¬μ©λλ ν¨μμ μΈν°νμ΄μ€ (Functional Interface) λ java.util.function
νμ€ API ν¨ν€μ§λ‘ μ 곡ν©λλ€.
μ΄ ν¨ν€μ§μμ μ 곡νλ ν¨μμ μΈν°νμ΄μ€μ λͺ©μ μ λ©μλ λλ μμ±μμ 맀κ°νμ
μΌλ‘ μ¬μ©λμ΄ λλ€μμ λμ
ν μ μλλ‘ νκΈ° μν΄μ μ΄λ€.
java.util.function
ν¨ν€μ§μ ν¨μμ μΈν°νμ΄μ€λ ν¬κ² Consumer
Supplier
Function
Operator
Predicate
λ‘ κ΅¬λΆλλ€.
Consumer
Consumer
μΈν°νμ΄μ€μ νΉμ§μ 리ν΄κ°μ΄ μλ accept()
λ©μλλ₯Ό κ°μ§κ³ μλ€.
accept()
λ©μλλ 맀κ°κ°μ μλΉνλ μνλ§ νλ€.
Interface Name | Abstract Method | Description |
---|---|---|
Consumer<T> | void accept(T t) | κ°μ²΄ T λ₯Ό λ°μμ μλΉ |
BiConsumer<T, U> | void accept(T t, U u) | κ°μ²΄ T μ U λ₯Ό λ°μ μλΉ |
DoubleConsumer | void accpet(double value) | double κ°μ λ°μ μλΉ |
IntConsumer | void accept(int value) | int κ°μ λ°μ μλΉ |
LongConsumer | void accept(long value) | long κ°μ λ°μ μλΉ |
ObjDoubleConsumer<T> | void accpet(T t, double value) | κ°μ²΄ T μ double κ°μ λ°μ μλΉ |
ObjIntConsumer<T> | void accept(T t, int value) | κ°μ²΄ T μ int κ°μ λ°μ μλΉ |
ObjLongConsumer<T> | void accept(T t, long value) | κ°μ²΄ T μ long κ°μ λ°μ μλΉ |
Consumer<T>
μΈν°νμ΄μ€λ₯Ό νκ² νμ
μΌλ‘ νλ λλ€μμ λ€μκ³Ό κ°μ΄ μμ±ν μ μλ€.
Consumer<String> consumer = t -> {
/* t λ₯Ό μλΉνλ μ€νꡬ문 */
};
μ ꡬ문μ μ΄μ©ν μμ λ λ€μκ³Ό κ°λ€.
public static void main(String[] args) {
Consumer<String> consumer = t -> System.out.println(t + "8");
consumer.accept("Java SE ");
BiConsumer<String, String> biConsumer = (t, u) -> System.out.println(t + u);
biConsumer.accept("Java SE ", "8");
DoubleConsumer doubleConsumer = d -> System.out.println("Java SE " + d);
doubleConsumer.accept(8.0);
ObjIntConsumer<String> objIntConsumer = (t, i) -> System.out.println(t + i);
objIntConsumer.accept("Java SE ", 8);
}
Java SE 8
Java SE 8
Java SE 8.0
Java SE 8
forEach()
λ₯Ό μ΄μ©ν Consumer
μΈν°νμ΄μ€μ μλΉ λ°©λ²μ΄λ€.
μλΉμμ κ΄μ μΌλ‘ forEach(Consumer<? super T> action)
λ‘ μ¬μ©νλ€.
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class ForEach {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Persion(1, "KIM"));
list.add(new Persion(2, "LEE"));
list.add(new Persion(3, "PARK"));
Consumer<Person> style = (Person p) -> System.out.println("id: " + p.getPid() + ", Name: " + p.getName());
list.forEach(style);
}
}
public class Person {
private int pid;
private String name;
public Person() {}
public Person(int pid, String name){
this.pid = pid;
this.name = name;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
id:1, Name:KIM
id:2, Name:LEE
id:3, Name:PARK
λν μ λ ¬ μκ³ λ¦¬μ¦μ μ΄μ©ν μμ°μ κ΄μ μμ μ¬μ©νλ λ©μλμ΄λ€. (sort(Comparator<? super E> c)
)
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class ForEach {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Persion(1, "KIM"));
list.add(new Persion(2, "LEE"));
list.add(new Persion(3, "PARK"));
Consumer<Person> style = (Person p) -> System.out.println("id: " + p.getPid() + ", Name: " + p.getName());
list.sort(new PersonComparatorByName());
list.forEach(style);
}
}
import java.util.Comparator;
public class PersonComparatorByName implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
}
// μ€λ¦μ°¨μ μ λ ¬
id:1, Name:KIM
id:2, Name:LEE
id:3, Name:PARK
Supplier
Supplier
μΈν°νμ΄μ€μ νΉμ§μ 맀κ°λ³μκ° μκ³ λ¦¬ν΄κ°μ΄ μλ€.
get μΌλ‘ μμνλ μ΄λ¦μ λ©μλλ₯Ό κ°μ§κ³ μμΌλ©° μ΄ λ©μλλ μ€νν ν νΈμΆν κ³³μΌλ‘ λ°μ΄ν°λ₯Ό 리ν΄νλ μνμ νλ€.
λ¦¬ν΄ νμ
μ λ°λ₯Έ Supplier
μΈν°νμ΄μ€λ€μ΄ μλ€.
Interface Name | Abstract Method | Description |
---|---|---|
Supplier<T> | T get() | T κ°μ²΄λ₯Ό λ¦¬ν΄ |
BooleanSupplier | Boolean getAsBoolean() | Boolean κ°μ λ¦¬ν΄ |
DoubleSupplier | double getAsDouble() | double κ°μ λ¦¬ν΄ |
IntSupplier | int getAsInt() | int κ°μ λ¦¬ν΄ |
LongSupplier | long getAsLong() | long κ°μ λ¦¬ν΄ |
Supplier<T>
μΈν°νμ΄μ€λ₯Ό νκ² νμ
μΌλ‘ νλ λλ€μμ λ€μκ³Ό κ°μ΄ μμ±ν μ μλ€.
IntSupplier supplier = () -> {
/* statement */
return int_value;
}
λ€μ μμ λ μ£Όμ¬μμ μ«μλ₯Ό λλ€νκ² κ³΅κΈνλ IntSupplier
μΈν°νμ΄μ€λ₯Ό νκ²μΌλ‘ νλ λλ€μμ΄λ€.
public static void main(String[] args) {
IntSupplier intSupplier = () -> {
int num = (int) (Math.random() * 6) + 1;
return num;
}
int num = intSupplier.getAsInt();
System.out.println("λμ μ : " + num);
}
Function
Function
μΈν°νμ΄μ€μ νΉμ§μ 맀κ°κ°μ΄ 리ν΄κ°μ΄ μλ apply λ‘ μμνλ λ©μλλ₯Ό κ°μ§κ³ μλ€.
μ΄ λ©μλλ€μ 맀κ°κ°μ 리ν΄κ°μΌλ‘ 맀ννλ μνμ ν©λλ€.
맀κ°λ³μμ λ¦¬ν΄ νμ
μ λ°λΌ μλμ κ°μ Function
μΈν°νμ΄μ€κ° μλ€.
Interface Name | Abstract Method | Description |
---|---|---|
Function<T, R> | R apply(T t) | κ°μ²΄ T λ₯Ό κ°μ²΄ R λ‘ λ§€ν |
BiFunction<T, U, R> | R apply(T t, U u) | κ°μ²΄ T μ U λ₯Ό κ°μ²΄ R λ‘ λ§€ν |
DoubleFunction<R> | R apply(double value) | double μ κ°μ²΄ R λ‘ λ§€ν |
IntFunction<R> | R apply(int value) | int μ κ°μ²΄ R 맀ν |
IntToDoubleFunction | double applyAsDouble(int value) | int μ double λ‘ λ§€ν |
IntToLongFunction | long applyAsLong(int value) | int μ long μΌλ‘ 맀ν |
LongToDoubleFunction | double applyAsDouble(long value) | long μ double λ‘ λ§€ν |
LongToIntFunction | ins applyAsInt(long value) | long μ int λ‘ λ§€ν |
ToDoubleBiFunction<T, U> | double applyAsDouble(T t, U u) | κ°μ²΄ T μ U λ₯Ό double λ‘ λ§€ν |
ToDoubleFunction<T> | double applyAsDouble(T value) | κ°μ²΄ T λ₯Ό double λ‘ λ§€ν |
ToIntBiFunction<T, U> | int applyAsDouble(T t, U u) | κ°μ²΄ T μ U λ₯Ό int λ‘ λ§€ν |
ToIntFunction<T> | int applyAsDouble(T value) | κ°μ²΄ T λ₯Ό int λ‘ λ§€ν |
ToLongBiFunction<T, U> | long applyAsDouble(T t, U u) | κ°μ²΄ T μ U λ₯Ό long λ‘ λ§€ν |
ToLongFunction<T> | long applyAsDouble(T value) | κ°μ²΄ T λ₯Ό long λ‘ λ§€ν |
Function<T, R>
μΈν°νμ΄μ€λ₯Ό νκ² νμ
μΌλ‘ νλ λλ€μμ λ€μκ³Ό κ°μ΄ μμ± κ°λ₯ν©λλ€.
Function<Student, String> function = t -> { return t.getName(); };
Function<Student, String> function = t -> return t.getName();
μλ μμ λ List
μ μ μ₯λ Student
κ°μ²΄λ₯Ό νλμ© κΊΌλ΄μ νκ· μ μλ₯Ό μΆλ ₯νλ€.
class Student {
private String name;
private int englishScore;
private int mathScore;
public Student(String name, int englishScore, int mathScore) {
super();
this.name = name;
this.englishScore = englishScore;
this.mathScore = mathScore;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getEnglishScore() {
return englishScore;
}
public void setEnglishScore(int englishScore) {
this.englishScore = englishScore;
}
public int getMathScore() {
return mathScore;
}
public void setMathScore(int mathScore) {
this.mathScore = mathScore;
}
}
private static List<Student> lint = Arrays.asList(
new Student("Jolie", 100, 89),
new Student("Martin", 77, 94),
new Student("Pierre", 49, 100),
new Student("Paul", 80, 78)
);
public static double avg(ToIntFunction<Student> function) {
int sum = 0;
for (Student std : list ) {
sum += function.applyAsInt(std);
}
double avg = (double) sum / list.size();
return avg;
}
public static void main(String[] args) {
double englishAvg = avg(s -> s.getEnglishScore());
System.out.println("μμ΄ νκ· μ μ : " + englishAvg);
double mathAvg = avg(s -> s.getMathScore());
System.out.println("μν νκ· μ μ : " + mathAvg);
}
μμ΄ νκ· μ μ : 76.5
μν νκ· μ μ : 90.25
Operator
Operator
μΈν°νμ΄μ€λ Function
κ³Ό λμΌνκ² λ§€κ°λ³μμ 리ν΄κ°μ΄ μλ apply μ΄λ¦μΌλ‘ μμνλ λ©μλλ₯Ό κ°μ§κ³ μλ€.
Interface Name | Abstract Method | Description |
---|---|---|
BinaryOperator<T> | BiFunction<T, U, R> μ νμ μΈν°νμ΄μ€ | T μ U λ₯Ό μ°μ° ν R μ λ¦¬ν΄ |
UnaryOperator<T> | Function<T, R> μ νμ μΈν°νμ΄μ€ | T λ₯Ό μ°μ°ν ν R μ λ¦¬ν΄ |
DoubleBinaryOperator | double applyAsDouble(double, double) | λκ°μ double μ μ°μ° |
DoubleUnaryOperator | double applyAsDouble(double) | νκ°μ double μ μ°μ° |
IntBinaryOperator | int applyAsInt(int, int) | λκ°μ int μ μ°μ° |
IntUnaryOperator | int applyAsInt(int) | νκ°μ int λ₯Ό μ°μ° |
LongBinaryOperator | long applyAsLong(long, long) | λ κ°μ long μ μ°μ° |
LongUnaryOperator | long applyAsLong(long) | ν κ°μ long μ μ°μ° |
λ€μμ int[]
λ°°μ΄μ μ΅λκ°κ³Ό μ΅μκ°μ μ»μ΅λλ€.
private static int[] scores = {100, 92, 81, 78, 88, 96, 55, 94};
public static int compareNum(IntBinaryOperator operator) {
int result = scores[0];
for (int score : scores) {
result = operator.applyAsInt(result, score);
}
return result;
}
public static void main(String[] args) {
int max = compareNum((a, b) -> (a >= b ? a : b));
System.out.println("μ΅λκ° : " + max);
int min = compareNum((a, b) -> (a <= b ? a : b));
System.out.println("μ΅μκ° : " + min);
}
λ€μμ replaceAll(UnaryOperator operator)
μ μ΄μ©ν λ¬Έμμ΄μ concatenate
μ°μ° κ³Όμ μ΄λ€.
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class ForEach {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Persion(1, "KIM"));
list.add(new Persion(2, "LEE"));
list.add(new Persion(3, "PARK"));
Consumer<Person> style = (Person p) -> System.out.println("id: " + p.getPid() + ", Name: " + p.getName());
UnaryOperator<Person> unaryOpt = pn -> pn.getName(pn.getName().concat(" -God"));
list.replaceAll(unaryOpt);
list.forEach(style);
}
}
id:1, Name:KIM -God
id:2, Name:LEE -God
id:3, Name:PARK -God
Predicate
Predicate
μΈν°νμ΄μ€λ 맀κ°λ³μμ boolean
리ν΄κ°μ΄ μμΌλ©° test λ‘ μμνλ λ©μλ λͺ
μ κ°μ§κ³ μλ€.
μ΄ λ©μλλ 맀κ°κ°μ μ‘°μ¬ν΄μ true
νΉμ false
μ 리ν΄νλ μνμ νλ€.
맀κ°λ³μνμ
κ³Ό μμ λ°λΌμ μλμ κ°μ Predicate
ν¨μ μΈν°νμ΄μ€λ₯Ό κ°μ§κ³ μλ€.
Interface Name | Abstract Method | Description |
---|---|---|
Predicate<T> | Boolean test(T t) | κ°μ²΄ T λ₯Ό μ‘°μ¬ |
BiPredicate<T, U> | Boolean test(T t, U u) | κ°μ²΄ T μ U λ₯Ό μ‘°μ¬ |
DoublePredicate | Boolean test(double value) | double κ°μ μ‘°μ¬ |
IntPredicate | Boolean test(int value) | int κ°μ μ‘°μ¬ |
LongPredicate | Boolean test(long value) | long κ°μ μ‘°μ¬ |
λ€μμ removeIf()
μ μ΄μ©ν κ°μ 리μ€νΈλ₯Ό μ κ±°νλ μλΉμμ μ½λμ΄λ€. (removeIf(Predicate<? super E> filter)
)
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class ForEach {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Persion(1, "KIM"));
list.add(new Persion(2, "LEE"));
list.add(new Persion(3, "PARK"));
Consumer<Person> style = (Person p) -> System.out.println("id: " + p.getPid() + ", Name: " + p.getName());
int pid = 2;
Predicate<Person> predicate = p -> p.getPid() == pid;
list.removeIf(predicate);
list.forEach(style);
}
}
id:1, Name:KIM
id:3, Name:PARK
μ°Έκ³ μλ£
https://palpit.tistory.com/673 https://www.concretepage.com/java/jdk-8/java-8-list-example-with-foreach-removeif-replaceall-and-sort
andThen()
κ³Ό compose()
μ λν΄νΈ λ©μλ
andThen()
κ³Ό compose()
λ©μλλ λκ°μ Functional Interface λ₯Ό μμ°¨μ μΌλ‘ μ°κ²°νκ³ μ²«λ²μ§Έ μ²λ¦¬ κ²°κ³Όλ₯Ό λλ²μ§Έ 맀κ°κ°μΌλ‘ μ λ¬νμ¬ μ΅μ’
κ²°κ³Όκ°μ μ»μλ μ¬μ©νλ€.
andThen()
κ³Ό compose()
λ©μλλ μ²λ¦¬μμμ λ°λΌ λ€λ₯΄λ€.
InterfaceAB = InterfaceA.compose(Interface B)
Output = InterfaceAB.method()
InterfaceAB = InterfaceA.compose(Interface B)
Output = InterfaceAB.method()
Types | Functional Interface | andThen() | compose() |
---|---|---|---|
Consumer | Consumer<T> | O | |
BiConsumer<T, U> | O | ||
DoubleConsumer | O | ||
IntConsumer | O | ||
LongConsumer | O | ||
Function | Function<T, R> | O | O |
BiFunction<T, U, R> | O | ||
Operator | BinaryOperator<T> | O | |
DoubleUnaryOperator | O | O | |
IntUnaryOperator | O | O | |
LongUnaryOperator | O | O |
and()
or()
negate()
λν΄νΈ λ©μλμ isEqual()
μ μ λ©μλ
λ κ° μ΄μμ Predicate
μ°μ°μ μμ±ν©λλ€.
public static void main(String[] args) {
IntPredicate predicateA = a -> a % 2 == 0;
IntPredicate predicateB = b -> b % 3 == 0;
boolean result;
IntPredicate predicateAB = predicateA.and(predicateB);
result = predicateAB.test(9);
System.out.println("9λ 2μ 3μ λ°°μμ
λκΉ? : " + result);
predicateAB = predicateA.or(predicateB);
result = predicateAB.test(9);
System.out.println("9λ 2λλ 3μ λ°°μμ
λκΉ? : " + result);
predicateAB = predicateA.negate();
result = predicateAB.test(9);
System.out.println("9λ νμμ
λκΉ? : " + result);
}
λ€μμ isEquals()
λ₯Ό μ΄μ©ν λ¬Έμμ΄ λΉκ΅μ΄λ€.
public static void main(String[] args) {
Predicate<String> predicate;
predicate = Predicate.isEqual(null);
System.out.println("null, null: " + predicate.test(null));
predicate = Predicate.isEqual("Java");
System.out.println("Java, null: " + predicate.test(null));
predicate = Predicate.isEqual(null);
System.out.println("null, Java: " + predicate.test("Java"));
predicate = Predicate.isEqual("Java");
System.out.println("Java, Java: " + predicate.test("Java"));
}
null, null: true
Java, null: false
null, Java: false
Java, Java: true
μ°Έκ³ μλ£
β Lamda Method Reference β