-
[java] 함수형 프로그래밍 (람다, 스트림)java 2023. 1. 20. 17:08
람다 (익명 함수)
<람다 축약> 1. (int a, int b) -> a+b; 입력항목 리턴값 2. (a,b) -> a+b; //인터페이스에 이미 입출력에 대한 타입정의가 되어있을경우 ,입력값의 타입은 생략이 가능 3. Integer::sum // (a,b)->a+b는 Integer.sum(int a, int b)와 동일하기때문에 축약 가능
예를 통해 살펴보자
일반적인 코드
interface Calculator{ int sum(int a, int b); } class MyCalculator implements Calculator{ public int sum(int a, int b) { return a+b; } } public class Sample{ public static void main(String[] args) { MyCalculator mc = new MyCalculator(); int result = mc.sum(3, 4); System.out.println(result); //7 출력 } }
람다를 적용한 코드
람다를 사용하면 실체클래스 없이도 인터페이스의 객체를 생성할수있다.
interface Calculator{ int sum(int a, int b); } public class Sample{ public static void main(String[] args) { Calculator mc = (int a, int b)->a+b; int result = mc.sum(3, 4); System.out.println(result); //7 출력 } }
int a, int b는 sum메소드에 입력항목, a+b는 리턴값이 된다.
인터페이스 사용시 주의사항
람다를 사용할 인터페이스에 메소드가 위예제처럼 1개가 아닌 2개이상이면 람다함수를 사용할 수 없다.
그래서 람다 함수로 사용할 인터페이스는 @FunctionalInterface어노테이션을 사용해야한다,
->2개 이상의 메소드를 가진 인터페이스를 작성하는것을 불가능하게만들어주는 어노테이션
@FunctionalInterface
@FunctionalInterface interface Calculator{ int sum(int a, int b); int mum(int a); //@FunctionalInterface는 두번째 메소드를 허용하지 않음 사용불가하게 만듦 }
다음은 인터페이스를 생성하지 않고 함수형 프로그래밍을 위해 제공되는 인터페이스들을 사용하여 위코드를 더 축약해봤다.
(BiFunction interface 이용)
import java.util.function.BiFunction; public class Sample{ public static void main(String[] args) { BiFunction<Integer, Integer, Integer>mc = (a,b)->a+b; int result = mc.apply(3,4); System.out.println(result); //7 출력 } }
BiFunction의 <Integer, Integer, Integer> 제네릭스는 순서대로 입력항목2개 출력항목 1개를 의미한다.
BiFunction 의 apply메소드를 호출하면 람다함수(a,b) ->a+b가 실행된다.
(BinaryOperator interface 이용)
입출력항목이 동일한 경우 BinaryOperator를 이용해 더 간단하게 표현할수있다.
import java.util.function.BinaryOperator; public class Sample{ public static void main(String[] args) { BinaryOperator<Integer> mc = (a, b)->a+b; int result = mc.apply(3,4); System.out.println(result); //7 출력 } }
Stream // 더공부가 필요!
데이터가 물결처럼 흘러가면서 필터링 과정을 통해 여러변 변경되어 반환되기때문에 이러한 이름을 갖게 되었다.
문제) 배열에서 짝수만 뽑아 중복을 제거한 후 역순으로 정렬하는 프로그램을 작성해보자.
import java.util.ArrayList; import java.util.Comparator; import java.util.HashSet; public class Sample{ public static void main(String[] args) { int[] data ={5,6,4,2,3,1,1,2,2,4,8}; //짝수만 포함하는 ArrayList생성 ArrayList<Integer> dataList = new ArrayList<>(); for (int i = 0; i < data.length; i++) { if (data[i] % 2 == 0) { dataList.add(data[i]); } } System.out.println(dataList); //Set을 사용하여 중복을 제거 HashSet<Integer> dataSet = new HashSet<>(dataList); System.out.println(dataSet); //Set을 다시 List로 변경 ArrayList<Integer> distinctList = new ArrayList<>(dataSet); System.out.println(distinctList); //역순으로 정렬 distinctList.sort(Comparator.reverseOrder()); System.out.println(distinctList); //Integer리스트를 정수 배열로 전환 int[] result = new int[distinctList.size()]; for (int i = 0; i < distinctList.size(); i++) { result[i] = distinctList.get(i); System.out.println(result[i]); } } }
[6, 4, 2, 2, 2, 4, 8] [2, 4, 6, 8] [2, 4, 6, 8] [8, 6, 4, 2] 8 6 4 2
위 예제를 스트림을 이용해서 작성해 보겠다.
import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashSet; public class Sample{ public static void main(String[] args) { int[] data = {5, 6, 4, 2, 3, 1, 1, 2, 2, 4, 8}; int[] result = Arrays.stream(data) //IntStream을 생성한다. (정수 배열) .boxed() //Int Stream을 Stream<Integer>로 변경한다. (sorted에서 reverseOrder는 Integer타입을 사용하기때문에 바꿔주었음) .filter((a) -> a*2 ==0)//짝수만 뽑아낸다 .distinct()//중복을 제거한다 .sorted(Comparator.reverseOrder())//역순으로 정렬한다. .mapToInt(Integer::intValue)//Stream<Integer>를 IntStream으로 변경한다. (최종적으로 int[]을 리턴해야하기때문에 int타입으로 바꾸어줌) .toArray()//int[] 배열로 변경한다. ; }}
Arrays.strem : 스트림 생성
boxed,filter,dictinct,sorted,mapToInt : 스트림 가공
toARray : 스트림 형태 변환
'java' 카테고리의 다른 글
5장 연습문제 (1) 2023.01.25 4장 연습문제 (0) 2023.01.22 [java] Thread / Runnable (0) 2023.01.20 [java] 예외처리 (Exception), 트랜잭션 (0) 2023.01.20 [java] this, static, 싱글톤, final, 상수 (0) 2023.01.19