[Java] 자바 #45, 람다식 예제 및 활용
- 프로그래밍 언어/Java
- 2019. 3. 16. 14:01
람다식(Lamda)
- 병렬처리, 이벤트 처리, 스트림 처리 등..사용
- JDK 1.8에서 지원.
- 함수형 프로그래밍 방식( <-> 객체지향 프로그래밍)
- 형태는 매개변수를 가지는 코드블럭(=메소드)
- 인터페이스 + 익명객체 + 람다식 같이사용.
- 생김새는 메소드를 선언하는 것과 유사 -> 실제로는 이름없는 클래스와 이름없는 메소드를 만드는 코드
- (중요)람다식을 사용하는 이유는 1회용 익명 메소드가 필요하기 때문 > 하지만 자바는 독립적인 메소드만을 생성하지 못하기 때문에 익명객체를 이용해서 만든다.
1 2 3 4 5 6 7 | interface MyInterface { void test(); } interface MyType { void hello(); } | cs |
위와 같은 인터페이스가 있을 때!
기본적인 익명객체를 이용해서 익명 메소드를 사용하는 방법
// 익명객체
MyInterface my1 = new MyInterface() { new 키워드로 객체 직접 대입
@Override
public void test() { 메소드까지 클래스에 기재하는 것처럼 선언 -> 비용심화
System.out.println("테스트 입니다.");
}
};
my1.test(); 메소드사용
MyType my2 = new MyType() {
@Override
public void hello() {
System.out.println("안녕하세요. 홍길동입니다.");
}
};
my2.hello(); 메소드사용
람다식을 이용해서 익명 메소드를 사용하는 방법
람다식 기본 형태
- (자료형 매개변수) -> { 실행코드; }
a. 매개변수 : 메소드 매개변수
b. "->" : 에로우, 코드블럭을 실행(호출)
c. "{ }" : 메소드 구현부
익명 메소드 -> 람다식을 사용해서 익명 메소드 생성
MyType my3 = () -> { 이런식으로 익명객체를 생성 후 그 안에 오버라이딩 메소드 내용을 기재
System.out.println("안녕하세요 아무개입니다.");
}; // 단일라인 메소드
my3.hello();
MyType my4 = (String message) -> {
System.out.println("안녕하세요.");
System.out.println(message+"입니다.");
System.out.println("감사합니다.");
};
my4.hello("홍길동");
람다식의 간단한 표기 방법
1 2 3 | interface YourType { void talk(String msg); } |
위의 인터페이스를 예로 들면...
매개변수 1개 반환값 X
1. (int num) -> {System.out.println()}; 가장 기본형태
ex)
YourType you = (String name) -> { System.out.printf("내이름은 %s입니다.",name); }
you.talk("홍길동");
2. (int num) -> System.out.println(); 단일코드 -> 실행블럭 제거
ex)
YourType you = (String name) -> System.out.println(name);
you.talk("홍길동");
3. (num) -> System.out.println(); 단일 매개변수 -> 타입 생략 -> 변수명만 기재
ex)
YourType you = (name) -> System.out.println(name);
you.talk("홍길동");
4. num -> System.out.println(); 매개변수가 1개일때는 매개변수를 감싸는 괄호 생략가능
ex)
YourType you = name -> System.out.println(name);
you.talk("홍길동");
1 2 3 | interface MyType { void hello(); } | cs |
- 매개변수 X, 반환값 X
5. () -> System.out.println(); 매개변수가 없는 람다식 -> 괄호를 무조건 기재
ex)
MyType my = () -> System.out.println("이거로 뭘할수있을까...");
1 2 3 | interface MyType { void hello(String name, int age); } | cs |
- 매개변수 2개, 반환값 X
6. (x,y) -> System.out.println(); 매개변수가 여러개 일때 -> 괄호로 무조건 감싸야함
ex)
MyType my = (name, age) -> System.out.printf("내 이름은 %s이고 %d살이야");
my.hello("홍길동",19);
1 2 3 | interface HisType { String getFood(); } | cs |
- 매개변수 X, 반환값 O
7. () -> {return value;} 물론 단일코드이기 때문에 괄호도 생략 가능
ex)
HisType his = () -> return "food";
System.out.println( his.getFood() );
8. () -> value; return문만 있는 단일코드는 return과 괄호를 같이 생략 가능
ex)
HisType his = () -> "food";
System.out.println( his.getFood() );
1 2 3 | interface HisTpye { String sayHello(String name, int age); } | cs |
9. (x,y) -> x+y; 매개변수 2개 이상, 반환타입 O, 리턴문 단일코드
ex)
HisType his = ( name, age ) -> String.format("안녕하세요. 제이름은 %s이고 %d살 입니다.",name, age);
System.out.println(his.sayHello("홍길동",19));
람다식을 이용한 정렬메소드 구현
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 | class User { private String name; private int age; public User() { } public User(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return String.format("%s(%s)", this.name, this.age); } } | cs |
- 위와 같은 User 클래스가 있을 때
- List 컬렉션에 User객체를 5개 담아보았다.
List<User> list = new ArrayList<User>();
list.add(new User("홍길동", 20));
list.add(new User("아무개", 25));
list.add(new User("무지개", 21));
list.add(new User("김린지", 24));
list.add(new User("호호호", 29));
System.out.println(list); 그냥 출력 결과 : [홍길동(20), 아무개(25), 무지개(21), 김린지(24), 호호호(29)]
나이순 정렬을 하고 싶다. -> Collections.sort()와 Arrays.sort()는 이용할 수 없음.
->Comparator 객체를 이용해 구현.
list.sort(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getAge() - o2.getAge(); // 정렬기준. -> 앞에 매개변수 - 뒤의매개변수 -> 오름차순
}
});
System.out.println(list); [홍길동(20), 무지개(21), 김린지(24), 아무개(25), 호호호(29)]
이것을 람다식으로 구현하면 다음과 같다.
람다식 구현(나이기준)
list.sort((o1, o2) -> o2.getAge() - o1.getAge()); //코드량이 현저히 줄었다.(이건 내림차순이다.)
System.out.println(list); [호호호(29), 아무개(25), 김린지(24), 무지개(21), 홍길동(20)]
그렇다면 이름기준으로 정렬은 못하나...? -> X 할수 있다! -> TreeSet을 이용.
TreeSet<User> set = new TreeSet<User>((o1,o2)-> o1.getName().compareTo(o2.getName()));
- TreeSet 타입이 User인 참조타입이므로 기준을 잡기가 힘듬. -> 기준을 잡아주는 작업 -> compareTo 메소드 활용.
set.add(new User("홍길동", 20));
set.add(new User("아무개", 25));
set.add(new User("무지개", 21));
set.add(new User("김린지", 24));
set.add(new User("호호호", 29));
System.out.println(set); [김린지(24), 무지개(21), 아무개(25), 호호호(29), 홍길동(20)]
- compareTo는 String 타입 전용이므로 다시 나이순으로 정렬하기 위한 조건은 위의 람다식으로 쓴 익명객체를 TreeSet생성자 안에 넣어주면 된다.
- TreeSet<User> set = new TreeSet<User>((o1,o2)-> o1.getAge() - o2.getAge()));
람다식 실제 사용
- 인터페이스 변수 = 람다식;
- 람다식과 인터페이스는 밀접한 관계(람다식 시그너처 == 인터페이스 추상메소드의 시그너처)
람다식에서 사용되는 인터페이스
1. 반드시 추상메소드가 유일해야 한다.(*****)
2. 람다식을 담는 인터페이스를 주로 타겟 타입(Target Type)이라고 한다.
3. 람다식을 담는 인터페이스를 주로'함수적(형) 인터페이스, Functional Interface 라고 한다.
4. 자바는 개발자에 사용하기 위한 함수적 인터페이스를 여러개 제공합니다.
'프로그래밍 언어 > Java' 카테고리의 다른 글
[Java] 자바 #47, 스트림의 개념 및 예제 (0) | 2019.03.17 |
---|---|
[Java] 자바 #46, 람다식의 함수형 인터페이스 개념 및 예제 (0) | 2019.03.17 |
[Java] 자바 #44, String split(), StringTokenizer 클래스 ( 문자열 분리 , 쪼개기) (5) | 2019.03.11 |
[Java] 자바 #43, 정규표현식 설명 및 예제 (5) | 2019.03.10 |
[Java] 자바 #42, 익명객체(Anonymous Object) 개념 및 예제 (0) | 2019.03.09 |