본문 바로가기
Programming/JAVA(eclipse)

java 13일차 _ 01. 제네릭스( generics ) / 컬렉션 API / 표준API함수형인터페이스

by yoon9i 2024. 3. 26.

1. 제네릭스 ( generics )

 1) 개념
  다양한 타입을 다루는 메서드 및 클래스(컬렉션)에서  
  컴파일시점(*)에 타입체크를 해서 예외를 미리 알 수 있도록 지원가능.

 2) 장점 2가지
   - 저장하는 객체의 타입 안전성 확보 ( 저장하고자 하는 데이터형을 제한 할 수 있다. ) 
   - 형변환 번거로움을 제거할 수 있다.

 3) 제네릭스 표현 ( 타입 파라미터 라고 부른다. )
  <T>: reference Type 의미
  <E>: Element 의미
  <K,V>:  Key, Value 의미
  <T,R>:  Return type 의미

 4) 특징
   - <T> 같은 제네릭은 컴파일 시점에 실제 지정된 타입으로 치환됨.
   예> <T> --> <String>
   - 타입 파라미터는 인스턴스 멤버로 간주한다.
     static 사용불가, 객체생성불가, instanceof 사용 불가
   - 클래스 및 인터페이스, 메서드 파라미터로 사용 가능.

5) 메서드 파라미터 전달시 사용되는 파라미터 타입 표현식
    - method(List<?> xxx) ==> 제네릭된 모든 데이터타입 전달 가능
    - method(List<? extends Person> xxx) ==> 제네릭된 Person 또는 Person의 자식 데이터타입만 전달 가능
    - method(List<? super Man> xxx) ==> 제네릭된 Man 또는 Man의 부모 데이터타입만 전달 가능

 

2. 컬렉션 API

 1) 데이터 저장 방법
   가. 변수

   나. 배열
     - 크기 변경 불가
     - 같은 데이터타입만 저장 가능
     - 지원되는 메서드가 없다. 길이는 배열명.length 구한다.
       나중에 추가된 API가 Arrays 유틸리티 클래스이다.
     - Arrays 클래스의 메서드
       List xx = Arrays.asList( 값, 값2 );
       Arrays.sort( 값 ); // 오름차순
       Arrays.fill( 배열, 값 );
       Arrays.copyOf( )
       Arrays.equals( 배열, 배열2 )
       ...

   다. 컬렉션 API
     - 크기 변경 가능 
     - 저장하는 데이터 타입에 제한이 없다. 
       ( 일반적으로 제네릭스 사용해서 타입을 제한해서 사용한다. )
     - 자체적으로 지원되는 메서드가 많다.
       추가된 API가 Collections 유틸리티 클래스이다.
  
 2) 컬렉션 API 종류 ( java.util 패키지 )
            Box<T>
            Collection<E> (인터페이스)                       Map<K,V> (인터페이스)
                 | (상속)                          |
  Set<E>(인터페이스)          List<E>(인터페이스)                 | (구현)
      |                                              |                       HashMap<K,V>(*)
      | (구현)                                     | ( 구현 )  
   HashSet<E>(*)                       ArrayList<E>(*)


   * 데이터 저장 방식에 따른 3가지 종류
   가. set계열: 저장되는 데이터의 순서가 없음.
                   중복저장이 안됨.(한 번만 저장됨 )

   나. list계열: 저장되는 데이터의 순서가 있음.
                   중복저장이 가능.

   다. map계열 : 데이터뿐만 아니라 데이터의 이름(키)까지 같이 저장됨.
                      ( key/value 쌍으로 저장됨 )
         저장순서가 없다.
         key 이용해서 value 얻음.

 

<List>

package exam22_컬렉션API;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ListTest {

	public static void main(String[] args) {
		// List 계열: 저장순서가 있고 중복이 가능하다.
		
		// 1. 추가 ( append 기능 )
		List<String> list = new ArrayList<>();
		list.add("홍길동1");
		list.add("홍길동2"); // 홍길동2 는 순서가 있기에 중복이가능하다.
		list.add("홍길동2");
		list.add("홍길동3");
		list.add("홍길동4");
		
		// 2. 삽입 ( insert 기능 )
		list.add(0,"이순신");
		
		// 3. 수정 ( 치환 기능 )
		list.set(1, "유관순");
		
		// 4. 삭제 ( 위치값 또는 값이용 )
		list.remove(0);
		list.remove("홍길동4");
		
		// 추가메서드
		System.out.println("리스트 길이(크기): " + list.size());
		
		Object [] arr = list.toArray();
		System.out.println("리스트를 배열로 변환: " + Arrays.toString(arr));
		
		System.out.println("특정값의 위치: " + list.indexOf("유관순"));
		System.out.println("리스트가 비어있냐: " + list.isEmpty());
		System.out.println("특정값 존재하냐: " + list.contains("유관순"));
		System.out.println("특정값 존재하냐: " + list.contains("정조"));
		System.out.println("특정값 얻기: " + list.get(0));
		
		// 전체 삭제
		list.clear();
				
		// 출력
		System.out.println(list); // list.toString()
	}

}
package exam22_컬렉션API;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListTest2 {

	public static void main(String[] args) {
		// List 계열: 저장순서가 있고 중복이 가능하다.
		
		List<String> list = new ArrayList<>();
		list.add("홍길동1");
		list.add("홍길동2"); 
		list.add("홍길동2");
		list.add("홍길동3");
		list.add("홍길동4");
				
		// 출력방법 1: toString() 이용
		System.out.println(list); // list.toString()
		System.out.println();
		
		// 출력방법 2: 반복문
		// - foreach
		for (String s : list) {
			System.out.println(s+"\t");
		}
		System.out.println();
		
		// - for
		for (int idx = 0; idx < list.size(); idx++) {
			System.out.println(list.get(idx) + "\t");
		}
		System.out.println();
		
		// 출력방법 3: Iterator 이용 ( * )
		Iterator<String> ite = list.iterator();
		while(ite.hasNext()) {
			String s= ite.next();
			System.out.println(s + "\t");
		}
		
	}// end main

}

 

<Set>

package exam22_컬렉션API;

import java.util.HashSet;
import java.util.Set;

public class SetTest {
	public static void main(String[] args) {
		// Set 계열: 저장 순서가 없고 중복 불가
		
		Set<String> set = new HashSet<>();
		set.add("홍길동1");
		set.add("홍길동2");
		set.add("홍길동2");
		set.add("홍길동3");
		set.add("홍길동4");
		
		// 추가 메서드
		System.out.println("set 길이(크기): " + set.size());
		System.out.println("set 비어있냐: " + set.isEmpty());
		System.out.println("특정값 존재하냐: " + set.contains("유관순"));
		
		// 삭제 ( 값이용 )
		set.remove("홍길동4");
		
		// 전체 삭제
		set.clear();
		
		// 값 출력: toString()
		System.out.println(set); // [홍길동4, 홍길동2, 홍길동3, 홍길동1] 
		
		
	}
}
package exam22_컬렉션API;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Cat {
	
	String name;
	int age;
	
	public Cat() {
		
	}

	public Cat(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Cat [name=" + name + ", age=" + age + "]";
	}
		
}// end class

public class Collections유틸리티 {

	public static void main(String[] args) {

		// 1. shuffle
		List<Integer> list = Arrays.asList(10,20,30,40,50,60);
		Collections.shuffle(list); // 실행할때마다 shuffle 이 됨
		System.out.println(list);
		
		// 2. copy : 길이가 같거나 대상이 소드보다 크면 copy 가능.
		List<Integer> list2 = Arrays.asList(10,20,30,40,50,60,70,80);
		List<Integer> list3 = Arrays.asList(1,2,3,4,5,6);
		
		// list3 -> list2
		Collections.copy(list2, list3); // 대상: list2, 소스:list3
		System.out.println(list2);
		System.out.println(list3);
		
		// 3. 정렬 ( * )
		List<Cat> list4 = Arrays.asList(
				new Cat("c1", 4), 
				new Cat("c2", 2), 
				new Cat("c3", 1), 
				new Cat("c4", 8), 
				new Cat("c5", 3)
				);
		
		System.out.println(list4);
		
		// Comparator 사용법
		// 1. 익명클래스
		System.out.println("---------익명클래스--------");
		Comparator<Cat> comp = new Comparator<Cat>() {

			@Override
			public int compare(Cat c1, Cat c2) {
				int result = c1.age - c2.age; // -> 오름차순
				int result2 = c2.age - c1.age; // -> 내림차순
				// result  0 이면 c1 과 c2 의 age 가 같다
				// result 음수 이면 c1.age 보다 c2.age 의 age 가 크다.
				// result 양수 이면 c1.age 가 c2.age 보다 크다.
				
				return result;  
//				return result2;
			}
			
		};// Comparator end
		
		Collections.sort(list4, comp);
		System.out.println(list4);
		System.out.println("-----------------------");
		
		
		// 2. 람다
		System.out.println("---------람다--------");
		Comparator<Cat> comp2 = (c1, c2) -> c1.age - c2.age;
		Collections.sort(list4, comp2);
		System.out.println(list4);
		System.out.println("-----------------------");
		
		// ( * )
		System.out.println("----------사용빈도높음---------");
		Collections.sort(list4, (c1, c2) -> c2.age - c1.age);
		System.out.println(list4);
		
		
		

		
	}

}

 

3) Collections 유틸리티 API
- 컬렉션 정렬

Collections.sort( 리스트, Comparator 타입 );
* Comparator 는 인터페이스로서 정렬할 변수 무엇인지
지정해야 될 의무가 있다.
Comparator 내의 Compare( T t1, T t2 ) 메서드를
재정의해서 정렬할 변수를 구현한다.

구현방법1: 익명클래스

Comparator<Cat> comp = new Comparator<Cat>() {

@Override
public int compare(Cat c1, Cat c2) {
int result = c1.age - c2.age; // -> 오름차순
int result2 = c2.age - c1.age; // -> 내림차순
// result  0 이면 c1 과 c2 의 age 가 같다
// result 음수 이면 c1.age 보다 c2.age 의 age 가 크다.
// result 양수 이면 c1.age 가 c2.age 보다 크다.

return result;  
// return result2;
}

};// Comparator end

Collections.sort(list4, comp);
System.out.println(list4);


구현방법2: 람다
Comparator<Cat> comp2 = (c1, c2) -> c1.age - c2.age;
Collections.sort(list4, comp2);
System.out.println(list4);

 

< Collections 유틸리티 API>

package exam22_컬렉션API;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Cat {
	
	String name;
	int age;
	
	public Cat() {
		
	}

	public Cat(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Cat [name=" + name + ", age=" + age + "]";
	}
		
}// end class

public class Collections유틸리티 {

	public static void main(String[] args) {

		// 1. shuffle
		List<Integer> list = Arrays.asList(10,20,30,40,50,60);
		Collections.shuffle(list); // 실행할때마다 shuffle 이 됨
		System.out.println(list);
		
		// 2. copy : 길이가 같거나 대상이 소드보다 크면 copy 가능.
		List<Integer> list2 = Arrays.asList(10,20,30,40,50,60,70,80);
		List<Integer> list3 = Arrays.asList(1,2,3,4,5,6);
		
		// list3 -> list2
		Collections.copy(list2, list3); // 대상: list2, 소스:list3
		System.out.println(list2);
		System.out.println(list3);
		
		// 3. 정렬 ( * )
		List<Cat> list4 = Arrays.asList(
				new Cat("c1", 4), 
				new Cat("c2", 2), 
				new Cat("c3", 1), 
				new Cat("c4", 8), 
				new Cat("c5", 3)
				);
		
		System.out.println(list4);
		
		// Comparator 사용법
		// 1. 익명클래스
		System.out.println("---------익명클래스--------");
		Comparator<Cat> comp = new Comparator<Cat>() {

			@Override
			public int compare(Cat c1, Cat c2) {
				int result = c1.age - c2.age; // -> 오름차순
				int result2 = c2.age - c1.age; // -> 내림차순
				// result  0 이면 c1 과 c2 의 age 가 같다
				// result 음수 이면 c1.age 보다 c2.age 의 age 가 크다.
				// result 양수 이면 c1.age 가 c2.age 보다 크다.
				
				return result;  
//				return result2;
			}
			
		};// Comparator end
		
		Collections.sort(list4, comp);
		System.out.println(list4);
		System.out.println("-----------------------");
		
		
		// 2. 람다
		System.out.println("---------람다--------");
		Comparator<Cat> comp2 = (c1, c2) -> c1.age - c2.age;
		Collections.sort(list4, comp2);
		System.out.println(list4);
		System.out.println("-----------------------");
		
		// ( * )
		System.out.println("----------사용빈도높음---------");
		Collections.sort(list4, (c1, c2) -> c2.age - c1.age);
		System.out.println(list4);
		
		
		

		
	}

}

 

 

3. 표준 API 함수적 인터페이스
1) 개념
- 메서드가 파라미터 및 리턴값의 존재여부에 따른 4가지 형태가 존재한다.
* 4가지 표현식
> 파라미터 x 리턴값 x
ex) public void method( );

> 파라미터 x 리턴값 o
ex) 
public int method( );
public String method( );

> 파라미터 o 리턴값 x
ex) 
public void method( int );
public void method( String );
public void method( int, String );

> 파라미터 o 리턴값 o
ex) 
public int method( int );
public String method( String );
public int method( int, String );

==> 위 4 가지 형식의 메서드를 가진 인터페이스를 API 로 제공한다.
       따라서 위 기능이 필요할 때 직접 만들지말고 API 로 제공된
      표준적 API 함수적 인터페이스를 사용하자.

 

2) java.util.function 패키지
=> @FunctionalInterface 지정. 따라서 추상메서드는 반드시 한개
     존재함( 람다 표현식 사용 가능 )
가. Consumer
- 추상메서드가 파라미터있고 리턴값은 없음.
- void accept​(T t)

* BiConsumer<T,​U>: void accept​(T t, U u)
DoubleConsumer : void accept​(double value)
IntConsumer: void accept​(int value)
LongConsumer : void accept​(long value)
ObjDoubleConsumer<T>: void accept​(T t, double value)
ObjIntConsumer<T> : void accept​(T t, int value)
ObjLongConsumer<T>: void accept​(T t, long value)

 

 

<Consumer>

package exam23_표준API함수형인터페이스;

import java.util.Date;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.ObjIntConsumer;

/*
 가. Consumer
        - 추상메서드가 파라미터있고 리턴값은 없음.
	- void	accept​(T t)

       * BiConsumer<T,​U>: void	accept​(T t, U u)
         DoubleConsumer : void	accept​(double value)
         IntConsumer:     void	accept​(int value)
	 	 LongConsumer   : void	accept​(long value)
	     ObjDoubleConsumer<T>: void accept​(T t, double value)
	     ObjIntConsumer<T> : void	accept​(T t, int value)
	     ObjLongConsumer<T>: void	accept​(T t, long value)
 */
public class Functional01_Consumer {

	public static void main(String[] args) {

		// Consumer 익명클래스
		Consumer<String> c = new Consumer<String>() {
			@Override
			public void accept(String t) {
				System.out.println("Consumer: " + t);
			}
		};
		c.accept("hello");
		
		//Consumer 람다 표현식
		Consumer<String> c2 = t-> System.out.println("람다 Consumer: " + t);
		c2.accept("hello");
		
		
		//BiConsumer  익명클래스
		BiConsumer<String, Integer> bc = new BiConsumer<String, Integer>() {
			@Override
			public void accept(String t, Integer u) {
				System.out.println("BiConsumer: " + t +"\t" + u);
			}
		};
		bc.accept("홍길동", 20);

       // BiConsumer 람다
		BiConsumer<String, Integer> bc2 = (x, x2)->System.out.println("BiConsumer: " + x +"\t" + x2);
		bc2.accept("홍길동", 20);
		
		// ObjIntConsumer<T> : void	accept​(T t, int value)
		ObjIntConsumer<Date> oit = (x, x2)->System.out.println("ObjIntConsumer: " + x +"\t" + x2);
		oit.accept(new Date(), 100);
		
	}//end main

}

 

나. Supplier
- 추상메서드가 파라미터 없고 리턴값이 있음.
- T  get( )

* BooleanSupplier: boolean getAsBoolean( )
  DoubleSupplier: double getAsDouble( )
  IntSupplier: int getAsInt( )
  LongSupplier: long getAsLong( )

 

<Supplier>

package exam23_표준API함수형인터페이스;

import java.util.function.IntSupplier;
import java.util.function.Supplier;

/*
* 나. Supplier
- 추상메서드가 파라미터 없고 리턴값이 있음.
- T  get( )

* BooleanSupplier: boolean getAsBoolean( )
  DoubleSupplier: double getAsDouble( )
  IntSupplier: int getAsInt( )
  LongSupplier: long getAsLong( )
 */


public class Functional02_Supplier {
	public static void main(String[] args) {
		
		// Supplier 익명클래스
		Supplier<String> s = new Supplier<String>() {
			@Override
			public String get() {
				return "hello";
			}
		};
		 System.out.println(s.get());
		 
		 // Supplier 람다
		 Supplier<String> s2 = () -> "hello";
		 System.out.println(s2.get());
		 
		 //------------------------------------------------
		 
		 // IntSupplier: int getAsInt()
		 IntSupplier is = () -> 100;
		 System.out.println(is.getAsInt());
		
		
	}// end main
}

 

다. Function<T,​R>
- 추상메서드가 파라미터 있고 리턴값은 있음.
- R apply​(T t)

* BiFunction<T,​U,​R> : R apply​(T t, U u)
DoubleFunction<R> : R apply​(double value)
DoubleToIntFunction: int applyAsInt​(double value)
DoubleToLongFunction : long applyAsLong​(double value)
IntFunction<R> : R apply​(int value)
IntToDoubleFunction : double applyAsDouble​(int value)
IntToLongFunction: long applyAsLong​(int value)
LongFunction<R>: R apply​(long value)
LongToDoubleFunction : double applyAsDouble​(long value)
LongToIntFunction : int applyAsInt​(long value)
ToDoubleBiFunction<T,​U>: double applyAsDouble​(T t, U u)

ToIntFunction<T> : int applyAsInt(T value)

...

 

<Function>

package exam23_표준API함수형인터페이스;

import java.util.function.BiFunction;
import java.util.function.Function;

/*
 * 
 * 다. Function<T,​R>
- 추상메서드가 파라미터 있고 리턴값은 있음.
- R apply​(T t)

* BiFunction<T,​U,​R> : R apply​(T t, U u)
DoubleFunction<R> : R apply​(double value)
DoubleToIntFunction: int applyAsInt​(double value)
DoubleToLongFunction : long applyAsLong​(double value)
IntFunction<R> : R apply​(int value)
IntToDoubleFunction : double applyAsDouble​(int value)
IntToLongFunction: long applyAsLong​(int value)
LongFunction<R>: R apply​(long value)
LongToDoubleFunction : double applyAsDouble​(long value)
LongToIntFunction : int applyAsInt​(long value)
ToDoubleBiFunction<T,​U>: double applyAsDouble​(T t, U u)
	......
 */

public class Functional03_Function {

	public static void main(String[] args) {

		// Function<T, R> : R apply ( T t )
		// Function 익명클래스
		Function<String, Integer> f = new Function<String, Integer>() {
			@Override
			public Integer apply(String t) {
				return t.length();
			}
		};
		System.out.println("문자열 길이: " + f.apply("hello"));
		
		// Function 람다표현식
		Function<String, Integer> f2 = t -> t.length();
		System.out.println("람다 문자열 길이: " + f2.apply("hello"));
		
		//-----------------------------------------
		// 파라미터 2개 리턴 1개
		// BiFunction<파라미터, 파라미터, 리턴>
		// BiFunction<T,​U,​R> : R apply​(T t, U u)
		BiFunction<String, String, Integer> bi = (t, u) ->  (t+u).length();
		System.out.println("BiFunction 문자열 길이: " + bi.apply("hello", "world")); // -> helloworld 의 길이
		
		
	}// end main

}

 

- Function 을 이용한 예시

package exam23_표준API함수형인터페이스;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.ToIntFunction;

class Student {
	
	String name;
	int kor; // 국어점수
	int eng; // 영어점수
	
	public Student() {}

	public Student(String name, int kor, int eng) {
		this.name = name;
		this.kor = kor;
		this.eng = eng;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getKor() {
		return kor;
	}

	public void setKor(int kor) {
		this.kor = kor;
	}

	public int getEng() {
		return eng;
	}

	public void setEng(int eng) {
		this.eng = eng;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", kor=" + kor + ", eng=" + eng + "]";
	}
	
	
}// end Student class

public class Functional03_Function2_sample {
	
	// 이름만 출력하는 메서드
	public static void printName(List<Student> list, Function<Student, String> x) {
		for (Student stu : list) {
			System.out.println(x.apply(stu));
		}
	}
	
	// Kor 출력하는 메서드
	public static void printKor(List<Student> list, ToIntFunction<Student> f) {
		for (Student stu : list) {
			System.out.println(f.applyAsInt(stu));
		}
	}

	public static void main(String[] args) {

		List<Student> list = new ArrayList<>();
		list.add(new Student("홍길동", 100, 80));
		list.add(new Student("이순신", 89, 90));
		list.add(new Student("유관순", 99, 99));
		
//		// 이름만 출력하시오.
//		Function<Student, String> x = new Function<Student, String>() {
//			@Override
//			public String apply(Student t) {
//				return t.getName();
//			}
//		};
//		
//		printName(list, x);
		
		// name 출력하는 메서드
		printName(list, t -> t.getName());
		// kor 출력하는 메서드
		printKor(list, t -> t.getKor());
		
	}// end main

}// end class

 

라. Operator
- Function 처럼 파라미터 있고 리턴값은 있음.
전달되는 파라미터 타입하고 리턴값의 타입이 동일함.
- Function API 를 상속받음.
  특징은 전달되는 파라미터 타입하고 리턴값의 타입이 동일함.

* BinaryOperator<T> : BiFunction의 하위 인터페이스이고
T apply(T t1, T t2)

DoubleBinaryOperator: double applyAsDouble​(double left, double right)
DoubleUnaryOperator: double applyAsDouble​(double operand)
IntBinaryOperator : int applyAsInt​(int left, int right)
IntUnaryOperator : int applyAsInt​(int operand)
LongBinaryOperator: long applyAsLong​(long left, long right)
LongUnaryOperator : long applyAsLong​(long operand)
UnaryOperator<T>: T apply(T t)

 

<Operator>

package exam23_표준API함수형인터페이스;

import java.util.function.BinaryOperator;
import java.util.function.LongUnaryOperator;

/*
 * 
 라. Operator
- Function 처럼 파라미터 있고 리턴값은 있음.
  전달되는 파라미터 타입하고 리턴값의 타입이 동일함.
- Function API 를 상속받음.
  특징은 전달되는 파라미터 타입하고 리턴값의 타입이 동일함.

* BinaryOperator<T> : BiFunction의 하위 인터페이스이고
T apply(T t1, T t2)

DoubleBinaryOperator: double applyAsDouble​(double left, double right)
DoubleUnaryOperator: double applyAsDouble​(double operand)
IntBinaryOperator : int applyAsInt​(int left, int right)
IntUnaryOperator : int applyAsInt​(int operand)
LongBinaryOperator: long applyAsLong​(long left, long right)
LongUnaryOperator : long applyAsLong​(long operand)
UnaryOperator<T>: T apply(T t)
 */

public class Functional04_Operator {
	public static void main(String[] args) {
		
		// BinaryOperator<T> 클래스
		BinaryOperator<Integer> x = new BinaryOperator<Integer>() {			
			@Override
			public Integer apply(Integer t, Integer u) {
				return t+u;
			}
		};
		
		System.out.println(x.apply(10, 20));
		
		// BinaryOperator<T> 람다 표현식
		BinaryOperator<Integer> x2 = (n, n2) -> n+n2;
		System.out.println(x2.apply(10, 20));
		
		//----------------------------------------------------------
		
		// LongUnaryOperator : long applyAsLong​(long operand)
		LongUnaryOperator y = n -> n+100;
		System.out.println(y.applyAsLong(10));
		
	}// end main
}

 

마. Predicate<T>
- 추상메서드가 파라미터 있고 리턴값은 있음.
리턴값은 boolean 값으로 제한됨.
- 조건체크 용도
  논리연산자의 역할의 메서드 제공
  && : and( )
  || : or( )
  ! : negate( )
 
- boolean test​(T t)

* BiPredicate<T,​U> : boolean test​(T t, U u)
DoublePredicate : boolean test​(double value)
IntPredicate : boolean test​(int value)
LongPredicate : boolean test​(long value)

 

<Predicate>

package exam23_표준API함수형인터페이스;

import java.util.function.IntPredicate;
import java.util.function.Predicate;

/*
 * 
 마. Predicate<T>
- 추상메서드가 파라미터 있고 리턴값은 있음.
리턴값은 boolean 값으로 제한됨.
- 조건체크 용도
- boolean test​(T t)

* BiPredicate<T,​U> : boolean test​(T t, U u)
DoublePredicate : boolean test​(double value)
IntPredicate : boolean test​(int value)
LongPredicate : boolean test​(long value)
 */

public class Functional05_Predicate {

	public static void main(String[] args) {

		// Predicate 익명클래스
		Predicate<String> x = new Predicate<String>() {
			@Override
			public boolean test(String t) {
				return t.length() >= 3;
			}
		};
		
		System.out.println(x.test("홍길동"));
		System.out.println(x.test("정조"));
		
		// Predicate 람다 표현식
		Predicate<String> x2 = t -> t.length() >= 3;
		System.out.println(x2.test("홍길동"));
		
		//---------------------------------------------
		// IntPredicate : boolean test​(int value)
		
		IntPredicate y = n -> (n % 2 == 0);
		System.out.println(y.test(10));
		System.out.println(y.test(11));
		
		
	}// end main

}

 

- Predicate 논리메서드

package exam23_표준API함수형인터페이스;

import java.util.function.IntPredicate;

/*
 * 
 마. Predicate<T>
- 추상메서드가 파라미터 있고 리턴값은 있음.
리턴값은 boolean 값으로 제한됨.
- 조건체크 용도
  논리연산자의 역할의 메서드 제공
  && : and( )
  || : or( )
  ! : negate( )
- boolean test​(T t)

* BiPredicate<T,​U> : boolean test​(T t, U u)
DoublePredicate : boolean test​(double value)
IntPredicate : boolean test​(int value)
LongPredicate : boolean test​(long value)
 */

public class Functional05_Predicate2_논리메서드 {

	public static void main(String[] args) {
		
		IntPredicate y = n -> (n % 2 == 0); // 2의 배수
		IntPredicate y2 = n -> (n % 3 == 0); // 3의 배수
		
		// 1. 2의 배수이면서 3의 배수냐?
		IntPredicate y3 = y.and(y2);
		System.out.println(y3.test(6)); // true
		System.out.println(y3.test(8)); // false
		
		// 2. 2의 배수이거나 3의 배수냐?
		IntPredicate y4 = y.or(y2);
		System.out.println(y4.test(7)); // false
		System.out.println(y4.test(8)); // true
		
		// 3. 부정(true->false, false->true)
		IntPredicate y5 = y.negate(); // 2의 배수를 부정
		System.out.println(y5.test(7)); // true
		System.out.println(y5.test(8)); // false
		
		
	}// end main

}

 

3) Consumer, Function 같은 인터페이스는 여러 개 인터페이스를 순차적으로 설정
       - andThen()
      
      예>
       // 1. Consumer 순차적인 작업
Consumer<String> c = t-> System.out.println("람다 Consumer1: " + t);
Consumer<String> c2 = t-> System.out.println("람다 Consumer2: " + t);

Consumer<String> c3 = c.andThen(c2);
c3.accept("hello");

//2. Function
Function<String, Integer> f =  t->t.length();
Function<Integer, Float> f2 =  t->t + 3.14F;

Function<String, Float> f3 =    f.andThen(f2);
System.out.println(f3.apply("hello"));

 

<andThen>

package exam23_표준API함수형인터페이스;

import java.util.function.Consumer;
import java.util.function.Function;

public class Functional06_andThen {

	public static void main(String[] args) {
		
		// 1. Consumer 순차적인 작업
		Consumer<String> c = t-> System.out.println("람다 Consumer 1: " + t);
		Consumer<String> c2 = t-> System.out.println("람다 Consumer 2: " + t);
		
		Consumer<String> c3 = c.andThen(c2);
		c3.accept("hello");
		/*
		 * >>>
		 
		 * 람다 Consumer 1: hello
		   람다 Consumer 2: hello
		 */
		
		
		// 2. Function
		// String -> String.length -> Integer(f 리턴) -> Integer(f2 파라미터) -> Float -> Float + 3.14F
		// * f 리턴값과 f2 파라미터 타입이 일치해야한다.
		Function<String, Integer> f = t -> t.length();
		Function<Integer, Float> f2 = t -> t + 3.14F;
		
		Function<String,Float> f3 = f.andThen(f2);
		System.out.println(f3.apply("hello")); // 8.14
		
	}// end main

}