한 개의 추상메소드를 가지는 인터페이스들은 모두 람다식 사용 가능
예: Runnable 인터페이스
public class RunnableExample {
public static void main(String[] args) {
// how1
Runnable runnable = () ->{
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
};
Thread thread = new Thread(runnable);
thread.start();
//how2
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
});
thread2.start();
}
}
자바 8부터 표준 API로 제공되는 함수적 인터페이스
java.util.function 패키지에 포함되어 있다.
매개타입으로 사용되어 람다식을 매개값으로 대입할 수 있도록 해준다.
종류
Consumer 함수적 인터페이스류 : 데이터를 소비
Supplier 함수적 인터페이스류 : 데이터를 공급
Function 함수적 인터페이스류 : A를 B로 변환
Operator 함수적 인터페이스류 : 데이터를 연산
Predicate 함수적 인터페이스류 : 매개 값을 조사해서 true & false 리턴
Consumer 함수적 인터페이스
Consumer인터페이스와 추상메소드 참고 --> https://docs.oracle.com/javase/8/docs/api/java/util/function/package-frame.html
Exam
import java.util.function.*;
public class ConsumerExample {
public static void main(String[] args) {
Consumer<String> consumer =
s -> System.out.println("s + \"8\" = " + s + "8");
consumer.accept("JAVA");
BiConsumer<String, String> biConsumer =
(s, s2) -> System.out.println("s + s2 = " + s + s2);
biConsumer.accept("Java","8");
DoubleConsumer doubleConsumer =
value -> System.out.println("Java" + value);
doubleConsumer.accept(7.0);
ObjIntConsumer<String> objIntConsumer =
(s, value) -> System.out.println("s + value = " + s + value);
objIntConsumer.accept("JAVA", 8);
}
}
Supplier 함수적 인터페이스
Supplier 함수적 인터페이스 특징 : 매개변수가 없고, 리턴값이 있는 getXXX() 메소드를 가지고 있다.
이들 메소드는 실행 후 호출한 곳으로 데이터를 리턴(공급)하는 역할을 한다.
Supplier 인터페이스와 추상메소드 참고 --> https://docs.oracle.com/javase/8/docs/api/java/util/function/package-frame.html
Exam
import java.util.function.IntSupplier;
public class SupplierExample {
public static void main(String[] args) {
IntSupplier intSupplier = () -> {
int num = (int) (Math.random() * 6) + 1;
return num;
};
System.out.println("주사위 1~6중의 수: = " + intSupplier.getAsInt());
System.out.println("주사위 1~6중의 수: = " + intSupplier.getAsInt());
System.out.println("주사위 1~6중의 수: = " + intSupplier.getAsInt());
//외에 DoubleSupplier, BooleanSupplier, LongSupplier 등등이 있다.
}
}
Function 함수적 인터페이스
Exam
public class Student {
private String name;
private int englishScore;
private int mathScore;
public Student(String name, int englishScore, int mathScore) {
this.name = name;
this.englishScore = englishScore;
this.mathScore = mathScore;
}
public String getName() {
return name;
}
public int getEnglishScore() {
return englishScore;
}
public int getMathScore() {
return mathScore;
}
}
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.ToIntFunction;
public class FunctionExample1 {
//두개의 Student를 가진 리스트 생성
private static List<Student> list = Arrays.asList(
new Student("홍길동", 90, 96),
new Student("김나박", 95, 93)
);
public static void printString(Function<Student,String > function) {
for (Student student : list) {
System.out.print(function.apply(student) + " ");
}
System.out.println();
}
public static void printInt(ToIntFunction<Student> function) {
for (Student student : list) {
System.out.print(function.applyAsInt(student) + " ");
}
System.out.println();
}
public static void main(String[] args) {
System.out.println("[학생 이름]");
printString(t -> t.getName());
System.out.println("[영어 점수]");
printInt( t -> t.getEnglishScore());
System.out.println("[수학 점수]");
printInt( t -> t.getMathScore());
}
}
Exam2
import java.util.Arrays;
import java.util.List;
import java.util.function.ToIntFunction;
public class FunctionExample2 {
//두개의 Student를 가진 리스트 생성
private static List<Student> list = Arrays.asList(
new Student("홍길동", 90, 96),
new Student("김나박", 95, 93)
);
//평균을 구하는..
public static double avg(ToIntFunction<Student> function) {
int sum = 0;
for (Student student : list) {
sum += function.applyAsInt(student);
}
double avg = (double)sum / list.size();
return avg;
}
public static void main(String[] args) {
double englishAvg = avg(t -> t.getEnglishScore());
System.out.println("영어 평균 점수= " + englishAvg);
double mathAvg = avg(t -> t.getMathScore());
System.out.println("수학 평균 점수 = " + mathAvg);
}
}
Operator 함수적 인터페이스
Operator 인터페이스와 추상메소드 참고 --> https://docs.oracle.com/javase/8/docs/api/java/util/function/package-frame.html
Exam
import java.util.function.IntBinaryOperator;
public class OperatorExample {
private static int[] scores = {92, 95, 87};
public static int maxOrMin(IntBinaryOperator operator) {
int result = scores[0];
for (int score : scores) {
result = operator.applyAsInt(result, score);
}
return result;
}
public static void main(String[] args) {
//쵀대값
int max = maxOrMin(
(a, b) -> {
if (a >= b) return a;
else return b;
}
);
System.out.println("최대값: " + max);
//최소값
int min = maxOrMin(
(a, b) -> {
if (a <= b) return a;
else return b;
}
);
System.out.println("최소값: " + min);
}
}
Predicate 함수적 인터페이스
Predicate 인터페이스와 추상메소드 참고 --> https://docs.oracle.com/javase/8/docs/api/java/util/function/package-frame.html
Exam
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class PredicateExample {
private static List<Student> list = Arrays.asList(
new Student("홍길동", "남자", 90),
new Student("김나박", "여자", 90),
new Student("김범수", "남자", 95),
new Student("박정현", "여자", 92)
);
public static double avg(Predicate<Student> predicate) {
int count = 0;
int sum = 0;
for (Student student : list) {
if (predicate.test(student)) {
count++;
sum += student.getScore();
}
}
return (double)sum / count;
}
public static void main(String[] args) {
//남자 평균 점수
double maleAvg = avg(t -> t.getSex().equals("남자"));
System.out.println("남자 평균 점수 : " + maleAvg);
//여자 평균 점수
double femaleAvg = avg(t -> t.getSex().equals("여자"));
System.out.println("여자 평균 점수 : " + femaleAvg);
}
}
andThen()과 compose() 디폴트 메소드
함수적 인터페이스가 가지고 있는 디폴트 메소드이다.
두 개의 함수적 인터페이스를 순차적으로 연결해서 실행한다.
첫번째 리턴값을 두번째 매개값으로 제공해서 최종 결과값 리턴
andThen()과 compose()의 차이점은 어떤 함수적 인터페이스부터 처리하느냐이다.
andThen() 디폴트 메소드
compose() 디폴트 메소드
최종결과 <--- 인터페이스A(람다식) <--- 인터페이스B(람다식) <--- 인터페이스AB method()
Consumer의 순차적 연결
exam
public class Member {
private String name;
private String id;
private Address address;
public Member(String name, String id, Address address) {
this.name = name;
this.id = id;
this.address = address;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
public Address getAddress() {
return address;
}
}
public class Address {
private String country;
private String city;
public Address(String country, String city) {
this.country = country;
this.city = city;
}
public String getCountry() {
return country;
}
public String getCity() {
return city;
}
}
import java.util.function.Consumer;
public class ConsumerAndThenExample {
public static void main(String[] args) {
Consumer<Member> consumerA = m -> {
System.out.println("consumerA: " + m.getName());
};
Consumer<Member> consumerB = m -> {
System.out.println("consumerB: " + m.getId());
};
Consumer<Member> consumerAB = consumerA.andThen(consumerB);
consumerAB.accept(new Member("홍길동", "IdHong", null));
// 실행 결과
// consumerA: 홍길동
// consumerB: IdHong
Consumer<Member> consumerAC = consumerB.andThen(consumerA);
consumerAC.accept(new Member("홍길동", "IdHong", null));
// 실행 결과
// consumerB: IdHong
// consumerA: 홍길동
}
}
Function의 순차적 연결
Exam
import java.util.function.Function;
public class FunctionAndThenComposeExample {
public static void main(String[] args) {
Function<Member, Address> functionA;
Function<Address, String> functionB;
Function<Member, String> functionAB;
functionA = m -> m.getAddress();
functionB = a -> a.getCity();
functionAB = functionA.andThen(functionB);
String city =
functionAB.apply(new Member("홍길동", "IdHong", new Address("한국", "서울")));
System.out.println("거주도시 = " + city);
// 실행 결과
// 거주도시 = 서울
functionAB = functionB.compose(functionA);
city = functionAB.apply(new Member("홍길동", "IdHong", new Address("한국", "서울")));
System.out.println("거주도시 = " + city);
// 실행 결과
// 거주도시 = 서울
}
}
and() , or(), negate() 디폴드 메소드와 isEqual() 정적 메소드
and(), or(), negate() 디폴트메소드
Exam
import java.util.function.IntPredicate;
public class PredicateAndOrNegateExample {
public static void main(String[] args) {
//2의 배수를 검사
IntPredicate predicateA = a -> { return (a % 2 == 0); };
//3의 배수를 검사
IntPredicate predicateB = a ->{ return (a % 3 == 0);};
IntPredicate predicateAB;
boolean result;
//and()
predicateAB = predicateA.and(predicateB);
result = predicateAB.test(9);
System.out.println("9는 2와 3의 배수입니까? " + result);
//or()
predicateAB = predicateA.or(predicateB);
result = predicateAB.test(9);
System.out.println("9는 2와 3의 배수입니까? " + result);
//negate
predicateAB = predicateA.negate();
result = predicateAB.test(9);
System.out.println("9는 false 입니까? " + result);
}
}
isEqual() 정적 메소드
Exam
import java.util.function.Predicate;
public class PredicateIsEqualExample {
public static void main(String[] args) {
Predicate<String > predicate;
predicate = Predicate.isEqual(null);
System.out.println("null, null: " + predicate.test(null));
//null과 null은 true
predicate = Predicate.isEqual("Java8");
System.out.println("null, Java8: " + predicate.test(null));
//false
predicate = Predicate.isEqual("Java8");
System.out.println("null, Java8: " + predicate.test(null));
//false
predicate = Predicate.isEqual("null");
System.out.println("null, Java8: " + predicate.test("Java8"));
//false
predicate = Predicate.isEqual("Java8");
System.out.println("Java8, Java8: " + predicate.test("Java8"));
//true
}
}
minBy(), maxBy 정적 메소드
BinaryOperator<T> 함수적 인터페이스의 정적 메소드
Comparator를 이용해서 최대 T와 최소 T를 얻는 BinaryOperator<T>를 리턴한다.
리턴타입 |
정적 메소드 |
BinaryOperator<T> |
minBy(Compareator<? super T> comparator) |
BinaryOperator<T> |
maxBy(Compareator<? super T> comparator) |
Comparator<T> 는 다음과 같이 선언된 함수적 인터페이스이다.
o1과 o2를 비교해서 o1이 작으면 음수를,
o1 과 o2를 비교해서 동일하면 0,
o1이 크면 양수를 리턴해야하는 compara() 메소드가 선언되어 있다.
@functionalInterface
public interface Comparator<T> {
public int compare(T o1, T o2);
}
Comparator<T>를 타겟 타입으로하는 람다식은 다음과 같이 작성할 수 있다.
(o1, o2) -> { ...; return int 값 ;}
만약 o1 와 o2가 int 타입이라면 다음과 같이 Integer.compare(int, int) 메소드를 이용 할 수 있다.
(o1, o2) -> Integer.compare(o1, o2);
Exam
public class Fruit {
public String name;
public int price;
public Fruit(String name, int price) {
this.name = name;
this.price = price;
}
}
import java.util.function.BinaryOperator;
public class OperatorMinByMaxByExample {
public static void main(String[] args) {
BinaryOperator<Fruit> binaryOperator;
Fruit fruit;
binaryOperator = BinaryOperator.minBy((f1, f2) -> Integer.compare(f1.price, f2.price));
fruit = binaryOperator.apply(new Fruit("딸기", 6000), new Fruit("수박", 10000));
System.out.println("fruit.name = " + fruit.name);
// fruit.name = 딸기
binaryOperator = BinaryOperator.maxBy((f1, f2) -> Integer.compare(f1.price, f2.price));
fruit = binaryOperator.apply(new Fruit("딸기", 6000), new Fruit("수박", 10000));
System.out.println("fruit.name = " + fruit.name);
// fruit.name = 수박
}
}
'JAVA > JAVA' 카테고리의 다른 글
자바 컬렉션) Map 컬렉션 (0) | 2018.06.14 |
---|---|
자바 컬렉션) Set 컬렉션 (0) | 2018.06.14 |
람다식 ) 클래스 멤버와 로컬 변수 사용 (0) | 2018.06.10 |
람다식 타겟 타입과 함수적 인터페이스 (0) | 2018.06.09 |
람다식 기본 문법 (0) | 2018.06.09 |