
git checkout b ~~
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
이걸 향상된 for문을 사용해서
List<String> list = List.of("a", "b", "c");
for (String s : list) {
System.out.println(s);
}
JAVA에서 데이터흐름(파이프라인)을 처리하기위한 방식
데이터를 반복 처리할 때, 더 선언적이고 간결하게 쓸 수 있게 도와주는 도구
| 메서드 | 역할 설명 |
|---|---|
.stream() | 컬렉션(List, Set 등)을 스트림으로 변환하여 연산 흐름 시작 |
.filter() | 조건에 맞는 데이터만 통과시킴 (if 역할) |
.map() | 데이터를 원하는 형태로 변환 (예: 객체 → |
main: A---B---C
feature: D---E (← 네가 지금 만든 커밋들)
main: A---B---C---D'---E' ← 같은 작업인데 main 뒤에 새로 재작성됨
항목 merge rebase
브랜치 병합 방식 두 브랜치를 하나로 합치고 내 브랜치를 다시 붙임
커밋 이력 분기 + merge 커밋 생김 일직선으로 정리
작업 흐름 원래 시간 순서대로 놔둠 마치 "내가 나중에 작업한 것처럼" 정리
커밋 충돌 적음 (보수적) 많을 수 있음 (재작성되니까)
협업 시 주의점 비교적 안전함 푸시 전까지만 사용해야 안전
협업 병합, 공식 마무리 시 개인 브랜치 정리, 깔끔한 이력 유지 시
흔한 수학 문제 중 하나는 주어진 점이 어느 사분면에 속하는지 알아내는 것이다. 사분면은 아래 그림처럼 1부터 4까지 번호를 갖는다. "Quadrant n"은 "제n사분면"이라는 뜻이다.

예를 들어, 좌표가 (12, 5)인 점 A는 x좌표와 y좌표가 모두 양수이므로 제1사분면에 속한다. 점 B는 x좌표가 음수이고 y좌표가 양수이므로 제2사분면에 속한다.
점의 좌표를 입력받아 그 점이 어느 사분면에 속하는지 알아내는 프로그램을 작성하시오. 단, x좌표와 y좌표는 모두 양수나 음수라고 가정한다.
첫 줄에는 정수 x가 주어진다. (−1000 ≤ x ≤ 1000; x ≠ 0) 다음 줄에는 정수 y가 주어진다. (−1000 ≤ y ≤ 1000; y ≠ 0)
점 (x, y)의 사분면 번호(1, 2, 3, 4 중 하나)를 출력한다.
12, 5
1
9,-13
4
package condition;
import java.util.Scanner;
public class BOJ_14681_Quadrant {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int y = sc.nextInt();
sc.close();
if (x>0 && y>0){
System.out.println(1);
}else if (x<0 && y>0){
System.out.println(2);
}else if (x<0 && y<0){
System.out.println(3);
}else if (x>0 && y<0){
System.out.println(4);
}
}
}
간단히 함수 좌표를 받아서 조건을 분기시키는 문제
상근이는 매일 아침 알람을 듣고 일어난다. 알람을 듣고 바로 일어나면 다행이겠지만, 항상 조금만 더 자려는 마음 때문에 매일 학교를 지각하고 있다.
상근이는 모든 방법을 동원해보았지만, 조금만 더 자려는 마음은 그 어떤 것도 없앨 수가 없었다.
이런 상근이를 불쌍하게 보던 창영이는 자신이 사용하는 방법을 추천해 주었다.
바로 "45분 일찍 알람 설정하기"이다.
이 방법은 단순하다. 원래 설정되어 있는 알람을 45분 앞서는 시간으로 바꾸는 것이다. 어차피 알람 소리를 들으면, 알람을 끄고 조금 더 잘 것이기 때문이다. 이 방법을 사용하면, 매일 아침 더 잤다는 기분을 느낄 수 있고, 학교도 지각하지 않게 된다.
현재 상근이가 설정한 알람 시각이 주어졌을 때, 창영이의 방법을 사용한다면, 이를 언제로 고쳐야 하는지 구하는 프로그램을 작성하시오.
첫째 줄에 두 정수 H와 M이 주어진다. (0 ≤ H ≤ 23, 0 ≤ M ≤ 59) 그리고 이것은 현재 상근이가 설정한 알
람 시간 H시 M분을 의미한다.
입력 시간은 24시간 표현을 사용한다. 24시간 표현에서 하루의 시작은 0:0(자정)이고, 끝은 23:59(다음날 자정 1분 전)이다. 시간을 나타낼 때, 불필요한 0은 사용하지 않는다.
첫째 줄에 상근이가 창영이의 방법을 사용할 때, 설정해야 하는 알람 시간을 출력한다. (입력과 같은 형태로 출력하면 된다.)
10 10
9 25
0 30
23 45
23 40
22 55
import java.util.Scanner;
public class Main {
public static void main(String[] arg){
Scanner sc = new Scanner(System.in);
int H = sc.nextInt(); //시간 시
int M = sc.nextInt(); //시간 분
int Minute = (M-45); //45분 줄이기
int LessMinute = ((60+M)-45); // 분이 부족할때 계산
int Hour = (H - 1);//시간 계산
if(H == 0) {
H = 24;
int ZeroHour = (H - 1);//시간 계산
if (M > 45) {
System.out.print(ZeroHour + " " + Minute);
} else if (M < 45) {
System.out.print(ZeroHour + " " + LessMinute);
}else {
System.out.print(ZeroHour + " " + Minute);
}
}else{
if (M > 45) {
System.out.print(H + " " + Minute);
} else if (M < 45) {
System.out.print(Hour + " " + LessMinute);
}else{
System.out.print(H + " " + Minute);
}
}
}
}
M == 45인 경우 Minute == 0이니까 그대로 출력하면 되는데,
H == 0이면 ZeroHour == 23이 되어야 하는데,
너는 H = 24로 만들고 → ZeroHour = 23으로 다시 설정해줌
문제는 그게 아니라,
H 값을 아예 조작하지 말고, 필요할 때 H - 1, H == 0이면 23로 대체하는 식을 원한다고 하네요 …
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int h = sc.nextInt();
int m = sc.nextInt();
m -= 45;
if (m < 0) {
m += 60;
h -= 1;
if (h < 0) h = 23;
}
System.out.println(h + " " + m);
}
}
보고 머리를 누가 망치로 친거같았습니다 깔끔하고… 한눈에 알아보기 쉽고…
조건을 많으넣으면 틀리기 쉽다! 화이팅!
KOI 전자에서는 건강에 좋고 맛있는 훈제오리구이 요리를 간편하게 만드는 인공지능 오븐을 개발하려고 한다. 인공지능 오븐을 사용하는 방법은 적당한 양의 오리 훈제 재료를 인공지능 오븐에 넣으면 된다. 그러면 인공지능 오븐은 오븐구이가 끝나는 시간을 분 단위로 자동적으로 계산한다.
또한, KOI 전자의 인공지능 오븐 앞면에는 사용자에게 훈제오리구이 요리가 끝나는 시각을 알려 주는 디지털 시계가 있다.
훈제오리구이를 시작하는 시각과 오븐구이를 하는 데 필요한 시간이 분단위로 주어졌을 때, 오븐구이가 끝나는 시각을 계산하는 프로그램을 작성하시오.
첫째 줄에는 현재 시각이 나온다. 현재 시각은 시 A (0 ≤ A ≤ 23) 와 분 B (0 ≤ B ≤ 59)가 정수로 빈칸을 사이에 두고 순서대로 주어진다. 두 번째 줄에는 요리하는 데 필요한 시간 C (0 ≤ C ≤ 1,000)가 분 단위로 주어진다.
첫째 줄에 종료되는 시각의 시와 분을 공백을 사이에 두고 출력한다. (단, 시는 0부터 23까지의 정수, 분은 0부터 59까지의 정수이다. 디지털 시계는 23시 59분에서 1분이 지나면 0시 0분이 된다.)
14 30
20
14 50
17 40
80
19 0
23 48
25
0 13
package condition;
import java.util.Scanner;
public class BOJ_2525_OvenClock {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int h = sc.nextInt();
int m = sc.nextInt();
int pt = sc.nextInt();
m += (pt%60);
h += (pt/60);
if(m>=60){
m-=60;
h+=1;
}if(h>23){
h-=24;
}
System.out.println(h+" "+m);
}
}
앞에 문제를 하고나니 머리가 잘 돌아가서 잘 풀었다 나 천잰가? 라는 생각을 했다
시간을 목과 나머지로 분리해서 더해가면서 예외처리도 하면서 시계처럼 풀었는데
gpt가 리팩토링한 코드를 보니 망치로 또 한대 맞은거같은 …
int totalMin = h * 60 + m + pt;
h = (totalMin / 60) % 24;
m = totalMin % 60;
System.out.println(h + " " + m);
??? 전부다 분으로 바꾼 다음에 몫을 24로 나눠서 시간을 뽑고
60의 나머지를 해서 분을 뽑는 나의 8줄이 4줄이 되는 기적을 맛보았다
그래도 풀엇으니까… 이런것도 있구나 이해하면서 넘어가자
git pull origin main
git checkout -b feat/category 새로운 브랜치 생성
git push --upstream origin feat/category 브랜치 연결
public class Todo {
private String task; // 할 일
private boolean isDone;// 끝난 일
private LocalDate dueDate;
private String category;
public Todo(String task,boolean isDone,String category ,LocalDate dueDate) {
this.task = task;
this.isDone = isDone;
this.category = category;
this.dueDate = dueDate;
}
@Override
public String toString() {
String checkbox = isDone ? "[x]" : "[]";
String due = dueDate != null ? "(마감일 " + dueDate + ","+ getStatus() + ")" : "";
return checkbox +""+ task +"("+category+")" +due;
public void add(String task,String category,String inputDate) {
LocalDate dueDate;
if (inputDate == null || inputDate.trim().isEmpty()) {
dueDate = LocalDate.now(); // 기본값
} else {
try {
dueDate = LocalDate.parse(inputDate);
} catch (DateTimeParseException e) {
System.out.println("⚠️ 마감일 형식이 잘못되었습니다. 오늘 날짜로 설정합니다.");
dueDate = LocalDate.now();
}
}
if (category == null || category.trim().isEmpty()) {
category = "기타";
}
todos.add(new Todo(task, false, category, dueDate));
System.out.println("할 일이 추가되었습니다.");
public void testTodoCreation() {
Todo todo = new Todo("공부하기", false,"기타" ,LocalDate.now());
assertEquals("공부하기", todo.getTask());
assertEquals("기타",todo.getCategory());
assertEquals(LocalDate.now(),todo.getDueDate());
assertFalse(todo.isDone());
}
@Test
public void testMarkDone() {
Todo todo = new Todo("운동하기", false,"기타" ,LocalDate.now());
todo.markDone();
assertTrue(todo.isDone());
}
@Test
public void testNullPointerException(){
Todo todo = null;
assertThrows(NullPointerException.class, () -> {
todo.getTask();
});
}
}
@Test
public void testAddTodo() {
service.add("복습하기","기타","2025-12-14");
assertEquals(1, service.getTodos().size());
assertEquals("복습하기", service.getTodos().get(0).getTask());
assertEquals("기타", service.getTodos().get(0).getCategory());
assertEquals(LocalDate.of(2025,12,14), service.getTodos().get(0).getDueDate());
}
TodoService int realIndex = id - 1;
@Test
public void testMarkDone() {
service.add("청소하기","기타","2025-12-14");
service.markDone(1);
assertTrue(service.getTodos().get(0).isDone());
}
@Test
public void testRemoveTodo() {
service.add("휴식","기타","2025-12-14");
service.remove(1);
assertEquals(0, service.getTodos().size());
}
코드의 흐름이 끊겨 있음
public class SyncExample {
public static void main(String[] args) {
cook();
clean();
}
public static void cook() {
try {
System.out.println("🍳 요리 시작");
Thread.sleep(3000); // 3초 동안 요리
System.out.println("🍽 요리 완료");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void clean() {
System.out.println("🧹 청소 시작");
System.out.println("🧽 청소 완료");
}
}
🍳 요리 시작
(3초 대기)
🍽 요리 완료
🧹 청소 시작
🧽 청소 완료
코드의 흐름이 끊기지 않음
public class AsyncExample {
public static void main(String[] args) {
Thread cookingThread = new Thread(() -> {
try {
System.out.println("🍳 요리 시작");
Thread.sleep(3000); // 3초 요리
System.out.println("🍽 요리 완료");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
cookingThread.start(); // 비동기 시작
clean(); // 요리와 동시에 청소함
}
public static void clean() {
System.out.println("🧹 청소 시작");
System.out.println("🧽 청소 완료");
}
}
🍳 요리 시작
🧹 청소 시작
🧽 청소 완료
(3초 후)
🍽 요리 완료
결과가 나올때까지 해당작업에서 cpu자원을 붙잡아두고 있는것
import java.util.concurrent.*;
public class BlockingExample {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<String> task = () -> {
Thread.sleep(3000); // 3초 걸리는 작업
return "작업 완료!";
};
System.out.println("작업 시작 (Blocking)");
Future<String> future = executor.submit(task);
// 결과가 나올 때까지 기다림 (Blocking)
String result = future.get();
System.out.println("결과: " + result);
executor.shutdown();
}
}
작업 시작 (Blocking)
(3초 대기)
결과: 작업 완료!
결과가 준비되지않으면 즉시 리턴하고 다른 일을하는 것
주기적으로 상태를 확인하면서 자원을 관리함 (Poling,Callback)
Poling 끝났어? 하고 주기적으로 물어보는 방식
Callback 끝나면 이거해줘~ 등록해놈
import java.util.concurrent.*;
public class NonBlockingExample {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<String> task = () -> {
Thread.sleep(3000); // 3초 걸리는 작업
return "작업 완료!";
};
System.out.println("작업 시작 (Non-Blocking)");
Future<String> future = executor.submit(task);
// 결과가 나올 때까지 다른 일 수행
while (!future.isDone()) {
System.out.println("▶ 다른 일 수행 중...");
Thread.sleep(1000);
}
// 결과 확인
String result = future.get();
System.out.println("결과: " + result);
executor.shutdown();
}
}
작업 시작 (Non-Blocking)
▶ 다른 일 수행 중...
▶ 다른 일 수행 중...
▶ 다른 일 수행 중...
결과: 작업 완료!
| 조합 | 설명 | 코드 흐름 | CPU 활용 | 예시 코드 | 주요 사용 상황 |
|---|---|---|---|---|---|
| 동기 + 블로킹 | 작업 끝날 때까지 기다림 | 멈춤 | 낮음 | reader.readLine()statement.executeQuery() | 순차처리 필요한 단순 프로그램, 파일/DB 처리 |
| 동기 + 논블로킹 | 바로 리턴하지만 결과 없을 수도 있음 | 연속 | 높음 | channel.read(buffer) (Java NIO) | 저수준 네트워크 통신, I/O 버퍼링 등 |
| 비동기 + 블로킹 | 동시에 요청하고 결과 받을 땐 멈춤 | get에서 멈춤 | 중간 | future.get() | 병렬 처리 후 결과 필요할 때 예: 멀티 다운로드 |
| 비동기 + 논블로킹 | 요청 후 다른 일, 결과는 콜백 처리 | 멈추지 않음 | 높음 | CompletableFuture.thenAccept() | 고성능 서버, UI 멈춤 방지, 실시간 처리 앱 |
오늘 무려 10일 차! 꾸준히 달려가고 있는게 상당히 멋있다
문제를 푸는데 드디어 틀렸습니다.. 가 보였고 내가 짠 코드가 너무 안멋있고 너무 비효율적인걸 확인해 버렸다
문제야 풀리면 그만이라고 생객했는데 이러면 기업이나 다른사람이 봤을때 너무 짜치는데? 라고 생각하지 않을까 라는 두려움도 생겼다
틀리고 못푸니까 푸는 시간도 길어졌고 손으로 쓰면서 이렇게 되니까 저렇게 되고 하면서 알고리즘도 머리를 사맸다
그래도 3번째 문제는 꽤 괜찮게 풀었다고 생각햇는데… gpt사마의 리팩토링을보니 그저 겸손… 알고리즘 책도 좀 읽고 더 발전해야겠다는 생각을했다
하지만 나의 자존감이 떨어지기도 전에 기능 확장에서 자존감 완전 상승!!! git 사용법도 어느정도 익숙해져서 브랜치만드는것도 샤샤샥
기능 추가하고 수정하고 리팩토링 할때마다 커밋 촥촥촥!!! 기능 추가하는데 아 이러면 이게 문제겠구나 이렇게하면 되겠는데?
메소드 인자 예외 처리까지 깔끔하게 하는 날 보고 와 성장했구나 하고 기분이가 좋아졌다 이말입니다 하하하 오늘로 자신감이 좀 붙었달까?
이렇게 성장하는거겠죠?
cs공부하면서 간간히 들었던 동기 비동기를 좀 공부했는데 이런게 있구나 … 나중엔 동기 처리할지 비동기 처리할지
뭐가 좋을지 고민하고 블로킹 논블로킹을 고민하면서 하겠지? 면접에서 질문들어오면 잘 할 수 있을까도 고민되고
지금은 콘솔에서 작동하는 앱이지만 이제 웹으로 넘어가면 더 많은걸 하겠구나 하면서 다시 심장이 타올르던 하루였다!
고생했어 오늘도!! 내일도 화이팅~