Java 8 Lambda 람다 #1

6 분 소요

Intro

Java 8에 새로 도입된 Lambda에 대해서 알아보자.
Java 8 Lambda 강좌 - Java Brains
연습예제 github

람다, 왜 사용하나?

  • 함수형 프로그래밍을 가능하게 해준다.
  • 읽기 쉽고 간결한 코드생성을 도와준다.
  • API와 library 사용을 더 쉽게 해준다.
  • 병렬 프로세싱을 지원해준다.

interface type 람다

Greeter.java

1
2
3
4
5
6
7
8
9
10
11
public class Greeter {

	public static void main(String[] args) {
		MyLambda myLambda = () -> System.out.println("Hello World!!");
		myLambda.foo();
	}
}

interface MyLambda {
	void foo();
}

MyLambda 인터페이스의 foo 함수를 사용하기 위해서는
인터페이스를 구현한 클래스를 생성하고 foo함수 기능을 Override하여 사용하였으나

람다는 위의 과정 필요없이
‘->’ 뒤에 foo함수 기능을 정의하여 바로 실행할 수 있게 해준다.

인터페이스 메소드를 구현한 클래스가 없는데 어떻게 람다식 표현만으로
인터페이스 메소드를 사용가능하게 하는걸까?
그건 자바 컴파일러가 런타임시에 람다표현식을 토대로 인터페이스의 어떤 메소드 Type으로 할당할지 추론이 가능하기 때문이다.

Runnable Type 람다

RunnableExample.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class RunnableExample {

	public static void main(String[] args) {
		// Thread 생성
		Thread myThread = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("Print inside Runnable");
			}
		});

		// Thread 실행
		myThread.start();

		// 람다식을 사용한 Runnable로 Thread 생성
		Thread myLambdaThread = new Thread(() -> System.out.println("Print inside Runnable"));

		// Thread 실행
		myLambdaThread.start();
	}

}

Thread에 할당되는 Runnable도 interface이기 때문에 run 메소드 Override 구현을 람다식으로 간편하게 대체 가능하다.

비람다식 VS 람다식

람다식이 도입되기 전 소스코드와
람다식이 도입된 후 소스코드를 예제를 통해 알아보자.
예제는 코드는 아래 4가지 기능을 구현한다.

  • Step1. List 정렬
  • Step2. Step1 결과 출력
  • Step3. Step1 결과에 조건1 추가후 출력
  • Step4. Step1 결과에 조건2 추가후 출력

출력 대상 Object

Person.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class Person {
	private String firstName;
	private String lastName;
	private int age;

	public Person(String firstName, String lastName, int age) {
		super();
		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [lastName=" + lastName + ", firstName=" + firstName + ", age=" + age + "]";
	}

}

비람다식

Unit1ExcerciseSolutionJava7.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public static void main(String[] args) {
	List<Person> people = Arrays.asList(
		new Person("길동", "홍", 45),
		new Person("꺽정", "임", 30),
		new Person("보고", "장", 37),
		new Person("철수", "김", 12),
		new Person("영이", "김", 12)
	);

	System.out.println("Step1. lastname으로 정렬하라.");
	Collections.sort(people, new Comparator<Person>() {
		@Override
		public int compare(Person p1, Person p2) {
			return p1.getLastName().compareTo(p2.getLastName());
		}
	});

	System.out.println("Step2. list의 Person Objects 출력하라.");
	printAll(people);

	System.out.println("Step3. '김'씨성의 Persons 출력하라.");
	printConditionally(people, new Condition() {
		@Override
		public boolean test(Person p) {
			return p.getLastName().startsWith("김");
		}
	});

	System.out.println("Step4. 이름이 '길'로 시작하는 Persons 출력하라.");
	printConditionally(people, new Condition() {
		@Override
		public boolean test(Person p) {
			return p.getFirstName().startsWith("길");
		}
	});
}

/**
 * people들 정보를 모두 출력한다.
 * @param people
 */
private static void printAll(List<Person> people) {
	for (Person p : people) {
		System.out.println(p.toString());
	}
}

/**
 * 조건
 */
interface Condition {
	boolean test(Person p);
}

/**
 * people들 정보중 condition 조건에 해당하는 Person만 출력됨
 * @param people
 * @param condition
 */
private static void printConditionally(List<Person> people, Condition condition) {
	for (Person p : people) {
		if(condition.test(p)) {
			System.out.println(p.toString());
		}
	}
}
  • 결과값
Step1. lastname으로 정렬하라.
Step2. list의 Person Objects 출력하라.
Person [lastName=김, firstName=철수, age=12]
Person [lastName=김, firstName=영이, age=12]
Person [lastName=임, firstName=꺽정, age=30]
Person [lastName=장, firstName=보고, age=37]
Person [lastName=홍, firstName=길동, age=45]
Step3. '김'씨성의 Persons 출력하라.
Person [lastName=김, firstName=철수, age=12]
Person [lastName=김, firstName=영이, age=12]
Step4. 이름이 '길'로 시작하는 Persons 출력하라.
Person [lastName=홍, firstName=길동, age=45]

람다식

Unit1ExcerciseSolutionJava8.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public static void main(String[] args) {
	List<Person> people = Arrays.asList(
		new Person("길동", "홍", 45),
		new Person("꺽정", "임", 30),
		new Person("보고", "장", 37),
		new Person("철수", "김", 12),
		new Person("영이", "김", 12)
	);

	System.out.println("Step1. lastname으로 정렬하라.");
	Collections.sort(people, (p1, p2) -> p1.getLastName().compareTo(p2.getLastName()));
//		Collections.sort(people, new Comparator<Person>() {
//			@Override
//			public int compare(Person p1, Person p2) {
//				return p1.getLastName().compareTo(p2.getLastName());
//			}
//		});

	System.out.println("Step2. list의 Person Objects 출력하라.");
	printConditionally(people, (p) -> true);
//		printAll(people);

	System.out.println("Step3. '김'씨성의 Persons 출력하라.");
	printConditionally(people, (p) -> p.getLastName().startsWith("김"));
//		printConditionally(people, new Condition() {
//			@Override
//			public boolean test(Person p) {
//				return p.getLastName().startsWith("김");
//			}
//		});

	System.out.println("Step4. 이름이 '길'로 시작하는 Persons 출력하라.");
	printConditionally(people, (p) -> p.getFirstName().startsWith("길"));
//		printConditionally(people, new Condition() {
//			@Override
//			public boolean test(Person p) {
//				return p.getFirstName().startsWith("길");
//			}
//		});
}

//	/**
//	 * people들 정보를 모두 출력한다.
//	 * @param people
//	 */
//	private static void printAll(List<Person> people) {
//		for (Person p : people) {
//			System.out.println(p.toString());
//		}
//	}

//	/**
//	 * 조건
//	 */
//	interface Condition {
//		boolean test(Person p);
//	}

/**
 * people들 정보중 condition 조건에 해당하는 Person만 출력됨
 * @param people
 * @param predicate
 */
private static void printConditionally(List<Person> people, Predicate<Person> predicate) {
	for (Person p : people) {
		if(predicate.test(p)) {
			System.out.println(p.toString());
		}
	}
}

주석 제거 Unit1ExcerciseSolutionJava8.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public static void main(String[] args) {
	List<Person> people = Arrays.asList(
		new Person("길동", "홍", 45),
		new Person("꺽정", "임", 30),
		new Person("보고", "장", 37),
		new Person("철수", "김", 12),
		new Person("영이", "김", 12)
	);

	System.out.println("Step1. lastname으로 정렬하라.");
	Collections.sort(people, (p1, p2) -> p1.getLastName().compareTo(p2.getLastName()));

	System.out.println("Step2. list의 Person Objects 출력하라.");
	printConditionally(people, (p) -> true);

	System.out.println("Step3. '김'씨성의 Persons 출력하라.");
	printConditionally(people, (p) -> p.getLastName().startsWith("김"));

	System.out.println("Step4. 이름이 '길'로 시작하는 Persons 출력하라.");
	printConditionally(people, (p) -> p.getFirstName().startsWith("길"));
}

/**
 * people들 정보중 condition 조건에 해당하는 Person만 출력됨
 * @param people
 * @param predicate
 */
private static void printConditionally(List<Person> people, Predicate<Person> predicate) {
	for (Person p : people) {
		if(predicate.test(p)) {
			System.out.println(p.toString());
		}
	}
}
  • 결과값
Step1. lastname으로 정렬하라.
Step2. list의 Person Objects 출력하라.
Person [lastName=김, firstName=철수, age=12]
Person [lastName=김, firstName=영이, age=12]
Person [lastName=임, firstName=꺽정, age=30]
Person [lastName=장, firstName=보고, age=37]
Person [lastName=홍, firstName=길동, age=45]
Step3. '김'씨성의 Persons 출력하라.
Person [lastName=김, firstName=철수, age=12]
Person [lastName=김, firstName=영이, age=12]
Step4. 이름이 '길'로 시작하는 Persons 출력하라.
Person [lastName=홍, firstName=길동, age=45]

람다식을 사용하면서 변경된 메소드 하나가 보이시나요?
그 메소드 차이점을 찾으셨다면 당신은 꼼꼼하거나 예리한 사람이겠죠?
람다식을 사용하면서 기존 Condition Interface가 사라지고 Predicate Interface로 대체했는데요.
Predicate는 람다와 함께 1.8부터 도입된 인터페이스 입니다.
이것은 함수형 인터페이스로써 람다식 또는 메서드 참조의 할당 대상으로 사용할 수 있습니다.
이처럼 람다가 도입되면서 람다식을 더 수월하게 사용할 수 있도록 함수형 인터페이스들도 함께 제공되는데요.
관련된 내용은 보실 분은 다음 포스팅으로 넘어가세요.

Java 8 Lambda 람다 #2 link

댓글남기기