[JAVA] 람다와 스트림 ( Lambda & Stream ) ③

DongGyu Jung·2022년 4월 28일
0

자바(JAVA)

목록 보기
51/60
post-thumbnail

🏃‍♂️ 들어가기 앞서..

본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕

*해당 교재의 목차 순서와 구성을 참고하여 작성하며
각 내용마다 부족할 수 있는 내용이나 개인적으로 궁금한 점은
추가적인 검색을 통해 채워나갈 예정입니다.



💼 java.util.function 패키지

자중 사용되는 다양한 " 함수형 인터페이스 " 제공

일일이 사용할 때마다
새로운 함수형 인터페이스를 만들어서 구현하는
불필요한 작업을

자주 사용되는 유형에 맞춰
미리 표준화된 함수형 인터페이스를 제공해준 것이
java.util.function 패키지 이다.

덕분에
함수형 인터페이스에 정의된 메서드 이름통일되고
재사용성 / 유지보수 측면에서 좋다는
장점이 있다.


대표적으로 자주 쓰이는
가장 기본적인 함수형 인터페이스는 아래와 같다.

  • " 매개변수 " & " 반환값 유무 "에 따라 4가지로 분류

    • java.lang.Runnable : 매개변수 X / 반환값 X --[메서드]--> void run()

    • Supplier<T> : 매개변수 X / 반환값 O --[메서드]--> T get()

    • Consumer<T> : 매개변수 O / 반환값 X --[메서드]--> void accept(T t)

    • Function<T,R> : 매개변수 O / 반환값 O (일반적인 함수) --[메서드]--> R apply(T t)


  • Function<T,R> ▶ 반환값 boolean == Predicate<T>
    • Predicate<T> : 조건식을 표현하는데 사용됨. --[메서드]--> boolean test(T t)

    • 《 사용 방법 》

      Predicate<String> isEmptyStr = s -> s.length() == 0 ; // 연산결과가 boolean형의 실행문
      String s = "";
      
      if (isEmptyStr.test(s)) // if(s.length() == 0) 동일
      	System.out.println("Empty String!!");

✌ "매개변수" 가 "2개" 인 FunctionalInterface

위에서 알아본 인터페이스는
말했다시피
가장 기본적인 인터페이스이고

더 나아가
매개변수2개인 함수형 인터페이스도 존재한다.
( 말 그대로 2개이기 때문에 Bi라는 키워드가 앞에 붙는다. )

  • " 매개변수 "가 2개인 함수형 인터페이스 ( 반환값 여부가 기준이 되지 않음!! )

    • BiConsumer<T,U>
      : " 두 개의 매개변수 "만 있고 반환값 X --[메서드]--> void accept(T t, U u)
    • BiFunction<T,U,R>
      : " 두 개의 매개변수 " & 하나의 결과를 반환 --[메서드]--> R apply(T t, U u)
    • BiPredicate<T>
      : " 두 개의 매개변수 " & 하나의 boolean타입 결과를 반환 --[메서드]--> boolean test(T t, U u)

🤘 "매개변수" 타입 === "반환값" 타입 FunctionalInterface

이번에는
매개변수의 "타입"과 반환값의 "타입"이
일치한다는 특징을 가진 함수형 인터페이스로

" 단항 연산자 " 와 " 이항 연산자 "로 나눠진다.

타입이 일치하기 때문에 제네릭스엔 타입이 하나만 작성되어 있다.
★ 공통 : " 투입 & 반환 타입 동일 "

  • UnaryOperator<T>
    : " 두 개의 매개변수 "만 있고 반환값 X --[메서드]--> T apply(T t)
    Function 의 자손
@FunctionalInterface
// Function의 자손
public interface UnaryOperator<T> extend Function<T, T> {
	static <T> UnaryOperator<T> identity() { // 항등함수 유형
		return t -> t; // 
    }
}
  • BinaryOperator<T>
    : " 두 개의 매개변수 " & 하나의 결과를 반환 --[메서드]--> T apply(T t, T t)
    BiFunction 의 자손

해당 특징을 제외하면
앞서 알아봤던
Function동일하다.

조금 위의 UnaryOperator의 예시에서
" static에 제네릭이 붙어있는 것 "을 제네릭 메서드 라고 한다.
static은 인스턴스가 생성되기 전에 먼저 메모리에 올라가게 되는데
이 코드를 살펴보자.

// 오류 발생
public class Member<T> {
	static T getName(T name){
    	return name ;
    }
}

위와같이
해당 클래스 타입 객체를 매개변수로 받거나 반환타입이 해당 클래스 타입이라면

인스턴스가 생성되기 전까진
T의 타입이 뭔지 정해지지 않기 때문에 오류가 발생하는 것이다.

그 때, 아래와 같이

public class Member<T> {
	static <T> getName(T name){
    	return name ;
    }
}

코드상으로는 class의 제네릭 <T>와 static 메서드의 <T>
같아 보일 순 있지만
완전히 다른 별개의 제네릭 타입으로서
" 해당 클래스가 인스턴스화가 되지 않더라도 먼저 메모리에 올라갈 수 있도록 "
분리시켜 지정하는 방법이다.

0개의 댓글