ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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

    댓글

lee-ding