Java

< Java > lamda

98kg 2023. 8. 24. 20:46

lamda 란?


람다 함수는 말 그대로 함수(function) 이다.
 (메서드가 아니라는 뜻) 
 이 함수는 자바 스크립트에서 파급되었고, 요즘은 거의 모든 언어에서 사용한다.
  익명 메서드를 구현하는 형태라고 생각하면 편하다.
익명객체 이름이 없는 객체를 뜻하듯이 함수명이 없이 선언된 함수와 특정 데이터 영역을 이 함수를 통해서
구현하게끔 하는 형태이다.
  자바에서도 람다를 지원하는데, 규칙이 매우 엄격합니다.

아래는 람다 표현식에 규칙입니다.


  1.  모든 람다 함수는 인터페이스만 가능하다.
  2. 람다 함수가 되는 함수를 가진 인터페이스는 무조건 람다 함수 하나만 보유해야합니다.(반드시)
  3. 람다 함수는 인터페이스에서 선언되었기 때문에, 당연히 body 가 없습니다. 따라서 구현 시에 body를 추가합니다.
  4. FunctionInterface 라는 어노테이션을 인터페이스 선언문 전에 선언해서 람다 인터페이스임을 선언해야합니다.
     만약 안하면 컴파일 시 위 조건을 컴파일러가 검색해서, 문제 없으면 자동으로 넣어 줍니다.
  5. 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  에 추상메서드로 선언된 메서드는 자동으로 람다 함수로 적용된다

그리고 만약에 추상메서드가 하나 이상으로 정의된다면 그것은 바로 컴파일 에러가 뜨는 것을 확인 할 수 있었다.

 

위에 적었듯이 자바의 람다함수는 엄격한 규칙을 가지고 있기때문에 위에 적은 규칙을 주의하여 이용해야겠다.