본문 바로가기
Programming Languages/Java

Chapter 32. 람다식

by 더 이프 2023. 1. 31.
728x90

목차

    1. 람다식

    ■ 람다식이란?

    • 람다식은 객체를 정의 및 생성함(익명클래스와 같음)
    • 람다는 메소드가 주체임
    • 람다는 추상메소드가 하나인 인터페이스만 정의 가능
    • 독립적으로 존재 불가능하기 때문에 적용 가능한 대상 필요

    ■ 람다식 매개변수

    • 매개변수의 자료형을 생략 가능
    • 매개변수의 이름 변경 가능
    • 매개변수가 하나이면 매개변수를 감싸는 괄호 생략 가능

    ■ 람다식 구현부

    • 구현부의 명령이 하나일 때 중괄호 생략 가능
    • 중괄호를 생략하고 리턴 자료형이 정해져 있으면 리턴값으로 사용됨
    • 중괄호를 생략하면 return을 적을 수 없음
    • 지역변수를 매개변수에 넣어 사용하지 않아도 바로 사용 가능
    • 지역변수명과 같은 변수명을 매개변수명으로 사용 불가

    ■ 인터페이스

    • 기본 함수형 인터페이스(파라미터가 없거나 하나임) 
      함수형 인터페이스 메소드 매개변수 반환값
      java.lang.Runnable void run() X X
      Supplier<T> T get() X O
      Consumer<T> void accept(T t) O X
      Function<T, R> R apply(T t) O O
      Predicate<T> boolean test(T t) O O
    • 파라미터가 두개인 함수형 인터페이스
      함수형 인터페이스 메소드 매개변수 반환값
      BiConsumer<T,U> void accept(T t, U u) O O
      BiFunction<T,U,R> R apply(T t, U u) O O
      BiPredicate<T,U boolean test(T t, U u) O O
    • 파라미터 타입이 반환타입과 일치하는 인터페이스
      함수형 인터페이스 메소드 매개변수 반환값
      UnaryOperator<T> T apply(T t) O O
      BinaryOperator<T> T apply(T t, T t) O O

     

    2. 예시

    ■ Instrument

    package j24_람다;
    
    // 함수형 인터페이스로 지정하는것
    // 추가적인 추상메소드 작성을 막아줌
    // default 메소드는 여러개 작성 가능
    @FunctionalInterface
    public interface Instrument {
    
    	public String play(String instrument);
    }

    Lamda1

    package j24_람다;
    
    public class Lamda1 {
    
    	public static void main(String[] args) {
    		
    		Instrument instrument = new Instrument() {
    			
    			@Override
    			public String play(String instrument) {
    				return instrument + "을(를) 연주합니다.";
    			}
    		};
    		
    		Instrument instrument2 = (String itm) -> {
    			return itm + "을(를) 연주합니다.";
    		};
    		
    		// 매개변수의 자료형을 생략할 수 있다.
    		// 매개변수의 이름을 바꿀 수 있다.
    		Instrument instrument3 = (itm) -> {
    			return itm + "을(를) 연주합니다.";
    		};
    		
    		// 매개변수가 하나이면 매개변수를 감싸는 괄호를 생략할 수 있다.
    		Instrument instrument4 = itm -> {
    			return itm + "을(를) 연주합니다.";
    		};
    		
    		// 구현부의 명령이 하나일 때 중괄호를 생략할 수 있다.
    		// 이때 리턴자료형이 정해져있으면 리턴값으로 사용이 된다.
    		// 중괄호를 생략하면 return을 적을 수 없음
    		Instrument instrument5 = itm -> itm + "을(를) 연주합니다.";
    		
    		// 지역변수를 매개변수에 넣어 사용하지 않아도 바로 사용 가능
    		// 지역변수명과 같은 변수명을 매개변수명으로 사용 불가
    		int result = 10 + 20;
    		
    		Instrument instrument6 = itm -> itm + "을(를) 연주합니다." + result;
    		
    		System.out.println(instrument2.play("기타"));
    		System.out.println(instrument.play("트럼펫"));
    		System.out.println(instrument6.play("피아노"));
    		
    	}
    }

    Lamda2

    package j24_람다;
    
    import java.time.LocalDate;
    import java.time.format.DateTimeFormatter;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.function.Consumer;
    import java.util.function.Function;
    import java.util.function.Predicate;
    import java.util.function.Supplier;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    public class Lamda2 {
    
    	public static void main(String[] args) {
    		
    		// 1. Runnable - run()
    		Runnable a = () -> System.out.println("실행");
    		Runnable b = () -> {
    			System.out.println("여");
    			System.out.println("러");
    			System.out.println("명");
    			System.out.println("령");
    			System.out.println("실");
    			System.out.println("행");
    		};
    		
    		a.run();
    		b.run();
    		
    		// 2. Supplier<T> - T get()
    		Supplier<LocalDate> c = () -> LocalDate.now();
    		Supplier<String> d = () -> {
    			LocalDate now = LocalDate.now();
    			return now.format(DateTimeFormatter.ofPattern("yyyy년 MM월 dd일"));
    		};
    		
    		System.out.println(c.get());
    		System.out.println(d.get());
    		
    		// 3. Consumer<T> - void accept(T t)
    		Consumer<String> e = name -> {
    			System.out.println("이름 : " + name);
    			System.out.println("오늘 날짜 : " + d.get());
    		};
    		
    		e.accept("이종현");
    		
    		// 메소드 참조 표현식 ([인스턴스] :: [메소드명 또는 new])
    		Consumer<String> f = System.out :: println;
    		f.accept("출력");
    		
    		List<String> names = new ArrayList<>();
    		names.add("김동민");
    		names.add("김두영");
    		names.add("장진원");
    		names.add("조병철");
    		
    		Consumer<String> g = name -> System.out.println("이름 : " + name + "님");
    		
    		names.forEach(g);
    		
    		names.forEach(name -> {
    			System.out.println("이름을 출력합니다.");
    			System.out.println("이름 : " + name);
    			System.out.println();
    		});
    		
    		Map<String, String> userMap = new HashMap<>();
    		userMap.put("username", "aaa");
    		userMap.put("password", "1234");
    		
    		userMap.forEach((key, value) -> {
    			System.out.println("key : " + key);
    			System.out.println("value : " + value);
    			System.out.println();
    		});
    		
    		// 4. Function<T, R>
    		Function<String, Integer> h = num -> Integer.parseInt(num);
    		
    		int convertStrNum1 = h.apply("10000");
    		int convertStrNum2 = h.apply("20000");
    		
    		System.out.println(convertStrNum1 + convertStrNum2);
    		
    		// 5. Predicate<T>
    		Predicate<String> p1 = str -> str.startsWith("김");
    		Predicate<String> p2 = str -> str.startsWith("이");
    		
    		
    		Function<Predicate<String>, Boolean> function1 =
    				predicate -> predicate.or(str -> str.startsWith("이")).test("김준일");
    		
    		boolean rs = function1.apply(str -> str.startsWith("김"));
    		
    		System.out.println(rs);
    		
    		List<String> nameList = new ArrayList<>();
    		nameList.add("김종환");
    		nameList.add("고병수");
    		nameList.add("김상현");
    		nameList.add("김준경");
    		
    		// 스트림 -> 일회용
    		Stream<String> stream = nameList.stream().filter(name -> name.startsWith("김"));
    //		stream.forEach(name -> System.out.println(name));
    		List<String> newList = stream.collect(Collectors.toList());
    		System.out.println(newList);
    		
    		System.out.println("========================================");
    		
    		nameList.stream()
    			.filter(name -> name.startsWith("김"))
    			.collect(Collectors.toList())
    			.forEach(System.out::println);
    	}
    }