s.indexOf("()")
: 해당 문자열이 있으면 해당 인덱스, 없다면 -1 리턴()
의 위치를 찾은 후 공백으로 변환public boolean solution(String s) {
// Stack 쓰지않고 괄호 풀기
while(s.indexOf("()") >= 0){
s = s.replace("()", "");
}
return s.length() == 0;
}
s.indexOf("()")
: 해당 문자열이 있으면 해당 인덱스, 없다면 -1 리턴()
을 기준으로 splitpublic boolean solution1(String s) {
// Stack 쓰지않고 괄호 풀기
while(s.indexOf("()") >= 0){
String[] splitted = s.split("\\(\\)");
s = String.join("", splitted);
}
return s.length() == 0;
}
(
면 push를 이용하여 stack에 넣기)
면, Stack이 비어있다면 올바르지 않은 괄호이므로 false 리턴, 남아있는 것이 있다면 popimport java.util.Stack;
public class SolveBracket02 {
// Stack으로 괄호 풀기
private Stack<Character> stack = new Stack<>();
boolean solution(String s) {
for (int i = 0; i < s.length(); i++) {
if('(' == s.charAt(i)){
stack.push(s.charAt(i));
} else if (')' == s.charAt(i)) {
if(stack.isEmpty()) return false;
stack.pop();
}
}
return stack.isEmpty();
}
}
Stack으로 풀면 장점
연산속도 : O(N^2) ➡ O(N)
에러
Communications link failure
: 재빌드 후 환경변수 재설정 후 해결
과정
- deleteAll, getCount 추가
- deleteAll, getCount 테스트
- User 객체를 따로 생성하여 테스트 보완
(User selectedUser = userDao.findbyId(user1.getId());
assertEquals(user1.getName(), selectedUser.getName());)- findbyId 예외처리(찾는 Id가 없을 경우)
- 테스트 코드 개선(BeforeEach 추가, Autowired에 변수 선언)
- deleteAll 예외처리(비정상적인 서버 종료로 close가 안될수도)
try catch 의문사항
현재 문제점
try/catch/finally 문제 : 너무 반복이 심함
➡ 익숙해지면 복붙하면서 빠르게 할 수 있지만
➡ Human에러의 가능성
➡ 따라서 리펙토링, 테스트를 해야함
UserDao의 메소드 : 몇 부분만 다르고 나머지는 동일
➡ StatementStrategy
인터페이스 도입
개선 과정
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public interface StatementStrategy {
PreparedStatement makePreparedStatement(Connection conn) throws SQLException;
}
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class DeleteAllStrategy implements StatementStrategy{
@Override
public PreparedStatement makePreparedStatement(Connection conn) throws SQLException {
return conn.prepareStatement("DELETE FROM users");
}
}
변경 전
ps = conn.prepareStatement("DELETE FROM users");
변경 후
StatementStrategy strategy = new DeleteAllStrategy();
ps = strategy.makePreparedStatement(conn);
ps = stmt.makePreparedStatement(conn);
로 사용하여 원하는 preparedStatement를 불러옴public void jdbcContextWithStatementStrategy(StatementStrategy stmt) throws SQLException, ClassNotFoundException {
Connection conn = null;
PreparedStatement ps = null;
try{
conn = connectionMaker.getConnection();
ps = stmt.makePreparedStatement(conn);
ps.executeUpdate();
} catch (SQLException e) {
throw e;
} finally { // error가 나도 실행되는 블럭
if(ps != null) {
try {
ps.close();
} catch (SQLException e) {
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
}
}
}
}
public void deleteAll() throws SQLException, ClassNotFoundException {
jdbcContextWithStatementStrategy(new DeleteAllStrategy());
}
import likelion.domain.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class AddStrategy implements StatementStrategy{
User user;
public AddStrategy(User user) {
this.user = user;
}
@Override
public PreparedStatement makePreparedStatement(Connection conn) throws SQLException {
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO users(id, name, password) VALUES (?, ?, ?)");
pstmt.setString(1, user.getId());
pstmt.setString(2, user.getName());
pstmt.setString(3, user.getPassword());
return pstmt;
}
}
🔴 add() 메소드 개선
public void add(User user) throws SQLException, ClassNotFoundException {
AddStrategy addStrategy = new AddStrategy(user);
jdbcContextWithStatementStrategy(addStrategy);
}