-
< Java > lamdaJava 2023. 8. 24. 20:46
lamda 란?
람다 함수는 말 그대로 함수(function) 이다.
(메서드가 아니라는 뜻)
이 함수는 자바 스크립트에서 파급되었고, 요즘은 거의 모든 언어에서 사용한다.
익명 메서드를 구현하는 형태라고 생각하면 편하다.
익명객체 이름이 없는 객체를 뜻하듯이 함수명이 없이 선언된 함수와 특정 데이터 영역을 이 함수를 통해서
구현하게끔 하는 형태이다.
자바에서도 람다를 지원하는데, 규칙이 매우 엄격합니다.
아래는 람다 표현식에 규칙입니다.
- 모든 람다 함수는 인터페이스만 가능하다.
- 람다 함수가 되는 함수를 가진 인터페이스는 무조건 람다 함수 하나만 보유해야합니다.(반드시)
- 람다 함수는 인터페이스에서 선언되었기 때문에, 당연히 body 가 없습니다. 따라서 구현 시에 body를 추가합니다.
- FunctionInterface 라는 어노테이션을 인터페이스 선언문 전에 선언해서 람다 인터페이스임을 선언해야합니다.
만약 안하면 컴파일 시 위 조건을 컴파일러가 검색해서, 문제 없으면 자동으로 넣어 줍니다. - JDK1.8부터는 인터페이스에서 static 메서드를 이용해서 메서드 boby 를 질 수 있고
default 키워드를 통해서 기본 메서드 또한 가질 수 있습니다.
즉 위 예를 종합하면, 람다 인터페이스는 총 3개의 메서드를 보유할 수 있는데, 위 두개와 람다 하나입니다.
더이상 보유하게 되면 컴파일 에러가 발생합니다.
문법
(파라미터 1, 2,,,, n ) -> { 파라미터 처리식 }
System.out::println ( 메서드 람다식 )
위 문법에서 파라미터가 하나도 없을 경우엔 () 처리한다.
그리고 구현하는 로직이 있는 경우엔 -> 를 통해 {구현로직} 을 정의한다라고 선언하는 방식입니다.
여기서 -> 는 반드시 넣어야하며
저는 -> 를 메서드 명 이라고 생각하니깐 쉽게 이해 됩니다.
a + b 결과값을 받아서 다음 로직에서 처리를 해야 한다면??
int sum(int a, int b) { return a+b}
(a,b) -> {a + b}
- 파라미터가 하나만 필요한 경우
하나일 경우에는 괄호를 생략해도 됨
만약 구현부가 하나의 수행문인 경우엔 {} 도 생략 가능함.
a -> {return a == 0 ? a : 1}
a -> return a == 0 ? a : 1
파라미터가 없을 경우 : () -> {} 처럼 빈 괄호를 이용해야 한다.
즉 파라미터 위치값은 반드시 존재해야 한다는 것입니다.class MyRun implements Runnable { @Override public void run() { System.out.println("runnable thread run"); try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } System.out.println("end of runnable thread "); } } public class LamdaEx1 { public static void main(String[] args) { Thread t = new Thread(); // 빈 스레드 { run이 없으니깐 아무것도 안 함} // Runnable 객체를 파람으로 받는 스레드 객체를 생성. Thread runnableT = new Thread(new MyRun()); runnableT.start(); Thread anonyT = new Thread(new Runnable() { @Override public void run() { System.out.println("anoy runnable thread run"); try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } System.out.println("end of anoy runnable thread "); } }); anonyT.start(); // Lamda 로 정의 Thread lam = new Thread(() -> { System.out.println("Lamda runnable thread run"); try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } System.out.println("end of Lamda runnable thread "); }); lam.start(); }
list.foreach 람다식
기존 list 요소 뽑아내기
public class LamdaEx2 { public static void main(String[] args) { ArrayList<Integer> l1 = new ArrayList(); l1.add(1); l1.add(2); l1.add(3); // 1번 방법 System.out.println("-----------------------"); for (int i = 0; i < l1.size(); i++) { System.out.println(l1.get(i)); } //2번 방법 System.out.println("-----------------------"); for (Integer i : l1) { System.out.println(i); }
람다 lists.foreach
foreach 를 이용한 람다 함수 적용방법
stream 객체의 메서드를 이용한 형태
stream 객체는 쉽게 표현하자면 다중 스레드를 내부적으로 병렬로 CPU 를 가동하도록 정의된 데이터 스트림입니다,
IO 와는 완전 다른 개념public class LamdaEx2 { public static void main(String[] args) { ArrayList<Integer> l1 = new ArrayList(); l1.add(1); l1.add(2); l1.add(3); // foreach 를 이용한 람다 함수 적용 방법 System.out.println("-----------------------"); l1.forEach(t -> { System.out.println(t); }); System.out.println("-----------------------"); l1.forEach(System.out::println); // 또다른 람다식
@FunctionalInterface 의 추상 메서드를 람다 함수로 가져다 쓰기
람다 함수는 특정 데이터가 있을 때 특정 기능의 함수를 그때그때 적용해서 결과를 도출하기 위한 목적입니다.
import java.util.ArrayList; @FunctionalInterface interface MyInter{ default void sum1() { System.out.println("이건 jdk 1.8 ?? 부터 지원되는 인턴페이스의 기본 메서드 입니다."); } // 아래는 static 메서드 // 1.8 부터 지원되는 메서드 static int sum2() { return 100; } // 하위는 람다 함수로 사용할 메서드, 반드시 추상이어야 한다. public int sum3(int a, int b); } public class LamdaEx2 { public static void main(String[] args) { MyInter function = (x,y) ->x + y; System.out.println(function.sum3(3, 2)); }
public int sum3(int a, int b);
@FunctionalInterface 를 이용하면 해당 interface 에 추상메서드로 선언된 메서드는 자동으로 람다 함수로 적용된다
그리고 만약에 추상메서드가 하나 이상으로 정의된다면 그것은 바로 컴파일 에러가 뜨는 것을 확인 할 수 있었다.
위에 적었듯이 자바의 람다함수는 엄격한 규칙을 가지고 있기때문에 위에 적은 규칙을 주의하여 이용해야겠다.
'Java' 카테고리의 다른 글
< Java > String (0) 2023.08.25 <Java> Stream Optional (0) 2023.08.25 < Java > Stream (0) 2023.08.25 <Java> Operator( 연산자 ) (0) 2023.08.24 <Java> 자료형과 변수 (0) 2023.08.23