함수형 프로그래밍이란?
함수를 정의하고 이 함수를 데이터 처리부로 보내 데이터를 처리하는 기법을 말한다.
데이터 처리부는 데이터만 가지고 있을 뿐, 처리 방법이 정해져 있지 않아 외부에서 제공된 함수에 의존한다.
람다식
자바는 함수형 프로그래밍을 위해 Java 8부터 람다식을 지원한다.
데이터 처리부는 람다식을 받아 매개변수에 데이터를 대입하고 중괄호를 실행시킨다.
자바는 람다식을 익명 구현 객체로 변환한다.
인터페이스의 익명 구현 객체를 람다식으로 표현하려면 반드시 하나의 추상메소드만 가져야 한다.
인터페이스가 단 하나의 추상메소드를 가질 때, 이를 함수형 인터페이스 라고 한다.
인터페이스가 함수형 인터페이스임을 보장하기 위해서는 @FunctionalInterface 어노테이션을 붙이면 된다. 컴파일 시 추상메소드가 하나인지 검색하기 때문에 정확한 함수형 인터페이스를 작성할 수 있다.
[형식]
(매개변수, ...) -> { 처리내용 }
[예]
public interface Runnable {
void run();
}
람다식 => ( ) -> { }
@FunctionalInterface
public interface Calculable {
void calculate(int x, int y);
}
람다식 => (x, y) -> { }
Java Project : 13_lambda
Package : lambda
Interface : Compute.java
Class : LambdaMain01.java
Compute.java
package lambda;
public interface Compute {
public void calc(int x, int y);
}
인터페이스이므로 추상 메소드는 하나만 가질 수 있따 !
LambdaMain01.java
public void execute(Compute compute) {
}
인터페이스를 매개변수 인자로 받겠다.
public class LambdaMain01 {
public void execute(Compute compute) { //구현부
int x = 25;
int y = 36;
compute.calc(x, y); // 추상메소드 호출
}
Compute compute는 틀만 가지고 있다.
excute 안에 인터페이스로 잡고있으므로 excute를 부를 때 인터페이스의 객체값을 넘겨줘야한다.
lambdaMain01.execute(new Compute()); // 함수 호출
클래스가 아니므로 이렇게 할 수 없다. 인터페이스는 new할 수 없다.
lambdaMain01.execute(new Compute() {}); // 함수 호출
new는 인터페이스가 아니라 뒤에 있는 것을 생성해주는 것
lambdaMain01.execute((x, y) -> {처리할 내용}); // 함수 호출
람다식
lambdaMain01.execute((x, y) -> {
int result = x + y;
System.out.println(x + " + " + y + " = " + result);
}); // 함수 호출
LambdaMain01.java
package lambda;
public class LambdaMain01 {
public void execute(Compute compute) { //구현부
int x = 25;
int y = 36;
compute.calc(x, y); // 추상메소드 호출
}
public static void main(String[] args) {
LambdaMain01 lambdaMain01 = new LambdaMain01();
lambdaMain01.execute((x, y) -> {
int result = x + y;
System.out.println(x + " + " + y + " = " + result);
}); // 함수 호출
}
}
25 + 36 = 61
package lambda;
public class LambdaMain01 {
public void execute(Compute compute) { //구현부
int x = 25;
int y = 36;
compute.calc(x, y); // 추상메소드 호출
}
public static void main(String[] args) {
LambdaMain01 lambdaMain01 = new LambdaMain01();
lambdaMain01.execute((x, y) -> {
int result = x + y;
System.out.println(x + " + " + y + " = " + result);
}); // 함수 호출
lambdaMain01.execute((x, y) -> {
int result = x * y;
System.out.println(x + " * " + y + " = " + result);
});
}
}
25 + 36 = 61
25 * 36 = 900
Interface : Workable.java
Class : LambdaMain01
Workable.java (인터페이스)
package lambda;
@FunctionalInterface
public interface Workable {
public void work();
}
work()안에 매개변수가 없는 경우
class Person02 {
public void execute(Workable workable) {
workable.work();
}
}
public class LambdaMain02 {
public static void main(String[] args) {
Person02 person02 = new Person02();
person02.execute(() -> {
System.out.println("안녕하세요");
System.out.println("나의 이름은 홍길동입니다.");
});
person02.execute(()->{
System.out.println("반갑습니다.");
});
}
}
LambdaMain02.java
package lambda;
class Person02 {
public void execute(Workable workable) {
workable.work();
}
}
//---------------------
public class LambdaMain02 {
public static void main(String[] args) {
Person02 person02 = new Person02();
person02.execute(() -> {
System.out.println("안녕하세요");
System.out.println("나의 이름은 홍길동입니다.");
});
person02.execute(()->{
System.out.println("반갑습니다.");
});
}
}
안녕하세요
나의 이름은 홍길동입니다.
반갑습니다.
//처리하는 실행문이 1개일 경우에는 {} 생략 가능
person02.execute(()-> System.out.println("반갑습니다."));
LambdaMain02.java
package lambda;
class Person02 {
public void execute(Workable workable) {
workable.work();
}
}
//---------------------
public class LambdaMain02 {
public static void main(String[] args) {
Person02 person02 = new Person02();
person02.execute(() -> {
System.out.println("안녕하세요");
System.out.println("나의 이름은 홍길동입니다.");
});
//처리하는 실행문이 1개일 경우에는 {} 생략 가능
person02.execute(()-> System.out.println("반갑습니다."));
}
}
Interface : InterA.java
InterB.java
Class : LambdaMain03.java
InterA.java
package lambda;
@FunctionalInterface
public interface InterA {
public void disp(String name, int age);
}
InterB.java
package lambda;
@FunctionalInterface
public interface InterB {
public void output(String data);
}
LambdaMain03.java
package lambda;
class Person03{
public void execute(InterA interA) {
interA.disp("홍길동", 25);
}
public void execute(InterB interB) {
interB.output("안녕하세요 홍길동입니다.");
}
}
public static void main(String[] args) {
Person03 person03 = new Person03();
person03.execute((name, age) ->{
System.out.println("나의 이름은 " + name + "입니다.");
System.out.println("내 나이는 " + age + "살입니다.");
});
나의 이름은 홍길동입니다.
내 나이는 25살입니다.
person03.execute((data) -> {
System.out.println(data);
});
person03.execute((data) -> System.out.println(data));
//매개변수가 1개일 경우에는 () 생략 가능
person03.execute(data -> System.out.println(data));
안녕하세요 홍길동입니다.
package lambda;
class Person03{
public void execute(InterA interA) {
interA.disp("홍길동", 25);
}
public void execute(InterB interB) {
interB.output("안녕하세요 홍길동입니다.");
}
}
//----------------
public class LambdaMain03 {
public static void main(String[] args) {
Person03 person03 = new Person03();
person03.execute((name, age) ->{
System.out.println("나의 이름은 " + name + "입니다.");
System.out.println("내 나이는 " + age + "살입니다.");
});
//매개변수가 1개일 경우에는 () 생략 가능
person03.execute(data -> System.out.println(data));
}
}
나의 이름은 홍길동입니다.
내 나이는 25살입니다.
안녕하세요 홍길동입니다.
Class : LambdaMain04.java
Interface : Compute02.java
Compute02.java
package lambda;
@FunctionalInterface
public interface Compute02 {
public String calc(int x, int y);
}
return 값이 String 형태로 존재
class Person04{
public void execute(Compute02 compute02) {
compute02.calc(25, 36);
}
}
값이 return돼서 들어올 때 String 값으로 들어오므로 밑에 코드처럼 써줘야한다.
class Person04{
public void execute(Compute02 compute02) {
String result = compute02.calc(25, 36);
System.out.println(result);
}
}
public class LambdaMain04 {
public static void main(String[] args) {
Person04 person04 = new Person04();
person04.execute((x, y) -> {
int result = x + y;
return x + " + " + y + " = " + result;
});
person04.execute((x, y) -> {
return x + " + " + y + " = " + (x+y);
});
//실행문이 1개일 경우에는 {}과 함께 return 생략 가능
person04.execute((x, y) -> x + " + " + y + " = " + (x+y));
}
person04.execute((x, y) -> x + " - " + y + " = " + (x-y));
class Person04{
public void execute(Compute02 compute02) { //구현(매개변수가 인터페이스로)
String result = compute02.calc(25, 36);
System.out.println(result);
}
public int mul(int x, int y) {//매개변수가 x, y로
return x * y;
}
}
public class LambdaMain04 {
public static void main(String[] args) {
Person04 person04 = new Person04();
person04.execute((x, y) -> {
int result = x + y;
return x + " + " + y + " = " + result;
});
//실행문이 1개일 경우에는 {}과 함께 return 생략 가능
person04.execute((x, y) -> x + " + " + y + " = " + (x+y));
person04.execute((x, y) -> x + " - " + y + " = " + (x-y));
person04.execute((x, y) -> x + " * " + y + " = " + person04.mul(x, y));
}
}
25 * 36 = 900
class Person04{
public void execute(Compute02 compute02) { //구현(매개변수가 인터페이스로)
String result = compute02.calc(25, 36);
System.out.println(result);
}
public int mul(int x, int y) {//매개변수가 x, y로
return x * y;
}
public double div(int x, int y) {
return (double)x / y;
}
}
public class LambdaMain04 {
public static void main(String[] args) {
Person04 person04 = new Person04();
person04.execute((x, y) -> {
int result = x + y;
return x + " + " + y + " = " + result;
});
//실행문이 1개일 경우에는 {}과 함께 return 생략 가능
person04.execute((x, y) -> x + " + " + y + " = " + (x+y));
person04.execute((x, y) -> x + " - " + y + " = " + (x-y));
person04.execute((x, y) -> x + " * " + y + " = " + person04.mul(x, y));
person04.execute((x, y) -> x + " / " + y + " = " + person04.div(x, y));
}
}
25 / 36 = 0.6944444444444444
LambdaMain04 .java
package lambda;
class Person04{
public void execute(Compute02 compute02) { //구현(매개변수가 인터페이스로)
String result = compute02.calc(25, 36);
System.out.println(result);
}
public int mul(int x, int y) {//매개변수가 x, y로
return x * y;
}
public double div(int x, int y) {
return (double)x / y;
}
}
//------------
public class LambdaMain04 {
public static void main(String[] args) {
Person04 person04 = new Person04();
person04.execute((x, y) -> {
int result = x + y;
return x + " + " + y + " = " + result;
});
//실행문이 1개일 경우에는 {}과 함께 return 생략 가능
person04.execute((x, y) -> x + " + " + y + " = " + (x+y));
person04.execute((x, y) -> x + " - " + y + " = " + (x-y));
person04.execute((x, y) -> x + " * " + y + " = " + person04.mul(x, y));
person04.execute((x, y) -> x + " / " + y + " = " + person04.div(x, y));
}
}
25 + 36 = 61
25 + 36 = 61
25 - 36 = -11
25 * 36 = 900
25 / 36 = 0.6944444444444444
Class : LambdaMain05.java
메소드 참조
메소드를 참조해서 매개변수의 정보 및 리턴 타입을 알아내 람다식에서 불필요한 매개변수를 제거하는 것을 목적으로 한다.
큰수를 리턴하는 람다식
(x, y) -> Math.max(x, y);
위에서 단순히 x, y 값을 매개값으로 전달하는 역활만 하기 때문에 메소드 참조를 이용하면 깔끔하게 처리된다.
Math :: max;
//Math 클래스의 max 함수를 이용하면 된다.
[형식]
① 정적 메소드
클래스 :: 메소드
② 인스턴스 메소드
참조변수 :: 메소드
LambdaMain05.java
package lambda;
class Calculator {
public static String staticMethod(int x, int y) {
return x + " + " + y + " = " + (x+y);
}
public String non_staticMethod(int x, int y) {
return x + " * " + y + " = " + (x*y);
}
}
public class LambdaMain05 {
public static void main(String[] args) {
Person04 person04 = new Person04();
person04.execute((x, y) -> Calculator.staticMethod(x, y));
25 + 36 = 61
호출하기만 하면 되니까 밑에처럼 바꿔도된다.
person04.execute(Calculator :: staticMethod);
25 + 36 = 61
person04.execute((x, y) -> new Calculator().non_staticMethod(x, y));
person04.execute(new Calculator() :: non_staticMethod);
25 * 36 = 900
25 * 36 = 900
package lambda;
@FunctionalInterface
interface Comp {
public int compare(String name, String irum); //음수, 0, 양수
}
class Person06 {
public void order(Comp comp) {
String name = "홍길동";
String irum = "코난";
int result = comp.compare(name, irum);
if(result < 0)
System.out.println(name + ", " + irum);
else if(result > 0)
System.out.println(irum + ", " + name);
else
System.out.println("같은 이름입니다.");
}
}
public class LambdaMain06 {
public static void main(String[] args) {
Person06 person06 = new Person06();
person06.order((name, irum) -> name.compareTo(irum)); //String의 compareTo()
//메소드만 호출하고 있으므로 바꿀 수 있음
person06.order(String :: compareTo); //메소드만 호출하고 있으므로 바꿀 수 있음
LambdaMain06. java
package lambda;
@FunctionalInterface
interface Comp {
public int compare(String name, String irum); //음수, 0, 양수
}
//-----------------
class Person06 {
public void order(Comp comp) {
String name = "홍길동";
String irum = "코난";
int result = comp.compare(name, irum);
if(result < 0)
System.out.println(name + ", " + irum);
else if(result > 0)
System.out.println(irum + ", " + name);
else
System.out.println("같은 이름입니다.");
}
}
//-----------------
public class LambdaMain06 {
public static void main(String[] args) {
Person06 person06 = new Person06();
person06.order((name, irum) -> name.compareTo(irum)); //String의 compareTo()
person06.order(String :: compareTo); //메소드만 호출하고 있으므로 바꿀 수 있음
}
}
String name = "홍길동";
String irum = "코난";
코난, 홍길동
String name = "둘리";
String irum = "코난";
둘리, 코난
String name = "코난";
String irum = "코난";
같은 이름입니다.
LambdaMain07.java
생성자 참조 new
생성자를 참조한다는 것은 객체를 생성하는 것을 의미한다.
생성자 Overload 되어 여러 개가 있을 경우, 함수형 인터페이스의 추상메소드와 동일한 매개변수 타입과 개수를 가진 생성자를 찾아 실행한다.
(a, b) -> {
return new 클래스(a, b);
}
=> 생성자 참조 클래스 :: new
@FunctionalInterface
interface Create1 {
public Person create(String nmae);
}
//---------------------
interface Create2 {
public Person02 create(String name, int age);
}
class Person{
private String name;
private int age;
public Person(String name) {
this.name = name;
System.out.println("Person(String name) 생성자");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Person(String name, int age) 생성자");
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
class PersonTest {
public Person getPerson01(Create01 create1) {
String name = "name";
Person person = new Person(name);
return person;
}
public Person getPerson02(Create02 create2) {
String name = "홍길동";
int age = 25;
Person person = new Person(name, age);
return person;
}
}
public class LambdaMain07 {
public static void main(String[] args) {
PersonTest personTest = new PersonTest();
Person one = personTest.getPerson01(Person :: new);
System.out.println("이름 : " + one.getName());
System.out.println("나이 : " + one.getAge());
System.out.println();
Person two = personTest.getPerson01(Person :: new);
System.out.println("이름 : " + one.getName());
System.out.println("나이 : " + one.getAge());
System.out.println();
}
}
package lambda;
@FunctionalInterface
interface Create01 {
public Person create(String nmae);
}
//---------------------
interface Create02 {
public Person02 create(String name, int age);
}
//---------------------
class Person{
private String name;
private int age;
public Person(String name) {
this.name = name;
System.out.println("Person(String name) 생성자");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Person(String name, int age) 생성자");
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
//---------------------
class PersonTest {
public Person getPerson01(Create01 create1) {
String name = "name";
Person person = new Person(name);
return person;
}
public Person getPerson02(Create02 create2) {
String name = "홍길동";
int age = 25;
Person person = new Person(name, age);
return person;
}
}
//---------------------
public class LambdaMain07 {
public static void main(String[] args) {
PersonTest personTest = new PersonTest();
Person one = personTest.getPerson01(Person :: new);
System.out.println("이름 : " + one.getName());
System.out.println("나이 : " + one.getAge());
System.out.println();
Person two = personTest.getPerson01(Person :: new);
System.out.println("이름 : " + one.getName());
System.out.println("나이 : " + one.getAge());
System.out.println();
}
}
Person(String name) 생성자
이름 : name
나이 : 0
Person(String name) 생성자
이름 : name
나이 : 0
'JAVA' 카테고리의 다른 글
DAY 16 - LOMBOK / 시퀀스 객체 / JDBC / DB 연결 (2024.07.24) (0) | 2024.08.09 |
---|---|
DAY 17 - MEMBER (2024.07.25) (0) | 2024.08.08 |
DAY 20 - Network (2024.07.30) (0) | 2024.08.07 |
DAY 21 - Network Thread (2024.07.31) (0) | 2024.08.06 |
DAY 21 - Stream (2024.07.31) (0) | 2024.08.06 |