스택(Stack)은 한쪽 끝에서만 데이터를 넣고 뺄 수 있는 제한적으로 접근할 수 있는 후입선출(Last-In-First-Out) 형태의 선형 자료구조이다.
데이터 추가(.push())
public class MyStack {
// 스택에 실제 데이터가 저장되는 곳 arr
private final int[] arr = new int[16];
// 현재 스택의 최고점을 파악하기 위한 top
private int top = -1;
//push : 데이터를 스택의 제일 위에 넣는 메소드
public void push(int data){
// 0. arr가 가득 찬 건지 판단한다.
if(arr.length - 1 == top){
throw new RuntimeException("stack is full");
}
// 1. top을 하나 증가 시킨다.
top++;
// 2. arr[top]에 data를 할당한다.
arr[top] = data;
// 끝!!
}
}
데이터 회수(.pop())
public int pop() {
// 0. arr가 비어있는지 판단한다. top을 기준으로 -1이라면 비어있는 것
if(top == -1){
throw new RuntimeException("stack is empty");
}
// 1. arr[top]의 값을 임시저장한다.
int temp = arr[top];
// 2. top의 값을 하나 감소한다.
top--;
// 3. 임시 저장했던 값을 반환한다. (return)
return temp;
}
데이터 확인 (.peek())
//peek : 제거하지 않고 스택의 맨 위에 값을 반환한다. top의 값을 변환시키지 않은 상태
public int peek() {
// 0. arr가 비어있는지 판단한다.
if(top == -1){
throw new RuntimeException("stack is empty");
}
// 1. return arr[top]
return arr[top];
}
데이터 비어있는지 확인 (.isEmpty())
public boolean empty(){
// 스택이 비어있을 때 top의 값은 -1을 반환한다.
return top == -1;
}
데이터 가득 차 있는지 확인 (.isFull())
public boolean isFull() {
// 스택이 다 차있는 경우, 배열 크기보다 하나 작은 크기를 반환한다
return top == capacity - 1;
}
메서드가 호출되면 수행에 필요한 만큼의 메모리를 스택에 할당
호출 스택의 제일 위에 있는 메서드가 현재 실행 중인 메서드
함수 또는 메소드의 호출 시 마지막 수행 위치를 Stack에 저장
호출된 함수가 종료 시 마지막 수행위치로 복귀하기 위해 Stack에서 pop(반환 후 제거)
( 할당 되었던 메모리 공간은 반환되어 비워짐 )
자신을 다시 사용(재참조)하는 재귀적 함수 호출로 인해 Call Stack의 최상단이 JVM의 Heap에 도달할 때
즉, Stack 영역의 메모리가 지정된 범위를 넘어갈 때 발생하는 에러
push
와 pop
을 이용한 예제
public class ParTest {
public boolean solution() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String input = reader.readLine(); // 괄호 입력 받는 부분
Stack<Character> charStack = new Stack<>(); //Character형을 담는 stack
// 문자열의 길이만큼 순회한다.
for (int i = 0; i < input.length(); i++) {
// charAt을 이용하여 문자열 하나씩 검사
char next = input.charAt(i);
// 1. 여는 괄호를 만날 때 push
if (next == '(') {
charStack.push(next);
}
// 2. 닫는 괄호를 만날 경우
else if (next == ')') {
// a. pop 할 게 없으면 검사 실패 (false 반환) => Stack이 비어있다.
if (charStack.empty()) return false;
// b. 아니라면 pop
char top = charStack.pop();
// c. pop의 결과로 나온 값이 여는 괄호인지 확인 => 여는 괄호가 아니라면 실패
if (top != '(') return false;
}
}
// 3. 순회가 끝났을 때 스택이 비었는지 확인
return charStack.empty();
}
public static void main(String[] args) throws IOException {
System.out.println((new ParTest()).solution());
}
}
public class ParTest2 {
public boolean solution() throws IOException{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String input = reader.readLine(); //괄호 입력 받는 부분
//소괄호, 중괄호, 대괄호로 이루어진 수식을 검사하는 코드를 작성하시오
Stack<Character> charStack = new Stack<>();
for (int i = 0; i < input.length(); i++) {
// charAt을 이용하여 문자열 하나씩 검사
char next = input.charAt(i);
// 1. 모든 여는 괄호를 만날 때 push
if (next == '(' || next =='{' || next == '[') {
charStack.push(next);
}
// 2. 어떤 닫는 괄호를 만날 경우
else if (next == ')' || next == '}' || next == ']') {
// a. pop 할 게 없으면 검사 실패 (false 반환) => Stack이 비어있다.
if (charStack.empty()) return false;
// b. 아니라면 pop
char top = charStack.pop();
// c. pop의 결과로 나온 값이 올바른 여는 괄호인지 확인 => 맞는 괄호가 아니라면 실패
// 들어온 건 닫는 소괄호 && top은 여는 소괄호가 아닐 때 실패
if (next == ')' && top != '(') return false;
else if(next =='}' && top != '{') return false;
else if(next ==']' && top != '[') return false;
}
}
// 3. 순회가 끝났을 때 스택이 비었는지 확인
return charStack.empty();
}
public static void main(String[] args) throws IOException {
System.out.println(new ParTest2().solution());
}
}
반복적으로 자주 사용되는 코드들(Boilerplate)을 간편하게 사용할 수 있게 해주는 어노테이션 기반 자바 라이브러리다. ex) Getter, Setter
Lombok은 컴파일 시에만 작동한다.
NoArgsConstructor
: 파라미터가 없는 기본 생성자를 생성해준다. 만약 final이 있는 필드가 있다면 Compiler가 에러를 일으킨다.
AllArgsConstructor
: 모든 필드 값을 파라미터로 받는 생성자를 만들어준다.
즉, 이경우에는 필드값에 매칭되는 값을 하나하나 전부 다 parameter에 매칭시켜서 생성자를 호출해야 한다
RequiredArgsConstructor
: final이나 @NonNull이 적혀있는 필드를 대상으로 생성자를 생성해준다.
당연히 매칭되는 파라미터 값이 존재해야 하며 NonNull에 경우 null check를 제공해준다.
getter와 setter 메소드를 롬복이 세팅해준다.
클래스 단위가 아니라 필드 단위에 설정해도 된다. 그럴 경우 해당되는 필드에만 Getter 또는 Setter 메소드를 설정해준다.
DDL – Data Definition Language, 데이터의 모습을 정의하기 위한 명령
DML – Data Manipulation Language, 데이터 조작을 위한 명령
DCL – Data Control Language, 데이터 접근 권한 관련
데이터 무결성이란 데이터베이스에서 데이터의 정확성, 일관성, 유효성을 유지하는 것을 의미한다.
정확하고 신뢰할 수 있는 정보를 저장하고 유지해야 하기 때문에 데이터 무결성은 중요한 개념이다.
이 데이터 무결성을 위해서 테이블의 컬럼에 들어올 수 있는 데이터를 제한 시키는 것. 또는 그 제약 조건을 Table constraints
라고 한다.
데이터의 무결성을 강화하고 일관성을 유지하는 데 도움이 된다.
데이터의 무결성을 보장하고 부적절한 데이터 입력을 방지하는 데 사용된다.
NOT NULL : 해당 열에는 NULL
값을 허용하지 않는다는 것을 나타낸다. 즉, 열에는 항상 값이 존재해야 하며, NULL
값을 입력하려고 하면 오류가 발생한다.
UNIQUE : 해당 열의 값이 중복되지 않아야 한다는 것을 나타낸다. UNIQUE
제약 조건을 가진 열은 각 레코드에서 고유한 값을 가져야 한다. 다른 레코드에 이미 존재하는 값을 입력하려고 하면 오류가 발생한다.
PRIMARY KEY : 해당 열의 값이 고유하며, NULL
값을 허용하지 않는다. PRIMARY KEY
는 테이블에서 레코드를 식별하는 주요 식별자 역할을 한다.
주로 AUTOINCREMENT
와 함께 사용되어 자동으로 증가하는 고유한 값으로 기본 키를 생성한다.
AUTOINCREMENT : 일련번호를 자동으로 생성하기 위한 옵션이다. 주로 PRIMARY KEY
와 함께 사용되며, 해당 열이 자동으로 증가하는 고유한 값을 가지게 된다.
AUTOINCREMENT
를 사용하면 데이터베이스 시스템이 새 레코드를 삽입할 때마다 해당 열의 값을 자동으로 증가시킨다.
-- DDL
-- CREATE TABLE : 새로운 테이블을 데이터베이스에 추가
-- CREATE TABLE table_name(
-- column_name_1 integer,
-- column_name_2 integer,
-- column_name_3 integer,
-- ...
-- );
-- id, name, email
CREATE TABLE students
(
id INTEGER,
name VARCHAR(32),
email TEXT
);
-- id, username, first_name, last_name, email
CREATE TABLE students_2
(
id INTEGER,
username TEXT,
first_name TEXT,
last_name TEXT,
email TEXT
);
-- Constraints
-- NOT NULL Constraint
CREATE TABLE students_not_null
(
id INTEGER,
username TEXT,
first_name TEXT,
last_name TEXT,
email TEXT NOT NULL -- email은 null이 될 수 없다.
);
-- UNIQUE Constraint
CREATE TABLE students_unique
(
id INTEGER,
username TEXT UNIQUE, -- username은 레코드별로 고유하다.
first_name TEXT,
last_name TEXT,
email TEXT
);
-- PRIMARY KEY + AUTOINCREMENT
CREATE TABLE students_pka
(
-- id INTEGER PRIMARY KEY
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT,
first_name TEXT,
last_name TEXT,
email TEXT
);
-- Final
CREATE TABLE students_final
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE ,
first_name TEXT,
last_name TEXT,
email TEXT NOT NULL
);
-- ALTER TABLE
-- RENAME TO
ALTER TABLE students_2 RENAME TO students_temp;
ALTER TABLE students_temp RENAME TO students_2;
-- RENAME COLUMN
ALTER TABLE students_2 RENAME COLUMN first_name TO given_name;
ALTER TABLE students_2 RENAME COLUMN given_name TO first_name;
ALTER TABLE students_2 RENAME COLUMN last_name TO sur_name;
ALTER TABLE students_2 RENAME COLUMN sur_name TO last_name;
-- ADD COLUMN
ALTER TABLE students_2 ADD COLUMN phone VARCHAR(64);
ALTER TABLE students_2 ADD COLUMN phone_2 VARCHAR(64) NOT NULL;
ALTER TABLE students_2 ADD COLUMN phone_3 VARCHAR(64) NOT NULL DEFAULT '';
-- DROP COLUMN
ALTER TABLE students_2 DROP COLUMN phone_3;
-- DROP TABLE
DROP TABLE students_2;
DROP TABLE IF EXISTS students_2;
SELECT * FROM users;
-- SELECT * FROM users;
-- SELECT column_1, column_2, ..., column_n
-- FROM table_name;
-- id, first_name, last_name, age, balance, phone, email, country
SELECT first_name, age
FROM users;
SELECT first_name, last_name, age
FROM users;
-- 이름, 나이, 잔고, 전화번호를 출력하는 SELECT 문 작성
SELECT first_name, last_name, age, balance, phone
FROM users;
-- DISTINCT : 중복없이 조회할 때 사용
SELECT DISTINCT country
FROM users;
SELECT DISTINCT first_name
FROM users;
-- DISTINCT에 두 개의 컬럼을 작성하면?
SELECT DISTINCT first_name, last_name
FROM users;
-- SELECT ORDER BY : 정렬된 조회
SELECT first_name, age, balance
FROM users
ORDER BY first_name;
SELECT last_name, balance
FROM users
ORDER BY balance DESC;
-- ORDER BY 에 두 가지 이상의 칼럼을 지정하면?
SELECT first_name, last_name
FROM users
ORDER BY balance, age;
-- WHERE : 조건을 덧붙인 조회
SELECT *
FROM users
WHERE age >= 30;
SELECT *
FROM users
WHERE age < 30;
-- 40 이상 50 미만
SELECT *
FROM users
WHERE age >= 40 AND age < 50;
-- 30 미만 60 이상
SELECT *
FROM users
WHERE age < 30 OR age >= 60;
-- WHERE 문자열 LIKE
-- email이 naver.com인 계정만 조회
SELECT id, first_name, email
FROM users
WHERE email LIKE '%naver.com';
-- % 기호를 사용하면, 0개 이상의 문자와 일치한다고 가정한다.
SELECT id, first_name, phone
FROM users
WHERE phone LIKE '010%';
-- NOT LIKE
SELECT id, first_name, phone
FROM users
WHERE phone NOT LIKE '010%';
출처 : 멋사 백엔드 5기 6팀 식스센스
백엔드 위키 작성
오늘 배운 대부분이 저번에 배웠던 내용들이라 다시 한 번 복습을 하는 날이 되었다. SQL은 몇 번 해본걸 실습하느라 어렵지는 않았다. Stack은 저번에 집중이 잘 안됐는지 금방 잊었는데 오늘 다시 보니까 이해가 되었다. 월요일에다 위키 작성일이라 걱정이 조금 됐는데 강사님의 빌드인지 월요일이라서 가볍게 진행해주신 것 같아서 다행이다. 충전 제대로 하고 내일 다시 에너지를 써야겠다.