정의되어 있는 함수형 인터페이스

gustjtmd·2022년 1월 13일
0

Java

목록 보기
32/40

미리 정의되어 있는 함수형 인터페이스

Predicate<T>	boolean tedt(T t)
Supplier<T>	T get();
Consumer<T>	void accept(T t)
Function<T,R>	R apply(T t)

Predicate<'T'>

Predicate 인터페이스에는 다음 추상 메소드가 존재한다.
boolean tst(T t);	//전달된 인자를 대상으로 treu, false를 판단할 때
따라서 Pridecate<T> 인터페이스는 전달된 인자를 판단하여 true 또는 false를 반환해야
하는 상황에서 유용하게 사용할 수 있다.
---------------------------------------------------------------------
public class PredicateDemo {
    public static int sum(Predicate<Integer> p , List<Integer> lst){
        int s = 0;
        for(int n : lst){
            if(p.test(n))
                s += n;
        }
        return s;
    }
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,5,7,9,11,12);
        int s;
        s = sum(n -> n%2 == 0,list);
        System.out.println("짝수 합 : " +s);

        s = sum(n -> n%2 != 0,list);
        System.out.println("홀수 합 : " +s);
    }
}
---------------------------------------------------------------------
짝수 합 : 12
홀수 합 : 33
---------------------------------------------------------------------------
public interface Predicate<T>{
  	boolean test(T t);
  }
public static int sum(Predicate<Integer> p, List<Integer> 1st{...}
위 메소드의 매개변수 선언을 볼때 Predicate가 어떤 인터페이스인지 알고 있다면 바로 다음과
같이 판단 할 수 있다.
'boolean test(Integer t)메소드 정의에 해당하는 람다식을 작성해야 전달해야 한다'
이것이 다양한 함수형 인터페이스를 표준화해서 자바 라이브러리에 포함시킨 이유.

Predicate<'T'>를 구체화하고 다양화 한 인터페이스들.

제공한 이유는 불필요한 언박싱 오토박싱 과정을 막기위해서.
Predicate<T>에서 T를 다음과 같이 기본 자료형으로 결정하여 정의한 인터페이스들도 존재함.
IntPredicate	boolean test(int value)
LongPredicate	boolean test(long value)
DoublePredicate boolean test(double value)
그리고 Predicate<T>와 달리 두개를 인자로 받아서 true 또는 false를 결정할수있는
다음 인터페이스도 정의되어 있다.
BiPredicate<T,U> boolean test(T t, U u);
---------------------------------------------------------------------
public class IntPredicateDemo {
    public static int sum(IntPredicate ip, List<Integer> lst){
        int s = 0;
        for(int n : lst){
            if(ip.test(n))
                s += n;
        }
        return s;
    }
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,5,7,9,11,12);
        int s;
        s = sum(n -> n%2 == 0,list);
        System.out.println("짝수 합 : " +s);

        s = sum(n -> n%2 != 0, list);
        System.out.println("홀수 합 : " +s);
    }
}
-----------------------------------------------------------------------
짝수 합 : 12
홀수 합 : 33

Supplier<'T'>

Supplier<'T'> 인터페이스에는 다음 추상 메소드가 존재한다.
T get(); //단순히 무엇인가 반환할때.
public class SupplierDemo {
    public static List<Integer> makeIntList(Supplier<Integer> s, int n){
        List<Integer> list = new ArrayList<>(); //컬렉션 인스턴스 생성

        for(int i = 0; i< n; i++)
            list.add(s.get());  //난수를 생성해 담는다.

        return list;
    }
    public static void main(String[] args) {
        Supplier<Integer> spr = () ->{
            Random rand = new Random();
            return rand.nextInt(50);
        };

        List<Integer> list = makeIntList(spr,5);
        System.out.println(list);

        list = makeIntList(spr, 10);
        System.out.println(list);
    }
}
-------------------------------------------------------------------
[47, 29, 23, 22, 2]
[2, 18, 3, 39, 43, 17, 15, 35, 5, 25]
-------------------------------------------------------------------
public static List<Integer> makeIntList(Supplier<Integer> s, int n)

첫 번째 인자를 통해서 컬렉션 인스턴스에 담을 정수의 생성 방법을 결정할 수 있다.
위 예제에서는 난수의 생성을 택했지만 람다식의 작성을 달리하여 동일한 특정 값을
담을 수도 있고 1씩 증가하는 정수들을 담을 수도 있다.

Supplier<'T'> 구체화 한 인터페이스들.

Supplier<T>에서 T를 기본 자료형으로 결정하여 정의한 인터페이스들은 다음과 같다.
  
IntSupplier		int getasInt()
LongSupplier		long getAsLong()
DoubleSupplier		double getAsDouble()
BooleanSupplier		boolean getAsBoolean()
IntSupplier 기반으로 수정해보기
  public class IntSupplierDemo {
    public static List<Integer> makeIntList(IntSupplier is, int n){
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < n; i++)
            list.add(is.getAsInt());

        return list;
    }
    public static void main(String[] args) {
        IntSupplier ispr = () -> {
            Random rand = new Random();
            return rand.nextInt(50);
        };
        List<Integer> list = makeIntList(ispr,5);
        System.out.println(list);

        list = makeIntList(ispr,10);
        System.out.println(list);
    }
}

Consumer<'T'>

Consumer<T> 인터페이스에는 다음 추상 메소드가 존재한다. Consumer라는 이름 처럼
전달 인자를 소비하는 형태로 매개변수화 반환형이 선언되어 있다.
(인자는 전달받지만 반환은 하지 않는다는 뜻)

void accept(T t); //전달된 인자 기반으로 반환 이외의 다른 결과를 보일때.

따라서 Consumer<T> 인터페이스는 전달된 인자를 가지고 어떤 결과를 보여야 할 때 유용하게
사용된다.

public class ConsumerDemo {
  public static void main(String[] args) {
      Consumer<String> c = s -> System.out.println(s);
      c.accept("Pineapple");  //출력이라는 결과를 보임
      c.accept("Strawberry");
  }
}
--------------------------------------------------------------------
Pineapple
Strawberry

Consumer<'T'>를 구체화하고 다양화 한 인터페이스들

Consumer<T>에서 T를 기본 자료형으로 결정하여 정의한 인터페이스들과, 매개변수의 선언을
다양화 한 인터페이스들은 다음과 같다.

IntConsumer		void accpt(int value)
ObjIntConsumer<T>	void accpt(T t, int value)

LongConsumer		void accpet(long value)
ObjLongConsumer<T>	void accpet(T t,long value)

DoubleConsumer		void accpet(double value)
ObjDoubleConsumer<T>	void accpet(T t,double value)

BiConsumer<T, U>	void(T t, U u)
이들은 추상 메소드 중심으로 이해하고, 필요할 때 참조할 수 있으면 된다.

public class ObjIntConsumerDemo {
  public static void main(String[] args) {
      ObjIntConsumer<String> c = (s,i) -> 
		System.out.println(i + ". " +s);

      int n = 1;
      c.accept("Toy",n++);
      c.accept("Book",n++);
      c.accept("Candy",n);
  }
}

1. Toy
2. Book
3. Candy

Function<T, R>

Function<T,R> 인터페이스에는 다음 추상 메소드가 존재한다.
R apply(T t);	//전달 인자와 반환 값이 모두 존재할때.
이렇듯 Function<T,R>의 추상 메소드는 전달 인자와 반환 값이 있는 가장 보편적인 형태이다.
따라서 프로그래머가 흔히 사용 할 수 있는 인터페이스이다.

Function<String, Integer> f = s -> s.length();
      System.out.println(f.apply("Robot"));
      System.out.println(f.apply("System"));

5
6

Function<T,R>을 구체화하고 다양화 한 인터페이스들

Function<T,R>에서 TR을 모두 기본 자료형으로 결정하여 정의한 인터페이스들
---------------------------------------------------------------------
IntToDoubleFunction	double applyAsDouble(int value)
(int 타입을 Double)
DoubleToIntFunction	int applyAsInt(Double value)
(Double 타입을 int)
---------------------------------------------------------------------
Function<T,R>에서 TR의 자료형이 일치한다면
IntUnaryOperator	int applyAsInt(int operand)
DoubleUnaryOperator	double applyAsDouble(double operand)
----------------------------------------------------------------------
Function<T,R>에 위치한 추상 메소드의 매개변수 선언과 반환형을 다양화 한것들
BiFunction<T,U,R>	R apply(T t, U u)
IntFunction<R>		R apply(int value)

DoubleFunction<R>	R apply(double value)
ToIntFunction<T>	int applyAsInt(T value)

ToDoubleFunction<T>	double applyAsDouble(T value)
ToIntBiFunction<T,U>	int applyAsInt(T t,U u)
ToDoubleBiFunction<T,U>	double applyAsDouble(T t,U u)
------------------------------------------------------------------------
T,R또는 T,U,R의 자료형이 모두 일치하는 경우
UnaryOperator<T>		T apply(T t)
BinaryOperator<T>		T apply(T t1, T t2)

UnaryOperator<T>Function<T,R>BinaryOperator<T>BiFunction<T,U,R>을 상속하여 정의한 인터페이스이다.

removeIf 메소드를 사용해보자.

함수형 인터페이스 Collection<E> 인터페이스에 정의되어 있는 다음 디폴트 메소드
default boolean removeIf(Predicate<? super E> filter)

위의 메소드 removeIf 매개변수 선언은 다음과 같다.
Predicate<? super E> filter

따라서 ArrayList<Integer> 인스턴스를 생성하면 그 안에 존재하는 removeIf 메소드 E는
다음과 같이 변경된다
public boolean removeIf(Predicate<? super Integer> filter){...}

매개변수 선언에<? super Integer>가 존재하므로 다음 참조변수 대상으로 람다식을 작성하여
위의 메소드의 인자로 전달할 수 있다.
Predicate<Integer> f = ...
Predicate<Number> f = ...
Predicate<Object> f = ...

removeIf메소드의 기능은 컬렉션 인스턴스에 저장된 인스턴스를 다음 test 메소드의 인자로
전달할때 true가 반환되는 인스턴스는 삭제하겠다는 뜻.

public interface Predicate<T>{
	boolean test(T t);
}
-----------------------------------------------------------------------
public class RemoveIfDemo {
  public static void main(String[] args) {
      List<Integer> ls1 = Arrays.asList(1, -2, 3, -4, 5);
      ls1 = new ArrayList<>(ls1);

      List<Double> ls2 = Arrays.asList(-1.1, 2.2, 3.3, -4.4, 5.5);
      ls2 = new ArrayList<>(ls2);

      Predicate<Number> p = n -> n.doubleValue() < 0.0;   //삭제의 조건
      ls1.removeIf(p);    //List<Integer> 인스턴스에 전달
      ls2.removeIf(p);    //List<Double> 인스턴스에 전달

      System.out.println(ls1);
      System.out.println(ls2);
  }
}
[1, 3, 5]
[2.2, 3.3, 5.5]

-------------------------------------------------------------------------
위 예제에서
Predicate<Number> p = n -> n.doubleValue() < 0.0;
이를 List<Integer> 인스턴스, 그리고 List<Double> 인스턴스의 removeIf 메소드에
인자로 전달을 하였다. 이것이 가능한 이유는 removeIf 메소드의 매개변수 선언이
Predicate<? super E> filter 이기 때문이다.
profile
반갑습니다

0개의 댓글