๋ธ๋ก๊ทธ ์ฎ๊ฒผ์ต๋๋ค! ๐ก integer.blog
์๋ฐ์ ์ ์(๋จ๊ถ์ฑ ์ ) 2๊ถ ํ์ต๋ด์ฉ ์ ๋ฆฌ
1. ๋๋ค์
๋ฉ์๋๋ฅผ ํ๋์ ์(expression)์ผ๋ก ํํํ ๊ฒ.
๋ฉ์๋๋ฅผ ๋๋ค์์ผ๋ก ํํํ๋ฉด ๋ฉ์๋์ ์ด๋ฆ๊ณผ ๋ฐํ๊ฐ์ด ์์ด์ง๋ฏ๋ก ๋๋ค์์ ์ต๋ช ํจ์(anonymous function)๋ผ๊ณ ๋ ํ๋ค.
๋๋ค์์ ๋ฉ์๋์ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋ ์ ์๊ณ ,
๋ฉ์๋์ ๊ฒฐ๊ณผ๋ก ๋ฐํ๋ ์ ์๋ค.
์ฆ, ๋ฉ์๋๋ฅผ ๋ณ์์ฒ๋ผ ๋ค๋ฃจ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค.
2. ๋๋ค์ ์์ฑํ๊ธฐ
- ๋ฉ์๋์์ ์ด๋ฆ๊ณผ ๋ฐํํ์ ์ ๊ฑฐ
- ๋งค๊ฐ๋ณ์ ์ ์ธ๋ถ์ ๋ชธํต{} ์ฌ์ด์ -> ์ถ๊ฐ
//๊ธฐ์กด
๋ฐํํ์
๋ฉ์๋์ด๋ฆ (๋งค๊ฐ๋ณ์ ์ ์ธ) {
...
}
//๋๋ค์
(๋งค๊ฐ๋ณ์ ์ ์ธ) -> {
...
}
- ๋ฐํ๊ฐ์ด ์๋ ๋ฉ์๋๋ return ๋์ ์(expression)์ผ๋ก ๋์ ํ ์ ์๋ค.(์ฐ์ฐ ๊ฒฐ๊ณผ๊ฐ ์๋์ผ๋ก ๋ฐํ๊ฐ์ด ๋๊ณ ; ์๋ต)
- ๋งค๊ฐ๋ณ์์ ํ์ ์ ์ถ๋ก ๊ฐ๋ฅํ๋ฉด ์๋ต ๊ฐ๋ฅ (๋๋ถ๋ถ ์๋ต ๊ฐ๋ฅ)
- ๋ ๋งค๊ฐ๋ณ์ ์ค ํ๋์ ํ์ ๋ง ์๋ตํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅ
- ๋งค๊ฐ๋ณ์๊ฐ ํ๋๋ฟ์ด๋ฉด ๊ดํธ() ์๋ต ๊ฐ๋ฅ
- ์ค๊ดํธ{} ์์ ๋ฌธ์ฅ์ด ํ๋์ผ ๋๋ ์ค๊ดํธ{} ์๋ต ๊ฐ๋ฅ (๋ฌธ์ฅ ๋์ ; ์๋ต)
- ์ค๊ดํธ{} ์์ ๋ฌธ์ฅ์ด return๋ฌธ์ผ๊ฒฝ์ฐ ์ค๊ดํธ{} ์๋ต ๋ถ๊ฐ๋ฅ
//๊ธฐ์กด
int max(int a, int b) {
return a > b ? a : b;
}
//๋๋ค์
(int a, int b) -> {
return a > b ? a : b;
}
//return๋ฌธ ๋์ expression ์ฌ์ฉ
(int a, int b) -> a > b ? a: b
//๋งค๊ฐ๋ณ์ ํ์
์๋ต
(a, b) -> a > b ? a : b
//๋งค๊ฐ๋ณ์ 1๊ฐ์ผ ๊ฒฝ์ฐ ๊ดํธ ์๋ต
a -> a*a //OK
int a -> a*a //์๋ฌ
//๋ณธ๋ฌธ ๋ฌธ์ฅ 1๊ฐ์ผ ๊ฒฝ์ฐ ์ค๊ดํธ ์๋ต
(String name, int i) -> System.out.println(name+"="+i)
3. ํจ์ํ ์ธํฐํ์ด์ค(Functional Interface)
๋๋ค์์ ๋ค๋ฃจ๊ธฐ ์ํ ์ธํฐํ์ด์ค
๋๋ค์์ ๋ฉ์๋์ ๋๋ฑํ ๊ฒ์ด ์๋๋ผ ์ต๋ช ํด๋์ค์ ๊ฐ์ฒด์ ๋๋ฑํ๋ค.
// ๋๋ค์
(int a, int b) -> a > b ? a : b
// ์ต๋ช
ํด๋์ค์ ๊ฐ์ฒด
new Object() {
int max(int a, int b) {
return a > b ? a : b ;
}
}
๋๋ค์์ผ๋ก ์ ์๋ ์ต๋ช
๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ค๋ฉด ์ฐธ์กฐ๋ณ์๊ฐ ํ์ํ๋ค.
์ด ๋, ์ฐธ์กฐ๋ณ์์ ํ์
์ ํด๋์ค ๋๋ ์ธํฐํ์ด์ค๊ฐ ๊ฐ๋ฅํ๋ฐ,
๋๋ค์๊ณผ ๋๋ฑํ ๋ฉ์๋๊ฐ ์ ์๋์ด ์๋ ๊ฒ์ด์ด์ผ ํ๋ค.
// ์๋ฅผ ๋ค์ด max() ๋ฉ์๋๊ฐ ์ ์๋ Myfunction ์ธํฐํ์ด์ค ์ ์
interface MyFunction {
public abstract int max(int a, int b);
// MyFunction ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ์ต๋ช
ํด๋์ค ๊ฐ์ฒด ์์ฑ
MyFunction f = new MyFunction() {
public int max (int a, int b);
return a > b ? a : b;
}
}
int big = f.max(5, 3); //์ต๋ช
๊ฐ์ฒด์ ๋ฉ์๋ ํธ์ถ
// ์์ ์ต๋ช
๊ฐ์ฒด๋ฅผ ๋๋ค์์ผ๋ก ๋์ฒด
MyFunction f = (int a, int b) -> a > b ? a : b;
int big = f.max(5, 3);
์ ์ฒ๋ผ MyFunction ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ์ต๋ช ๊ฐ์ฒด๋ฅผ ๋๋ค์์ผ๋ก ๋์ฒด ๊ฐ๋ฅํ ์ด์ ๋ ๋๋ค์๋ ์ค์ ๋ก๋ ์ต๋ช ๊ฐ์ฒด์ด๊ณ , MyFunction ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ์ต๋ช ๊ฐ์ฒด์ ๋ฉ์๋ max()์ ๋๋ค์์ ๋งค๊ฐ๋ณ์์ ํ์ ๊ณผ ๊ฐ์, ๋ฐํ๊ฐ์ด ์ผ์นํ๊ธฐ ๋๋ฌธ์ด๋ค.
๋จ, ํจ์ํ ์ธํฐํ์ด์ค์๋ ์ค์ง ํ๋์ ์ถ์ ๋ฉ์๋๋ง ์ ์๋์ด ์์ด์ผ ํ๋ค. ๊ทธ๋์ผ ๋๋ค์๊ณผ ์ธํฐํ์ด์ค๊ฐ 1:1๋ก ์ฐ๊ฒฐ๋๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฐ๋ฉด static ๋ฉ์๋์ default ๋ฉ์๋์ ๊ฐ์์๋ ์ ์ฝ์ด ์๋ค.
@FunctionalInterface๋ฅผ ๋ถ์ด๋ฉด ์ปดํ์ผ๋ฌ๊ฐ ํจ์ํ ์ธํฐํ์ด์ค๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ ์ํ์๋์ง ํ์ธํด์ค๋ค.
// ๊ธฐ์กด ์ธํฐํ์ด์ค์ ๋ฉ์๋ ๊ตฌํ
List<String> list = Arrays.asList("abc", "aaa", "bbb", "ccc");
Collections.sort(list, new Comparator<String>() {
public int compare(String s1, String s2) {
return s2.compareTo(s1);
}
});
// ๋๋ค์์ผ๋ก ๊ตฌํ
List<String> list = Arrays.asList("abc", "aaa", "bbb", "ccc");
Collections.sort(list, (s1, s2) -> s2.compareTo(s1));
ํจ์ํ ์ธํฐํ์ด์ค๋ก ๋๋ค์์ ์ฐธ์กฐํ ์ ์์ง๋ง, ๋๋ค์์ ํ์ ์ด ํจ์ํ ์ธํฐํ์ด์ค์ ํ์ ๊ณผ ์ผ์นํ๋ ๊ฒ์ ์๋๋ค. ๋๋ค์์ ์ต๋ช ๊ฐ์ฒด์ด๊ณ ์ต๋ช ๊ฐ์ฒด๋ ํ์ ์ด ์๋ค. (์ ํํ๋ ํ์ ์ด ์์ง๋ง ์ปดํ์ผ๋ฌ๊ฐ ์์๋ก ์ด๋ฆ์ ์ ํ๊ธฐ ๋๋ฌธ์ ์ ์ ์๋ค.) ๊ทธ๋ฌ๋ฏ๋ก ์๋์ ๊ฐ์ด ํ๋ณํ์ด ํ์ํ๋ค.
MyFunction f = (MyFunction) (()->{}); //
๋๋ค์์ MyFunction์ธํฐํ์ด์ค๋ฅผ ์ง์ ๊ตฌํํ์ง ์์์ง๋ง, ์ด ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํด๋์ค์ ๊ฐ์ฒด์ ์์ ํ ๋์ผํ๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ ํ๋ณํ์ ํ์ฉํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ํ๋ณํ์ ์๋ต ๊ฐ๋ฅํ๋ค.
๋๋ค์์ ์ด๋ฆ์ด ์์ ๋ฟ ๋ถ๋ช ํ ๊ฐ์ฒด์ธ๋ฐ๋, Object ํ์ ์ผ๋ก ํ๋ณํ ํ ์ ์๋ค. ๋๋ค์์ ์ค์ง ํจ์ํ ์ธํฐํ์ด์ค๋ก๋ง ํ๋ณํ์ด ๊ฐ๋ฅํ๋ค. ๊ตณ์ด Object ํ์ ์ผ๋ก ํ๋ณํํ๋ ค๋ฉด ์๋์ ๊ฐ์ด ๋จผ์ ํจ์ํ ์ธํฐํ์ด์ค๋ก ๋ณํํด์ผ ํ๋ค.
Object obj = (Object)(MyFunction)(()->{});
String str = (Object)(MyFunction)(()->{})).toString();
4. java.util.function ํจํค์ง
์ด ํจํค์ง์ ์์ฃผ ์ฐ์ด๋ ํ์์ ๋ฉ์๋๋ฅผ ํจ์ํ ์ธํฐํ์ด์ค๋ก ์ ์ํด๋์๋ค.
ํจ์ํ ์ธํฐํ์ด์ค | ๋ฉ์๋ | ์ค๋ช |
---|---|---|
java.lang.Runnable | void run() | ๋งค๊ฐ๋ณ์๋ ์๊ณ , ๋ฐํ๊ฐ๋ ์์ |
Supplier |
T get() | ๋งค๊ฐ๋ณ์๋ ์๊ณ , ๋ฐํ๊ฐ๋ง ์์ |
Consumer |
void accept(T t) | Supplier์ ๋ฐ๋๋ก ๋งค๊ฐ๋ณ์๋ง ์๊ณ , ๋ฐํ๊ฐ์ด ์์ |
Function |
R apply(T t) | ์ผ๋ฐ์ ์ธ ํจ์. ํ๋์ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ์์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ |
Predicate |
boolean test(T t) | ์กฐ๊ฑด์์ ํํํ๋๋ฐ ์ฌ์ฉ. ๋งค๊ฐ๋ณ์๋ ํ๋, ๋ฐํ ํ์ ์ boolean |
BiConsumer |
void accept(T t, U u) | ๋๊ฐ์ ๋งค๊ฐ๋ณ์๋ง ์๊ณ , ๋ฐํ๊ฐ์ด ์์ |
BiPredicate |
boolean test(T t, U u) | ์กฐ๊ฑด์์ ํํํ๋๋ฐ ์ฌ์ฉ๋จ. ๋งค๊ฐ๋ณ์๋ ๋, ๋ฐํ๊ฐ์ boolean |
BiFunction |
R apply(T t, U u) | ๋๊ฐ์ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ์์ ํ๋์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ |
- ์ํ์์ ๊ฒฐ๊ณผ๋ก true ๋๋ false๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ Predicate ๋ผ๊ณ ํ๋ค.
- ๋งค๊ฐ๋ณ์๊ฐ 2๊ฐ์ธ ํจ์ํ ์ธํฐํ์ด์ค๋ ์ด๋ฆ ์์ ‘Bi’๊ฐ ๋ถ๋๋ค.
- Supplier๋ ๋งค๊ฐ๋ณ์๋ ์๊ณ ๋ฐํ๊ฐ๋ง ์กด์ฌํ๋๋ฐ ๋ฉ์๋๋ ๋ ๊ฐ์ ๊ฐ์ ๋ฐํํ ์ ์์ผ๋ฏ๋ก BiSupplier๊ฐ ์๋ค.
- ๋งค๊ฐ๋ณ์์ ํ์ ๊ณผ ๋ฐํํ์ ์ด ์ผ์นํ ๋๋ Function ๋์ UnaryOperator๋ฅผ ์ฌ์ฉํ๋ค. (๋งค๊ฐ ๋ณ์ 2๊ฐ๋ฉด BinaryOperator)
// ์กฐ๊ฑด์ ํํ์ ์ฌ์ฉ๋๋ Predicate
Predicate<String> isEmptyStr = s -> s.length() == 0;
String s = "";
if(isEmptyStr.test(s))
System.out.println("This is an empty String.");
5. Function์ ํฉ์ฑ๊ณผ Predicate์ ๊ฒฐํฉ
5.1. Function์ ํฉ์ฑ
๋ ๋๋ค์์ ํฉ์ฑํด์ ์๋ก์ด ๋๋ค์์ ๋ง๋ค ์ ์๋ค.
ํจ์ f, g๊ฐ ์์ ๋
f.andThen(g)๋ ํจ์ f๋ฅผ ๋จผ์ ์ ์ฉํ๊ณ g ์ ์ฉ.
f.compose(g)๋ ํจ์ g๋ฅผ ๋จผ์ ์ ์ฉํ๊ณ f ์ ์ฉ.
5.2. Predicate์ ๊ฒฐํฉ
์ฌ๋ฌ Predicate๋ฅผ and(), or(), negate()๋ก ์ฐ๊ฒฐํด์ ํ๋์ ์๋ก์ด Predicate๋ก ๊ฒฐํฉํ ์ ์๋ค. Predicate์ ๋์ negate()๋ฅผ ๋ถ์ด๋ฉด ์กฐ๊ฑด์ ์ ์ฒด๊ฐ ๋ถ์ ์ด ๋๋ค.
Predicate<Integer> p = i -> i < 100;
Predicate<Integer> q = i -> i < 200;
Predicate<Integer> r = i -> i%2 == 0;
Predicate<Integer> notP = p.negate();
// 100 <= i && (i < 200 || i%2==0)
Predicate<Integer> all = notP.and(q.or(r));
System.out.println(all.test(150)); // true
static ๋ฉ์๋์ธ isEqual()์ ๋ ๋์์ ๋น๊ตํ๋ Predicate๋ฅผ ๋ง๋ค ๋ ์ฌ์ฉํ๋ค.
isEqual()์ ๋งค๊ฐ๋ณ์๋ก ๋น๊ต๋์์ ํ๋ ์ง์ ํ๊ณ , ๋ ๋ค๋ฅธ ๋น๊ต๋์์ test()์ ๋งค๊ฐ๋ณ์๋ก ์ง์ ํ๋ค.
Predicate<String> p = Predicate.isEqual(str1);
boolean result = p.test(str2); //str1๊ณผ str2๊ฐ ๊ฐ์์ง ๋น๊ตํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ
// ์์ ๋ ๋ฌธ์ฅ์ ํ๋๋ก ํฉ์น๋ฉด
boolean result = Predicate.isEqual(str1).test(str2);
6. ๋ฉ์๋ ์ฐธ์กฐ(Method reference)
๋๋ค์์ด ํ๋์ ๋ฉ์๋๋ง ํธ์ถํ๋ ๊ฒฝ์ฐ, ๋ฉ์๋ ์ฐธ์กฐ๋ฅผ ํตํด ๋๋ค์์ ๊ฐ๋ตํ ํ ์ ์๋ค.
ํด๋์ค๋ช ::๋ฉ์๋๋ช ๋๋ ์ฐธ์กฐ๋ณ์::๋ฉ์๋๋ช
// ๊ธฐ์กด
Function<String, Integer> f = (String s) -> Integer.parseInt(s);
// ๋ฉ์๋ ์ฐธ์กฐ
Funcation<String, Integer> f = Integer::parseInt;
์์ฑ์๋ฅผ ํธ์ถํ๋ ๋๋ค์๋ ๋ฉ์๋ ์ฐธ์กฐ๋ก ๋ณํ ๊ฐ๋ฅ
Supplier<MyClass> s = () -> new MyClass(); // ๋๋ค์
Supplier<MyClass> s = MyClass::new; // ๋ฉ์๋ ์ฐธ์กฐ
๋ฐฐ์ด ์์ฑํ ๊ฒฝ์ฐ
Function<Integer, int[]> f = x -> new int[x]; // ๋๋ค์
Function<Integer, int[]> f2 = int[]::new; // ๋ฉ์๋ ์ฐธ์กฐ