람다 표현식에 대해 다시 한번 정리 해보자.
class SLenComp implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
}
class SLenComparator {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Robot");
list.add("Lambda");
list.add("Box");
Collections.sort(list, new SLenComp()); // 첫번째 매개변수는 정렬할 자료 구조, 두번째는 정렬 기준이다.
for(String s : list)
System.out.println(s);
}
}
interface Printable {
void print(String s); // 매개변수 하나, 반환형 void
}
class OneParamNoReturn {
public static void main(String[] args) {
Printable p;
p = (String s) -> { System.out.println(s); } // 줄임 없는 표현
p.print("Lambda exp one.");
p = (String s) -> System.out.println(s); // 중괄호 생략
p.print("Lambda exp two.");
p = (s) -> System.out.println(s); // 매개변수 형 생략
p.print("Lambda exp three.");
p = s -> System.out.println(s); // 매개변수 소괄호 생략
p.print("Lambda exp four.");
}
}
중괄호, 소괄호 생략이 불가능한 상황
interface Calculate {
void cal(int a, int b);
}
class TwoParamNoReturn {
public static void main(String[] args) {
Calculate c; // 인터페이스
c = (a, b) -> System.out.println(a + b);
c.cal(4, 5);
c = (a, b) -> System.out.println(a - b);
c.cal(4, 3);
c = (a, b) -> System.out.println(a * b);
c.cal(4, 3);
}
}
interface Calculate {
int cal(int a, int b);
}
class TwoParamAndReturn {
public static vodi main(String[] args) {
Calculate c;
c = (a, b) -> { return a + b; }; // return문의 중괄호는 생략 불가!
System.out.println(c.cal(4, 3));
c = (a, b) -> a + b; // **연산 결과가 남으면, 별도로 명시하지 않아도 반환 대상이 됨!**
System.out.println(c.cal(4, 3));
}
}
interface HowLong {
int len(String s); // 값을 반환하는 메소드
}
class OneParamAndReturn {
public static void main(String[] args) {
HowLong h1 = s -> s.length();
System.out.println(h1.len("I am so happy"));
}
}
interface Generator [
int rand(); // 매개변수가 없는 메소드
}
class NoParamAndReturn {
public static void main(String[] args) {
Generator gen = () -> {
Random rand = new Random();
return rand.nextInt(50);
};
System.out.println(gen.rand());
}
}
@FunctionalInterface
@FunctionalInterface
interface Calculate {
int cal(int a, int b);
default int add(int a, int b) { return a + b; }
static int sub(int a, int b) { return a - b; }
}
추상 메서드란 구현부는 작성하지 않고 선언부만 작성해둔 메소드를 의미한다.
@FunctionalInterface
interface Calculate <T> {
T cal(T a, T b)
}
class LambdaGeneric {
Calculate<Integer> ci = (a, b) -> a + b;
System.out.println(ci.cal(4, 3));
Calculate<Double> cd = (a, b) -> a + b;
System.out.println(ci.cal(4.32, 3.45));
}
default boolean removeIf(Predicate<? super E> filter)
-> Collection< E > // 인터페이스에 정의되어 있는 디폴트 메소드
Predicate // 인터페이스의 추상 메소드는 다음과 같이 정의해 두었다.
boolean test(T t);
// 미리 정의해 두었으므로 Predicate라는 이름만으로 통한다!
@FunctionalInterface
public interface Predicate< T > {
boolean test(T t);
}
Predicate< T >
// 아래 코드는 실제로 작성 해보면 좋을 듯 하다.
public static int sum(Predicate<Integer> p, List<Integer> lst) { // 매개변수를 유심히 보자~~!!
int s = 0;
for(int n : lst) {
if(p.test(n)) {
s += n;
}
}
return s;
}
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 5, 7, 9, 11, 12);
int s;
s = sum(n -> n % 2 == 0, list); // test() 메소드의 몸체가 되는 부분이다.
System.out.println("짝수 합 : " + s);
s = sum(n -> n % 2 != 0, list);
System.out.println("홀수 합 : " + s);
}
autoBoxing, autoUnboxing 과정을 없애기 위해 아래 인터페이스를 만들었다.
IntPredicate
LongPredicate
DoublePredicate
BiPredicate<T, U>
Supplier< T >
public static List<Integer> makeIntList(Supplier<Integer> s, int n) {
List<Integer> list = new ArrayList<>();
for(int i = 0; i < n; i++) {
list.add(s.get()); // 난수를 생성해 담는다.
}
return list;
}
public static void main(String[] args) {
Supplier<Integer> spr = () -> {
Random rand = new Random();
return rand.nextInt(50);
}
List<Integer> list = makeIntList(spr, 5);
System.out.println(list);
list = makeIntList(spr, 10);
System.out.println(list);
}
autoBoxing, autoUnboxing 과정을 없애기 위해 아래 인터페이스를 만들었다.
IntSupplier
LongSupplier
DoubleSupplier
BooleanSupplier
Consumer< T >
class ConsumerDemo {
public static void main(String[] args) [
Consumer<String> c = s -> System.out.println(s);
c.accept("Pineapple"); // 출력이라는 결과를 보임
c.accept("Strawberry");
}
}
autoBoxing, autoUnboxing 과정을 없애기 위해 아래 인터페이스를 만들었다.
IntConsumer
ObjIntConsumer
LongConsumer
ObjLongConsumer
DoubleConsumer
ObjDoubleConsumer
BiConsumer<T, U>
Function< T, R >
class FunctionDemo {
public static void main(String[] args) {
Function<String, Integer> f = s -> s.length();
System.out.println(f.apply("Robot"));
System.out.println(f.apply("System"));
}
}
autoBoxing, autoUnboxing 과정을 없애기 위해 아래 인터페이스를 만들었다.
외우려고 하지말고 찾아서 쓰면 된다.
IntToDoubleFunction
DoubleToIntFunction
IntUnaryOperator
DoubleUnaryOperator
BiFunction(T, U, R)
IntFunction
DoubleFunction
ToIntFunction
ToDoubleFunction
ToIntBiFunction<T, U>
ToDoubleBiFunction<T, U>
public static void main(String[] args) {
List<Integer> ls1 = Arrays.asList(1, -2, 3, -4, 5);
ls1 = new ArrayLsit<>(ls1);
List<Double> ls2 = Arrays.asList(-1.1, 2.2, 3.3, -4.4, 5.5);
ls2 = new ArrayList<>(ls2);
Predicate<Number> p = n -> n.doubleValue() < 0.0; // 삭제의 조건 (이 라인이 핵심)
ls1.removeIf(p);
ls2.removeIf(p);
System.out.println(ls1);
System.out.println(ls2);
}