자바 함수형 인터페이스로 클로저로직 구현하기

LiiNi·2025년 2월 21일

계기

순열, 조합, 부분집합을 자바로 구현할 때 여러 마음에 들지 않는 부분이 더러 있었다.
1. N, R, ARR등 모든 변수를 static으로 전역변수로 둬야한다
2. is_selected, visited같이 순조부만을 위한 변수도 static으로 전역변수로 두니 다른 변수들하고 용도가 헷갈려짐
3. 순조부의 결과가 보통 재구함수의 기저부분에 완성이 되니, 이때 바로 그 결과를 가지고 로직을 실행하고싶음.(결과값을 모조리 하나의 Array에 넣는건 비효율적)

public class SubSetTest2 {
	static int[] arr;
	
	//subSet에 관한 변수도 추가... 여기에 적고 싶지않음..
	static boolean[] is_selected;
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		arr = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
		is_selected = new boolean[arr.length];
		subSet(0);
	}
	private static void subSet(int cnt) {
		if(cnt == arr.length) {
			//subSet결과인 is_selected를 사용한 로직을 다변화하고시싶다.
			for (int i = 0; i < is_selected.length; i++) {
				System.out.print(((is_selected[i])? arr[i] : "X") + " ");
			}
			System.out.println();
			return;
		}
		
		is_selected[cnt] = true;
		subSet(cnt+1);
		is_selected[cnt] = false;
		subSet(cnt+1);
	}
}
/* 입력
 * 1 2 3
출력
1 2 3 
1 2 X 
1 X 3 
1 X X 
X 2 3 
X 2 X 
X X 3 
X X X 
 * 
 * */

구현

1. 클래스를 이용하여 1, 2해결

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

class SubSet{
	int[] arr;
	boolean[] is_selected;
	public SubSet(int[] arr) {
		this.arr = arr;
		is_selected = new boolean[arr.length];
		createSubSet(0);
	}
	private void createSubSet(int cnt) {
		if(cnt == arr.length) {
			//순조부 결과인 is_selected를 이용한 로직을 콜백형태로 전달하고 싶어...
            for (int i = 0; i < is_selected.length; i++) {
				System.out.print(((is_selected[i])? arr[i] : "X") + " ");
			}
			System.out.println();
			return;
		}
		
		is_selected[cnt] = true;
		createSubSet(cnt+1);
		is_selected[cnt] = false;
		createSubSet(cnt+1);
	}
}

public class SubSetTest {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int[] arr = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();

		new SubSet(arr);
	}
}
/* 입력
 * 1 2 3
출력
1 2 3 
1 2 X 
1 X 3 
1 X X 
X 2 3 
X 2 X 
X X 3 
X X X 
 * 
 * */

하지만, 콜백을 넘겨줘서 내가 하고싶은 로직을 순조부의 결과가 나온 곳에서 바로 실행시키고 싶다. 그래서 함수형 인터페이스를 사용하여 고쳤다.

2. 함수형 인터페이스 Consumer계열을 사용

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

class SubSet{
	int[] arr;
	boolean[] is_selected;
	private BiConsumer<boolean[], SubSet> callback;
	public SubSet(int[] arr, BiConsumer<boolean[], SubSet> print) {
		this.arr = arr;
		is_selected = new boolean[arr.length];
		this.callback = print;
		createSubSet(0);
	}
	private void createSubSet(int cnt) {
		if(cnt == arr.length) {
        //콜백함수를 js처럼 바로 사용하진못하고, 이렇게 .accept()를 활용해야함
			this.callback.accept(is_selected, this);
			return;
		}
		
		is_selected[cnt] = true;
		createSubSet(cnt+1);
		is_selected[cnt] = false;
		createSubSet(cnt+1);
	}
}

public class SubSetTest {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int[] arr = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
		
		BiConsumer<boolean[], SubSet> print = (is_selected, object)->{
			for (int i = 0; i < is_selected.length; i++) {
				System.out.print(((is_selected[i])? object.arr[i] : "X") + " ");
			}
			System.out.println();
		};
        //콜백함수와 같이 전달
		new SubSet(arr, print);
	}
}
profile
보안을 겸비하고픈 풀스택개발자

0개의 댓글