람다식
JDK8에서 추가된 기능으로 개발자가 핵심 내용만 구현하고 나머지는 자바 언어에서 자동으로 처리하는 방식인 함수형 스타일이어서 코드가 간결해진다. 인터페이스를 익명클래스보다 간편하게 구현하려고 사용하기 때문에 먼저 인터페이스 구현 방법부터 살펴본다.
인터페이스 구현 방법
interface MyInterface{
public void print();
}
implements 키워드로 클래스 선언
class MyClass1 implements MyInterface{ @Override public void print(){ System.out.println("MyClass1"); } }
익명 클래스 사용
MyInterface mi = new MyInterface(){ @Override public void print(){ System.out.println("익명 클래스로 구현"); } }
익명 클래스로 선언 생성 호출 한번에 처리람다식 사용하기
(new MyInterface(){ @Override public void print(){ System.out.println("한번에 처리"); }).print();
일반 인터페이스 구현m == MyInterface의 익명클래스 인스턴스 참조변수
public static MyInterface test3(){ return new MyInterface(){
@Override public void print(){ System.out.println("hello"); }
}}
MyInterface m = test3(); m.print();
람다식 구현화살표 다음에는 인터페이스에 선언된 추상 메서드의 본문을 구현한다. 근데 이때 인터페이스에 선언된 추상 메서드가 여러 개일 경우에는 어떤 메서드의 본문인지 구별할 방법이 없다. 따라서 람다식으로 구현하려는 인터페이스는 반드시 하나의 메서드만 선언되어야하고 이처럼 하나의 메서드만 선언된 인터페이스를 "함수형 인터페이스"라고 한다.
MyInterface m = () -> System.out.println("hello"); m.print();
람다식 블록
람다식 문법에서 () -> 기호 부분은 람다식의 본문이다. 람다식 본문의 명령문이 한 줄이면 다음처럼 표현하고 return문을 생략해도 명령문에서 처리된 값이 자동으로 반환된다
() -> 명령문;
람다식 본문에 명령문을 여러줄로 구현하려면 다음처러 {}로 감싸야한다.
() -> {명령문1;명령문2;return 값;};
반환값이 존재하는 메서드를 구현할때는 반드시 return문 지정해야하고 명령문이 한줄일때는 return을 생략해도 되지만 블록{}을 사용하면 생략할 수 없다.
제너릭 함수형 인터페이스
interface MyFunc<T>{ T modify(T t); }
public class Test{ public static void main(String[] args){
MyFunc<String> mf1= (str) -> str.toUpperCase() + ":" + str.length(); System.out.println(mf1.modify("hello");
MyFunc<Integer> mf2= (n) -> n*2; System.out.println(mf2.modify(23));
}
}
메서드 참조
람다식을 구현하는 메서드의 리턴 타입과 매개변수는 함수형 인터페이스의 추상메서드와 동일해야함.
인터페이스 객체 생성
static 메서드 : 클래스명::메서드명
인스턴스 메서드 : 참조변수명::메서드명
interface StringFunc{
String modify(String s);
}
public class Test{
static String func(String s){
return s + " hello";
}
public static void main(String\[\] args){
StringFunc sf = Test::func;
System.out.println(sf.modify("Jack"));
}
}
Comprable 구현 클래스, Comparator 익명 클래스, Comparator 람다식
프로그래머스 가장 큰 수로 예시를 들었다.
//Comparable
import java.util.*;
class Solution {
public String solution(int[] numbers) {
String answer = "";
List<S> list = new ArrayList<>();
for(int i=0;i<numbers.length;i++){
list.add(new S(String.valueOf(numbers[i])));
}
Collections.sort(list);
if(list.get(0).num.equals("0"))return "0";
StringBuilder sb = new StringBuilder();
for(int i=0;i<list.size();i++){
sb.append(list.get(i).num);
}
answer = sb.toString();
return answer;
}
}
class S implements Comparable<S>{
String num;
public S(String num){
this.num=num;
}
@Override
public int compareTo(S o){
return (o.num+this.num).compareTo(this.num+o.num);
}
}
Compartor 익명 클래스
import java.util.*;
class Solution {
public String solution(int[] numbers) {
String[] stringNumbers = new String[numbers.length];
for(int i=0;i<numbers.length;i++){
stringNumbers[i]=Integer.toString(numbers[i]);
}
if(stringNumbers[0].equals("0"))return "0";
Arrays.sort(stringNumbers, new Comparator<String>(){
@Override
public int compare(String o1, String o2){
return (o2+o1).compareTo(o1+o2);
}
});
return String.join("",stringNumbers);
}
}
Comparator 람다식
import java.util.*;
class Solution {
public String solution(int[] numbers) {
String[] stringNumbers = new String[numbers.length];
for(int i=0;i<numbers.length;i++){
stringNumbers[i]=Integer.toString(numbers[i]);
}
if(stringNumbers[0].equals("0"))return "0";
Arrays.sort(stringNumbers, (o1,o2)->(o2+o1).compareTo(o1+o2));
return String.join("",stringNumbers);
}
}
Comparable : 클래스 정렬 기준
Comparator : 익명클래스나 람다식으로 값 비교
람다식은 인터페이스를 익명클래스로 생성하는 것과 같은데오버라이드 할 메소드가 하나인 함수형 인터페이스에만 사용이 가능하다.