/ JAVAJUNGSUK

Ch14-7~8. function 패키지

자바의 정석 기초편

0. 목차



Chapter14. 람다와 스트림

Ch14 - 7. java.util.function 패키지

Ch14 - 8. java.util.function 패키지 예제



Ch14 - 7. java.util.function 패키지


▶ java.util.function 패키지란?

▷ 자주 사용되는 다양한 함수형 인터페이스를 제공
▷ 우리는 가져와서 사용 : 편리함


▶ java.util.function 패키지 : 매개변수 1개

▷ 함수형 인터페이스 : java.lang.Runnable
▷ 메서드 : void run()
  • 매개변수 無, 반환값 無

▷ 함수형 인터페이스 : Supplier<T>
▷ 메서드 : T get() → T
  • 매개변수 無, 반환값 有

▷ 함수형 인터페이스 : Consumer<T>
▷ 메서드 : -T→ void accept{T t}
  • Supplier와 반대
  • 매개변수 有, 반환값 無

▷ 함수형 인터페이스 : Function<T, R>
▷ 메서드 : -T→ R apply{T t} → R
  • 일반적인 함수
  • 하나의 매개변수를 받아 결과를 반환

▷ 함수형 인터페이스 : Predicate<T>
▷ 메서드 : -T→ boolean test{T t} → boolean
  • 조건식 표현에 사용
  • 매개변수는 하나, 반환 타입은 boolean
    Predicate<String> isEmptyStr = s -> s.length() == 0; // s(String)를 받아서 길이가 '0'이면 true를 반환
    Stirng s = "";
      
    if (isEmptyStr.test(s)) // 위의 람다식 이름이 test, 그래서 이 코드는 if (s.length() == 0)
      System.out.println("This is an empty String.");
    



▶ java.util.function 패키지 : 매개변수 1개 퀴즈

▶ 알맞은 함수형 인터페이스(java.util.function 패키지)는?

▷ 퀴즈1
f = () -> (int)(Math.random() * 100) + 1;
  • 매개변수 無, 반환값 int
  • Supplier<Integer>
▷ 퀴즈2
f = i -> System.out.println(i + ", ");
  • 매개변수 int, 반환값 無
  • Consumer<Integer>
▷ 퀴즈3
f = i -> i % 2 == 0;
  • 조건식
  • 매개변수 int, 반환값 boolean
  • Predicate<Integer>
▷ 퀴즈4
f = i -> i / 10 * 10;
  • 매개변수 int, 반환값 int
  • Function<Integer, Integer>


▶ java.util.function 패키지 : 매개변수 2개

▷ 함수형 인터페이스 : BiConsumer<T, U>
▷ 메서드 : -T, U→ void accept(T t, U u)
  • 매개변수 2개 有, 반환값 無

▷ 함수형 인터페이스 : BiPredicate<T, U>
▷ 메서드 : -T, U→ boolean test(T t, U u) → boolean
  • 조건식 표현에 사용
  • 매개변수 2개 有, 반환값 boolean

▷ 함수형 인터페이스 : BiFunction<T, U, R>
▷ 메서드 : -T, U→ R apply(T t, U u) → R
  • 매개변수 2개를 받아 하나의 결과를 반환


▶ java.util.function 패키지 : 매개변수 3개

▷ 매개변수 3개 이상 부터는 직접 만들어 사용
@FunctionalInterface
interface TriFunction<T, U, V, R> { // 매개변수 3개, R은 반환 타입
  R apply(T t, U u, V v);
}


▶ java.util.function 패키지 : 매개변수 타입 == 반환 타입

▷ 함수형 인터페이스 : UnaryOperator<T>
▷ 메서드 : -T→ T apply(T t) → T
  • Function의 자손
  • Function과 달리 매개변수와 결과의 타입이 같음

  • UnaryOperator Code
    @FunctionalInterface
    public interface UnaryOperator<T> extends Function<T> { // Function을 상속
      static <T> UnaryOperator<T> identity() { // identity : 항등 함수
        return t -> t; // t를 넣으면 t 그대로 반환
      }
    }
    
▷ 함수형 인터페이스 : BinaryOperator<T>
▷ 메서드 : -T, T→ T apply(T t, T t) → T
  • BiFunction의 자손
  • BiFunction과 달리 매개변수와 결과의 타입이 같음



Ch14 - 8. java.util.function 패키지 예제


▶ 람다식 생성

▷ 1 ~ 100 난수 추출 람다식
Supplier<Integer>
Supplier<Integer>  s = ()-> (int)(Math.random() * 100) + 1;
▷ i, i, i 이런 식으로 나열하는 람다식
Consumer<Integer>
Consumer<Integer>  c = i -> System.out.print(i + ", ");
▷ 짝수 검사 람다식
Predicate<Integer>
Predicate<Integer> p = i -> i % 2 == 0;
▷ 1의 자리 삭제 람다식
Function<Integer, Integer>
Function<Integer, Integer> f = i -> i / 10 * 10; // i의 일의 자리 삭제


▶ main 메서드

▷ 짝수 난수의 일의 자리 0으로 바꾸어 출력
public static void main(String[] args) {
  
  // 람다식 ...
  
  List<Integer> list = new ArrayList<>(); // list 생성
  makeRandomList(s, list); // list를 1 ~ 100 중 난수로 채움
  System.out.println(list); // list 출력
  printEvenNum(p, c, list); // list의 난수 중 짝수 검사 → 짝수만 출력
  List<Integer> newList = doSomething(f, list); // list의 짝수 일의 자리 삭제
  System.out.println(newList); // 최종 list 출력
}


▶ doSomething 메서드

▷ 짝수 난수를 받아 1의 자리 삭제하는 메서드
// i의 일의 자리 삭제 : Function<Integer, Integer> f = i -> i / 10 * 10;

static <T> List<T> doSomething(Function<T, T> f, List<T> list) {
    List<T> newList = new ArrayList<T>(list.size());

    for(T i : list) {
      newList.add(f.apply(i)); // 일의 자리 삭제 후 newList에 저장
    }	
    
    return newList;
}


▶ printEvenNum 메서드

▷ 난수가 짝수인지 검사 후,
▷ [i, i, i] 이런 식으로 배열하여 출력하는 메서드
// 짝수 검사 : Predicate<Integer> p = i -> i % 2 == 0;
// 배열 : Consumer<Integer>  c = i -> System.out.print(i + ", ");

static <T> void printEvenNum(Predicate<T> p, Consumer<T> c, List<T> list) {
  System.out.print("[");
 
  for(T i : list) {
    if(p.test(i)) // 짝수 검사
    c.accept(i); // 배열
  }	
 
  System.out.println("]");
}


▶ makeRandomList 메서드

▷ 난수를 얻는 메서드
static <T> void makeRandomList(Supplier<T> s, List<T> list) {
    for(int i=0;i<10;i++) {
      list.add(s.get());
    }
  }
▷ 전체
import java.util.function.*;
import java.util.*;

class Ex14_2 {
	public static void main(String[] args) {
		Supplier<Integer>  s = ()-> (int)(Math.random()*100)+1;
		Consumer<Integer>  c = i -> System.out.print(i+", "); 
		Predicate<Integer> p = i -> i%2==0; 
		Function<Integer, Integer> f = i -> i/10*10;
		
		List<Integer> list = new ArrayList<>();	
		makeRandomList(s, list);
		System.out.println(list);
		printEvenNum(p, c, list);
		List<Integer> newList = doSomething(f, list);
		System.out.println(newList);
	}

	static <T> List<T> doSomething(Function<T, T> f, List<T> list) {
		List<T> newList = new ArrayList<T>(list.size());

		for(T i : list) {
			newList.add(f.apply(i));
		}	

		return newList;
	}

	static <T> void printEvenNum(Predicate<T> p, Consumer<T> c, List<T> list) {
		System.out.print("[");
		for(T i : list) {
			if(p.test(i))
				c.accept(i);
		}	
		System.out.println("]");
	}

	static <T> void makeRandomList(Supplier<T> s, List<T> list) {
		for(int i=0;i<10;i++) {
			list.add(s.get());
		}
	}
}

// console
[16, 43, 70, 91, 74, 77, 58, 83, 13, 21] // 난수 받자마자
[16, 70, 74, 58, ] // 난수가 짝수인지 검사
[10, 40, 70, 90, 70, 70, 50, 80, 10, 20] // 일의 자리 0으로 바꿈