Codewars 문제풀기 (03/01)
Mumbling
- 문자열을 인자로 받아서 결과 문자열 출력
- accum(“abcd”) –> “A-Bb-Ccc-Dddd”
-
accum(“RqaEzty”) –> “R-Qq-Aaa-Eeee-Zzzzz-Tttttt-Yyyyyyy”
- 문자열은 a-z A-z로만 이루어져있다.
1. Test를 만들었다
-
문자열길이가 1일때
입력한문자 하나의 대문자를 출력해주면되겠구나
public static String accum(String s){ return s.toUpperCase(); }
-
문자열길이가 2이상일때
문자열의 index+1만큼 문자를 찍어내되 첫문자는 대문자, 그 이후는 소문자 문자사이는 “-“로 이어준다. 라고생각
public static String accum(String s){ String result = ""; for(int i = 0; i < s.length(); i++) { for(int j = 0; j < i + 1 ; j++) { if(j == 0) { result += String.valueOf(s.charAt(i)).toUpperCase(); } else { result += String.valueOf(s.charAt(i)).toLowerCase(); } } result += "-"; } return result; }
제출하니까 문자열 마지막에 “-“가 붙어서 fail이 떴다. 그래서 수정
public static String accum(String s){ String result = ""; for(int i = 0; i < s.length(); i++) { for(int j = 0; j < i + 1 ; j++) { if(j == 0) { result += String.valueOf(s.charAt(i)).toUpperCase(); } else { result += String.valueOf(s.charAt(i)).toLowerCase(); } } if(i == s.length() - 1) { break; } result += "-"; } return result; }
제출하니까 Success.
2. 리팩토링 시작
코드를 보니까 뭘 수정할 수 있을까 고민해보니 첫 문자는 어짜피 대문자니까 바깥 for문에 넣어줘도 되겠다고 생각했다.
public static String accum(String s){
String result = "";
for(int i = 0; i < s.length(); i++) {
result += String.valueOf(s.charAt(i)).toUpperCase();
for(int j = 0; j < i ; j++) {
result += String.valueOf(s.charAt(i)).toLowerCase();
}
if(i == s.length() - 1) {
break;
}
result += "-";
}
return result;
}
if(i == s.length() - 1) break;
이 부분을 없애서 더 깔끔하게 만들어주면 좋을거같은데 생각은 들었는데.. 더 좋은방법이 생각나지않아서 그냥 제출
3. 답 비교, 느낀점
Best Practice 가장 많이 받은 코드
public class Accumul {
public static String accum(String s) {
StringBuilder bldr = new StringBuilder();
int i = 0;
for(char c : s.toCharArray()) {
if(i > 0) bldr.append('-');
bldr.append(Character.toUpperCase(c));
for(int j = 0; j < i; j++) bldr.append(Character.toLowerCase(c));
i++;
}
return bldr.toString();
}
}
- 바깥 for문에서 s.toCharArray로 해결했구나, 이렇게하면 확실히
if(i == s.length() - 1) break;
이부분 없애줄 수 있구나 느낌 - 근데 String써도 될거같은데 왜 StringBuilder를 쓰지? 그러고보면 String StringBuilder StringBuffer 차이점이뭘까?
- inline으로 표현하니 확실히 가독성이 떨어지는 걸 느낀다. 적어도 이 코드에선 그렇게 느낌
- toUpperCase, toLowerCase가 String클래스뿐 아니라 Character클래스에도 내부 메소드로 존재하는구나
Best Practice 두번째로 많이 받은 코드
public class Accumul {
public static String accum(String s) {
s = s.toLowerCase();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
builder.append(Character.toUpperCase(ch));
for (int j = 0; j < i; j++) {
builder.append(ch);
}
builder.append("-");
}
return builder.deleteCharAt(builder.lastIndexOf("-")).toString();
}
}
-
이게 그나마 내가 작성한 코드랑 가장 비슷하다.
-
deleteCharAt(builder.lastIndexOf("-"))
이걸로 마지막 “-“를 지워주면 되겠는구나! -
여기도 StringBuilder를 썼네?
4. 궁금한거 검색
-
String과 StringBuilder, StringBuffer의 차이
-
String은 불변객체이므로 새로운 값을 할당할때마다 새로 생성된다. String 클래스가 생성될때 내부 변수와 메서드들도 같이 생성되며 각 String의 주소값이 stack에 쌓이고 클래스들은 garbage collector가 호출되기전까지 heap에 쌓이므로 많이 사용될수록 메모리 관리측면에서 치명적이다.
-
StringBuilder와 StringBuffer는 객체 생성을 한번만 하고 append를 이용해 메모리 값을 변경시켜 문자열을 변경한다.
-
따라서 String은 문자열을 단순히 읽는 작업을 할때 좋고, StringBuilder와 StringBuffer는 문자열 연산이 자주있을때 사용하면 좋다.
-
-
StringBuilder와 StringBuffer의 차이
- StringBuffer는 멀티 쓰레드 환경에서 동기화가 가능하지만 StringBuilder는 동기화를 지원하지 않는다.
- 따라서 싱글 쓰레드환경에서는 StringBuilder가 적합하고, 멀티 쓰레드 환경에서는 StringBuffer가 적합하다.
-
lastIndexOf와 indexOf차이
String test = "A-Bb-Ccc-Ddddd-Eeeeee"; int indexOf = test.indexOf("-"); // 1 int lastIndexOf = test.lastIndexOf("-"); // 14
indexOf는 찾으려는 문자열을 왼쪽에서부터 찾는다. “-“ 문자열은 [1] index이므로 1을 반환
lastIndexOf는 찾으려는 문자열을 오른쪽에서부터 찾는다. “-“ 문자열은 [14] index이므로 14를 반환
댓글남기기