import java.util.*;
import java.text.*;
import java.util.function.*;
public class SupplierDemo {
public static void main(String[] args) {
// get 구현 (return apple;)
Supplier<String> s1 = () -> "apple";
System.out.println(s1.get());
int[]x = {0};
// getAsInt 구현, 배열방에 1 증가하는 것으로 구현
IntSupplier s2 = () -> x[0]++;
for(int i=0;i<3;i++)
System.out.println(s2.getAsInt());
DoubleSupplier s3 = () -> Math.random() * 10;
System.out.println(s3.getAsDouble());
SimpleDateFormat format = new SimpleDateFormat("MM월 dd일 (E요일) a hh:mm:ss)");
// 구현 get return format 씌워서 리턴
Supplier<String> s4 = () -> format.format(new Date());
System.out.println(s4.get());
}
}
Function 인터페이스 유형
종류
매개 값
반환 값
메소드
의미
Function
있음
있음
apply()
매개 값을 반환 값으로 매핑한다.
apply() : 매개 값을 타입 변환하는 추상 메소드
applyAsInt() : 결과를 정수로 반환 / applyAsDouble() : 결과를 실수로 반환
종류가 여러 개(Bi, Double, IntToDouble,ToDoubleBi 등)
포함하는 메소드 종류 (위의 종류에 따라 안 가지고 있을 수도 있음)
순방향 연결 디폴트 메소드 andThen()
역방향 연결 디폴트 메소드 compose()
정적 메소드 identity()
// 정의
Function<T,R> f = t -> {T타입 t객체를 사용하여 R타입 객체를 반환하는 실행문;}
Function<Integer, Integer> add2 = x -> x+2; // 정수형을 인자로 받아서, 2를 더한 후 정수형을 리턴하는 Function 메소드.
// 사용
참조변수.apply(매개변수);
add2.apply(3); // 정수 3을 인자로 받아서 2를 더하고 5를 반환하는 Function 메소드 사용
---------------------------------------------
두 개 이상일 때
//순방향 연결
add2.andThen(mul2).apply(3); // add2 먼저 연산 후, mul2 연산
//역방향 연결
add2.compose(mul2).apply(3); // mul2 먼저 연산 후, add2 연산
// Car 클래스 파일
import java.util.*;
public class Car {
private String model;
private boolean gasoline;
private int age;
private int mileage;
public Car(String model, boolean gasoline, int age, int mileage) {
this.model = model;
this.gasoline = gasoline;
this.age = age;
this.mileage = mileage;
}
public String getModel() { return model; }
public boolean isGasoline() { return gasoline; }
public int getAge() { return age; }
public int getMileage() { return mileage; }
public String toString() {
return String.format("Car(%s,%s,%d,%d)", model, gasoline, age, mileage);
}
public static final List<Car> cars = Arrays.asList(
new Car("소나타", true, 18, 210000),
new Car("코란도", false, 15, 200000),
new Car("그랜저", true, 12, 150000),
new Car("싼타페", false, 10, 220000),
new Car("아반테", true, 10, 70000),
new Car("에쿠스", true, 6, 100000),
new Car("그랜저", true, 5, 80000),
new Car("소나타", true, 2, 35000),
new Car("쏘렌토", false, 1, 10000),
new Car("아반테", true, 1, 7000)
);
}
//Function 인터페이스 유형 파일
import java.util.*;
import java.util.function.*;
import sec02.Car;
public class Function2Demo {
public static void main(String[] args) {
//Return 타입은 String 들어가는 인자는 Car
//Car c는 모델 리턴
Function<Car, String> f1 = c -> c.getModel();
ToIntFunction<Car> f2 = c -> c.getAge();
for (Car car : Car.cars)
System.out.println("("+f1.apply(car)+", "+f2.applyAsInt(car)+") ");
System.out.println();
double averageAge = average(Car.cars, c -> c.getAge()); // (1)
double averageMileage = average(Car.cars, c -> c.getMileage()); // (2)
System.out.println("평균 연식 = "+averageAge);
System.out.println("평균 주행거리 = "+averageMileage);
}
//(1) List<Car> cars = Car.cars이고 ToTintFunction<Car> f = c -> c.getAge()
//(2) List<Car> cars = Car.cars이고 ToTintFunction<Car> f = c -> c.getMileage()
static public double average(List<Car> cars, ToIntFunction<Car> f) {
double sum = 0.0;
for(Car car:cars)
sum+=f.applyAsInt(car);
return sum/cars.size();
}
}
Operator 인터페이스 유형
종류
매개 값
반환 값
메소드
의미
Operator
있음
있음
apply()
매개 값을 연산하여 반환 값으로 보낸다.
Function 인터페이스의 특수한 경우.
매개변수와 반환타입이 같다
apply() 사용
applyAsInt() : 결과를 정수로 반환 / applyAsDouble() : 결과를 실수로 반환
Operator는 기본 인터페이스는 없고, Binary, Unary, Double, Int, Long이 붙은 변종들만 있다.
포함하는 메소드 종류 (위의 종류에 따라 안 가지고 있을 수도 있음)
순방향 연결 디폴트 메소드 andThen()
역방향 연결 디폴트 메소드 compose()
정적 메소드 identity()
// 정의
Function<T> o = (x,y)-> {T타입 x와 y 객체를 사용하여 T타입을 반환하는 실행문;}
// Car 클래스 파일
import java.util.*;
public class Car {
private String model;
private boolean gasoline;
private int age;
private int mileage;
public Car(String model, boolean gasoline, int age, int mileage) {
this.model = model;
this.gasoline = gasoline;
this.age = age;
this.mileage = mileage;
}
public String getModel() { return model; }
public boolean isGasoline() { return gasoline; }
public int getAge() { return age; }
public int getMileage() { return mileage; }
public String toString() {
return String.format("Car(%s,%s,%d,%d)", model, gasoline, age, mileage);
}
public static final List<Car> cars = Arrays.asList(
new Car("소나타", true, 18, 210000),
new Car("코란도", false, 15, 200000),
new Car("그랜저", true, 12, 150000),
new Car("싼타페", false, 10, 220000),
new Car("아반테", true, 10, 70000),
new Car("에쿠스", true, 6, 100000),
new Car("그랜저", true, 5, 80000),
new Car("소나타", true, 2, 35000),
new Car("쏘렌토", false, 1, 10000),
new Car("아반테", true, 1, 7000)
);
}
import java.util.*;
import java.util.function.*;
import sec02.Car;
public class Operator2Demo {
public static void main(String[] args) {
// comparator +, - ,0
Comparator<Integer> comparator = (a,b) -> a-b;
// 두 수 중에 더 큰 값이 찾아지는 함수로 선언
BinaryOperator<Integer> o1 = BinaryOperator.maxBy(comparator);
System.out.println(o1.apply(10,5));
System.out.println(o1.apply(20,25));
// 두 수 중에 더 작은 값이 찾아지는 함수로 선언
BinaryOperator<Integer> o2 = BinaryOperator.minBy(comparator);
System.out.println(o2.apply(10, 5));
System.out.println(o2.apply(20, 25));
List<Car> newCars = remodeling(Car.cars, c-> new Car("뉴" +
c.getModel(), c.isGasoline(), c.getAge(), c.getMileage()
));
System.out.println(newCars);
}
// remodeling의 파라미터로 cars, new car
//new Car("뉴" +
//c.getModel(), c.isGasoline(), c.getAge(), c.getMileage()가 전달된다.
static public List<Car> remodeling(List<Car> cars, UnaryOperator<Car> o){
ArrayList<Car> result = new ArrayList<>();
for(Car car : Car.cars)
result.add(o.apply(car));
return result;
}
}
Comparator 인터페이스
객체의 순서를 정렬하기 위해 사용되는 함수형 인터페이스
메소드의 반환 타입은 모두 Comparator<T> 타입이다
매개변수 타입은 제네릭 타입이인데 복잡하므로, 편의상 생략한다.
포함하는 메소드 종류 (위의 종류에 따라 안 가지고 있을 수도 있음)
정적 메소드
comparing() : Comparable 타입의 정렬 키로 비교하는 Comparator를 반환
naturalOrder() : Comparable 객체에 자연 순서로 비교하는 Comparator를 반환
nullsFirst() : null을 객체보다 작은 값으로 취급하는 Comparator를 반환
nullsLast() : null을 객체보다 큰 값으로 취급하는 Comparator를 반환
reverseOrder() : 자연 반대 순서로 비교하는 Comparator를 반환
comparingInt(), comparingDouble() 등
디폴트 메소드
reversed() : 현재 Comparator의 역순으로 비교하는 Comparator를 반환
thenComparing() : 다중 키를 사용하여 정렬하려고 새로운 Comparator를 반환
// Car 클래스 파일
import java.util.*;
public class Car {
private String model;
private boolean gasoline;
private int age;
private int mileage;
public Car(String model, boolean gasoline, int age, int mileage) {
this.model = model;
this.gasoline = gasoline;
this.age = age;
this.mileage = mileage;
}
public String getModel() { return model; }
public boolean isGasoline() { return gasoline; }
public int getAge() { return age; }
public int getMileage() { return mileage; }
public String toString() {
return String.format("Car(%s,%s,%d,%d)", model, gasoline, age, mileage);
}
public static final List<Car> cars = Arrays.asList(
new Car("소나타", true, 18, 210000),
new Car("코란도", false, 15, 200000),
new Car("그랜저", true, 12, 150000),
new Car("싼타페", false, 10, 220000),
new Car("아반테", true, 10, 70000),
new Car("에쿠스", true, 6, 100000),
new Car("그랜저", true, 5, 80000),
new Car("소나타", true, 2, 35000),
new Car("쏘렌토", false, 1, 10000),
new Car("아반테", true, 1, 7000)
);
}
import java.util.*;
import sec02.Car;
public class Comparator1Demo {
public static void main(String[]args) {
List<Car> list = Car.cars.subList(0, 3);
Car[] cars = list.toArray(new Car[3]);
// car의 모델로 비교하는 함수 정의
Comparator<Car> modelComparator = Comparator.comparing(Car::getModel);
System.out.println("배열 cars => " + Arrays.toString(cars));
//cars를 가지고 모델을 비교하는 (가나다 순) 함수를 이요해서 정렬
Arrays.sort(cars, modelComparator);
System.out.println("모델 이름으로 정렬 : " + Arrays.toString(cars));
Arrays.sort(cars, modelComparator.reversed());
System.out.println("모델 이름 역순으로 정렬 : " + Arrays.toString(cars));
//비교 기준 : Car::getMileage 주행거리를 가져오는 함수이고, 그 결과를 정수로 비교
Arrays.sort(cars, Comparator.comparingInt(Car::getMileage));
System.out.println("주행거리 순으로 정렬 : " + Arrays.toString(cars));
// -, 0 ,+ => +, 0, - 순으로 결국 역순
Arrays.sort(cars, Comparator.comparing(Car::getMileage, (a,b) -> b-a));
System.out.println("주행거리 역순으로 정렬 : " + Arrays.toString(cars));
}
}