1. 문제점.
다음은 입력받은 두 문자열이 아나그램(한 단어에서 알파벳의 순서만 바꾼 것, 예: god dog)에 해당하는지 검사하는 간단한 프로그램입니다. 해쉬맵에 각 문자와 개수를 저장한 뒤, 해쉬맵이 서로 일치하는지 검사합니다.
이 때 해쉬맵이 서로 일치하는지 판단하기 위해 forEach 메소드를 사용했습니다. 그리고 내부에 람다식을 넣어 hm1의 값과 hm2의 값이 서로 일치하지 않으면 result 를 false로 변경해주려 했습니다.
딱히 이상할 것이 없어보이는 코드인데 빨간 줄이 똭!
Variable used in lambda expression should be a final or effectively final.
라고 하네요.
람다식 내부에서는 final 이거나 effectively final인 변수만 사용할 수 있다는 겁니다.
바로 return을 하는 것도 안 됩니다.
Scanner sc = new Scanner(System.in);
String s1 = sc.next();
String s2 = sc.next();
Boolean result = true;
HashMap<Character, Integer> hm1 = new HashMap<>();
HashMap<Character, Integer> hm2 = new HashMap<>();
if(s1.length() != s2.length()) return false;
for(int i = 0; i < s1.length(); i++) {
char next1 = s1.charAt(i);
char next2 = s2.charAt(i);
int cnt1 = 0, cnt2 = 0;
if(hm1.get(next1) != null) cnt1 = hm1.get(next1);
if(hm2.get(next2) != null) cnt2 = hm2.get(next2);
hm1.put(next1, cnt1 + 1);
hm2.put(next2, cnt2 + 1);
}
hm1.forEach((key, value)->{
if(value != hm2.get(key)) {
result = false; (X)
return false; (X)
}
});
return result;
2. 원인
(1) java의 람다식 또는 익명 클래스 내부에서는 final이거나 effectively final인 외부 지역 변수에만 접근할 수 있습니다.
final은 최초 1회 할당된 후 변경되지 않는 엔티티를 의미합니다.
effectively final은 명시적으로 final은 아니나, 실질적으로 final처럼 사용되는 경우를 말합니다.
즉,
final int realFinal = 10;
int effectivelyFinal = 10;
final 키워드로 선언된 변수, 메서드, 클래스는 final이므로 값을 변경할 수 없고,
final로 선언하지는 않았지만 코드 상에서 값이 변경되지 않는 변수는 effectively final 이라고 할 수 있습니다.
위 코드에서 result 는 람다식 외부에서 선언된 지역 변수이므로 람다식 내부에서는 접근할 수가 없습니다.
(2) 왜?
는 나중에 알아보도록 하고 우선 문제를 해결하겠습니다.
(참조 : https://vagabond95.me/posts/lambda-with-final/)
3. 해결
① 별도의 클래스를 만들고 객체를 생성하여 값을 저장해주는 방법
class result {
public String result = "";
}
② 클래스 변수를 선언하여 사용하는 방법
import java.util.*;
public class Problem {
String result = "YES";
public String solve() {
Scanner sc = new Scanner(System.in);
String s1 = sc.next();
String s2 = sc.next();
HashMap<Character, Integer> hm1 = new HashMap<>();
HashMap<Character, Integer> hm2 = new HashMap<>();
if(s1.length() != s2.length()) return "NO";
for(int i = 0; i < s1.length(); i++) {
char next1 = s1.charAt(i);
char next2 = s2.charAt(i);
int cnt1 = 0, cnt2 = 0;
if(hm1.get(next1) != null) cnt1 = hm1.get(next1);
if(hm2.get(next2) != null) cnt2 = hm2.get(next2);
hm1.put(next1, cnt1 + 1);
hm2.put(next2, cnt2 + 1);
}
Result r = new Result();
hm1.forEach((key, value)->{
if(value != hm2.get(key)) {
result = "NO";
}
});
return result;
}
}
'Java & Spring' 카테고리의 다른 글
[Java] 자료구조 - LinkedList (0) | 2022.09.28 |
---|---|
[Java] 자료구조 - 큐(Queue) (0) | 2022.09.22 |
java) 예외 처리 (0) | 2021.12.13 |
java) 스레드 Thread 와 동기화 (0) | 2021.12.09 |
Java 입출력을 위한 BufferedReader / BufferedWriter (0) | 2021.11.14 |
댓글