728x90

step 2 - 1. 위장


내가 떠올린 풀이 해설

문제를 읽다 보면 hashMap으로 풀어야 하는 단서가 되는 게 있다. 제한 사항에 같은 이름을 가진 의상은 존재하지 않습니다를 보고 떠올릴 수 있을 것 같다. 저는 hashMap의 key에 의상의 이름을 담고, value에 종류를 담아서 풀려고 했다. 하지만 key에 종류를 담고 value에 숫자를 담는다. 만약 담으려는 키가 존재하면 key의 value값을 리턴하고 만약 존재하지 않으면 default값을 반환하는 getOrDefault를 이용했다. 같은 종류의 의상은 1개밖에 입지 못하므로 경우의 수를 이용해서 풀었다. 


정확한 풀이

import java.util.*;

public class step2_1 {

	public static void main(String[] args) {
		String[][] clothes = {{"yellowhat", "headgear"}, 
								{"blue", "eyewear"}, 
								{"green_turban", "headgear"}};
		HashMap<String, Integer> map = new HashMap<>();
		int answer = 1;
		for(int i = 0; i < clothes.length; i++) {
			map.put(clothes[i][1], map.getOrDefault(clothes[i][1], 0) + 1);
        }
		Set<String> keySet = map.keySet();
		for(String key : keySet) {
			answer *= map.get(key) + 1;
		}
		System.out.println(answer - 1);
	}
}

오늘의 회고

문제를 풀면 풀수록 부족하다는 생각이 드네요. 언제쯤 쉽게 문제를 해결할 수 있을까요...? 오늘은 맥북 충전 단자가 고장이나서 서비스 센터에 갔다 오느라 정신없었던 하루였습니다. 공부도 많이 못했습니다. 남은 시간이라도 열심히 공부하겠습니다.

728x90
728x90

숨바꼭질 1679번


내가 떠올린 풀이 해설

BFS를 응용해서 푸는 문제였다. BFS()를 호출한 후 BFS에서 arr 배열을 최대 크기 배열로 생성한 후 Queue에 n을 add한다. Queue가 비어있을 때까지 반복한다. now 값에 Queue에서 poll 한 값을 대입하고 for문을 i가 3보다 작을 때까지 반복한다. 1초 후에 now - 1, now + 1, now * 2로 움직여야한다. 만약 next가 k와 같다면 arr[now]를 리턴해준다. 또한 만약 next가 0보다 크거나 같고 next가 100001보다 작아야하고 arr[next]가 0일 때 arr[next]에 arr[now] + 1을 대입한다. 그리고 Queue에 next를 add한다.


정확한 풀이

import java.util.*;
public class Baek1697 {
	static int n;
	static int k;
	static int[] arr;
	static Queue<Integer> que = new LinkedList<>();
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		k = sc.nextInt();
		
		if (n >= k) {
            System.out.println(n - k);
        } else {
            System.out.println(BFS());
        }
	}
	private static int BFS() {
		arr = new int[100001];
		que.add(n);
		arr[n] = 1;
		while(!que.isEmpty()) {
			int now = que.poll();
			for(int i = 0; i < 3; i++) {
				int next;
				if (i == 0) {
                    next = now - 1;
                } 
				else if (i == 1) {
                    next = now + 1;
                } 
                else {
                    next = now * 2;
                }
                if (next == k) {
                    return arr[now];
                }
                if (next >= 0 && next < 100001 && arr[next] == 0) {
                    arr[next] = arr[now] + 1;
                    que.add(next);
                }
			}
		}
		return 0;
	}
}

파티 1238번


내가 떠올린 풀이 해설

이 문제를 푸는데 시간이 오래 걸렸다. 다익스트라에서 조금만 응용하면 되는 문제였다. 1~N을 출발점으로 파티 마을 X까지의 거리를 다익스트라로 구한다. 그리고 반대로 파티 마을 X를 출발점으로 다익스트라를 돌려서 각 마을까지의 거리를 구했다. 그리고 이 두 값을 마을마다 더해주면 오고 가는 거리가 나오는데 이 값들 중 최댓값을 구하면 된다. time 배열은 파티 마을까지 오고 가는 거리의 값이다. 1~N 마을을 출발지로 다익스트라를 돌린 후 X까지의 거리를 time에 더해준다. 그 후 X를 출발지로 각 마을까지 거리를 구하여 time에 더해준다. 그 이후 time의 값들 중 최대값을 출력한다. 그 다음 dijkstra를 호출하고 다익스트라 메서드에서 우선순위 큐에 시작 정점을 넣어준다. 시작 지점의 가중치는 0이다. visit, distance를 초기화하고 distance에는 -1을 넣어준다. 우선순위 큐가 빌 때까지 while문을 반복한다. 현재 정점에 방문하지 않았을 때 연결된 정점들에 대해 검사를 시작한다. 연결된 정점의 가중치가 -1이거나 연결된 정점의 가중치가 현재 정점의 가중치와 현재 간선의 가중치의 합보다 클 때 값을 업데이트한다. 업데이트 후 다음 정점을 우선순위 큐에 넣어준다. Circle 클래스는 정점의 번호와 가중치를 가진다. 우선순위 큐의 타입으로 이용하기 위해 Comparable을 implements 해준다. 정렬 기준은 가중치의 오름차순이다.


 

참고 블로그

https://jellyinghead.tistory.com/79

 

[백준 1238] 파티 (자바)

난이도 : 골드 3 다익스트라 알고리즘을 이용해 풀었습니다. 2020/11/02 - [문제풀이/자바] - [백준 1753] 최단경로 (자바) [백준 1753] 최단경로 (자바) https://www.acmicpc.net/problem/1753 1753번: 최단경로..

jellyinghead.tistory.com


정확한 풀이

import java.util.*;
import java.io.*;

public class Baek1238 {
	static int[] distance;
	static boolean[] visit;
	static ArrayList<Circle>[] list;
	static PriorityQueue<Circle> que = new PriorityQueue<>();
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int x = Integer.parseInt(st.nextToken());
		visit = new boolean[n + 1];
		list = new ArrayList[n + 1];
		distance = new int[n + 1];
		
		for(int i = 1; i <= n; i++) {
			list[i] = new ArrayList<Circle>();
		}
		
		for(int i = 0; i < m; i++) {
			st = new StringTokenizer(br.readLine());
			int u = Integer.parseInt(st.nextToken());
			int v = Integer.parseInt(st.nextToken());
			int w = Integer.parseInt(st.nextToken());
			list[u].add(new Circle(v, w));
		}
		int time[] = new int[n+1];
        for(int i = 1; i <= n; i++) {
            dijkstra(i);
            time[i] += distance[x];
        }
        
        dijkstra(x);
        for(int i = 1; i <= n; i++)
            time[i] += distance[i];
        
        int max = 0;
        for(int i = 1; i <= n; i++) 
            max = Math.max(max, time[i]);
    
        System.out.println(max);
	}

	private static void dijkstra(int x) {
		que.offer(new Circle(x, 0));
		visit = new boolean[visit.length];
		distance = new int[distance.length];
        Arrays.fill(distance, -1);
		distance[x] = 0;
		while(!que.isEmpty()) {
			Circle current = que.poll();
			int c_v = current.vertex;
			if(visit[c_v]) {
				continue;
			}
			visit[c_v] = true;
			for(int i = 0; i < list[c_v].size(); i++) {
				Circle tmp = list[c_v].get(i);
				int next = tmp.vertex;
				int value = tmp.value;
				if(distance[next] == -1 || distance[next] > distance[c_v] + value) {
					distance[next] = distance[c_v] + value;
					que.add(new Circle(next, distance[next]));
				}
			}
		}	
	}
}	
class Circle implements Comparable<Circle> {
	int vertex, value;
	Circle(int vertex, int value) {
		this.vertex = vertex;
		this.value = value;
	}
	@Override
	public int compareTo(Circle o) {
		return value - o.value;
	}
}

오늘의 회고

오늘은 BFS와 다익스트라 문제를 풀었습니다. 두 문제 모두 조금만 응용해서 푸는 문제였고, 너무 오랫만에 BFS와 다익스트라 문제를 풀어서 시간이 오래걸렸습니다. 다른 개념들도 까먹지않게 여러 개념의 문제들을 풀어야할 것 같습니다. 조금만 화이팅하자

728x90

'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글

백준) DP, DFS  (0) 2022.08.27
백준) HashMap  (0) 2022.07.23
백준) 우선순위 큐, DP  (0) 2022.07.18
백준) 수학(피타고라스), 이분 탐색  (0) 2022.07.16
백준) 수학, 이분 탐색  (0) 2022.07.13
728x90

Optional<T>

T타입 객체의 래퍼 클래스 - Optional<T>

public final class Optional<T> {
   private final T value; // T 타입의 참조변수
      ....
   }
}

NullPointerException 오류의 발생이 없고 if문 코드로 null을 체크 안 해줘도 되는 장점이 있다.

 

Optional<T> 객체를 생성하는 다양한 방법

String str = "abc";
Optional<String> optVal = Optional.of(str);
Optional<String> optVal = Optional.of("abc");
Optional<String> optVal = Optional.of(null); // NullpointerException 발생
Optional<String> optVal = Optional.ofNullable(null); // ok

null 대신 빈 Optional<T> 객체를 사용하자

Optional<String> optVal = null; // 널로 초기화 바람직하지 않음
Optional<String> optVal = Optional.<String>empty(); // 빈 객체로 초기화

Optional 객체의 값 가져오기

Optional<String> optVal = Optional.of("abc");
String str1 = optVal.get(); // optVal에 저장된 값을 반환, null이면 예외발생
String str2 = optVal.orElse(" "); // optVal에 저장된 값이 null이면 " "반환
String str3 = optVal.orElseGet(String::new); // 람다식 사용가능
String str4 = optVal.orElseThrow(NullPointerException::new); // 널이면 예외발생

isPresent() - Optional 객체의 값이 null이면 false, 아니면 true를 반환

 

728x90
728x90

최대 힙 11279번


내가 떠올린 풀이 해설

이 문제는 단순히 우선순위 큐를 이용하면 해결할 수 있는 문제이다. 우선순위 큐의 Collections.reverseOrder를 이용하면 poll를 하면 배열에서 큰 숫자대로 출력된다. 0일 때 배열에서 제일 큰 수가 출력되도록 문제를 풀면 된다.


정확한 풀이

import java.util.*;
import java.io.*;
public class Baek11279 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		PriorityQueue<Integer> que = new PriorityQueue<>(Collections.reverseOrder());
		for(int i = 0; i < n; i++) {
			int m = Integer.parseInt(br.readLine());
			if(m != 0) {
				que.offer(m);
			}
			else {
				if(que.isEmpty()) {
					System.out.println(0);
				}
				else {
					System.out.println(que.poll());
				}
			}
		}
	}
}

Four Squares 17626번


내가 떠올린 풀이 해설

dp는 점화식을 떠올리는게 제일 어렵다. 제일 작은 수부터 계산을 해보면 1은 1개, 2 2개, 3 3개, 4  1개, 5  2개, 6  3개, 7  4개, 8  2개, 9  1개이다. 어떤 수 i의 최적의 해는 i 보다 작은 모든 제곱수 들 중 i - (제곱수)를 한 해 중 가장 작은 해에 1을 더한 값을 의미합니다. 그러면 점화식은 dp [i] = min(dp [i - j * j]) + 1 이렇게 작성할 수 있다. 작성한 점화식을 이용해 2중 for문을 이용해 풀면 답이 나오는 문제이다.


정확한 풀이

import java.util.*;
public class Baek17626 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int[] dp = new int[n + 1];
		dp[1] = 1;
		int min = 0;
		// 점화식 dp[i] = min(dp[i - j * j]) + 1
		for(int i = 2; i <= n; i++) {
			min = Integer.MAX_VALUE;
			for(int j = 1; j * j <= i; j++) {
				int tmp = i - j * j;
				min = Math.min(min, dp[tmp]);
			}
			dp[i] = min + 1;
		}
		System.out.println(dp[n]);
	}
}

오늘의 회고

오늘은 한주를 시작하는 월요일입니다. 이번 주도 열심히 공부하고 알고리즘 문제를 풀겠습니다. 벌써 제가 5월 13일에 퇴사하고 취업 준비한 지 2달이 지났습니다. 아직 부족한 것이 많은데 시간이 금방 지나갔습니다. 원래 퇴사하고 그전에 있던 회사에서 느낀 점 퇴사한 이유 취업준비에 대한 다짐을 쓴 글을 취업 준비하기 첫날에 쓰려고 했는데 쓰고 지우 고를 반복하다가 아직까지 작성하지 못했습니다. 취업 준비한 지 2달쯤 지났고 해이해진 정신상태를 다시 잡기 위해 다음 주 까지는 작성하겠습니다.

728x90
728x90

join()

지정된 시간 동안 특정 스레드가 작업하는 것을 기다린다.

예외처리를 해야 된다.(InterruptedException이 발생하면 작업 재개)

 

yield()

남은 시간을 다음 쓰레드에게 양보하고, 자신(현재 스레드)은 실행 대기한다.

yield()와 interrupt()를 적절히 사용하면, 응답성과 효율을 높일 수 있다.

 

스레드의 동기화

멀티 쓰레드 프로세스에서는 다른 쓰레드의 작업에 영향을 미칠 수 있다.

진행 중인 작업이 다른 스레드에게 간섭받지 않게 하려면 동기화가 필요

동기화하려면 간섭받지 않아야 하는 문장들을 임계 영역으로 설정

임계 영역은 락을 얻은 단 하나의 스레드만 출입가능(객체 1개에 락 1개)

 

synchronized를 이용한 동기화

synchronized로 임계 영역(lock이 걸리는 영역)을 설정하는 방법 2가지

1. 메서드 전체를 임계 영역으로 지정
public sychronized void calcsum() {
   // ...             임계 영역
}
2. 특정한 영역을 임계 영역으로 지정
sychronized(객체의 참조변수) {
   // ...             임계 영역
}

wait()과 notify()

동기화 효율을 높이기 위해 wait(), notify()를 사용

Object클래스에 정의되어 있으며, 동기화 블록 내에서만 사용할 수 있다.

  • wait() - 객체의 lock을 풀고 스레드를 해당 객체의 waiting pool에 넣는다.
  • notify() - waiting pool에서 대기 중인 쓰레드 중의 하나를 깨운다.
  • notifyAll() - waiting pool에서 대기중인 모든 스레드를 깨운다.

람다식

함수(메서드)를 간단한 식으로 표현하는 방법

익명 함수(이름이 없는 함수, anonymous function)

함수와 메서드의 차이

  • 근본적으로 동일. 함수는 일반적 용어, 메서드는 객체지향 개념 용어
  • 함수는 클래스에 독립적, 메서드는 클래스에 종속적

람다식 작성하기

  1. 메서드의 이름과 반환 타입을 제거하고 '->'를 블록{ } 앞에 추가한다.
  2. 반환 값이 있는 경우, 식이나 값만 적고 return문 생략 가능(끝에 ; 안 붙임)
  3. 매개변수의 타입이 추론 가능하면 생략 가능(대부분의 경우 생략 가능)

람다식 작성하기 - 주의 사항

  1. 매개변수가 하나인 경우, 괄호() 생략 가능(타입이 없을 때만)
  2. 블록 안의 문장이 하나뿐 일 때, 괄호 { } 생략 가능(끝에 ; 안 붙임)
  3. 단 하나뿐인 문장이 return문이면 괄호 { } 생략 불가

람다식은 익명 함수가 아니라 익명 객체이다.

 

함수형 인터페이스

함수형 인터페이스 - 단 하나의 추상 메서드만 선언된 인터페이스

함수형 인터페이스 타입의 참조 변수로 람다식을 참조할 수 있음(단, 함수형 인터페이스의 메서드와 람다식의 매개변수 개수와 반환 타입이 일치해야 함)

 

생성자와 메서드 참조

콜론 두 개 (:: – 이중 콜론 연산자)의 정식 명칭은 메서드 참조 표현식(method reference expression)이며, 결론부터 말하자면 람다식에서 파라미터를 중복해서 쓰기 싫을 때 사용합니다.

람다 표현식(expression)에서만 사용 가능하고, 사용 방법은 [인스턴스]::[메서드명(또는 new)]

Supplier<MyClass> s = () -> new MyClass();
Supplier<Myclass> s = MyClass::new;

 

스트림

다양한 데이터 소스를 표준화된 방법으로 다루기 위한 것

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> intStream = list.stream(); // 컬렉션
Stream<String> strStream = Stream.of(new String[] {"a", "b", "c"}); // 배열
Stream<Integer> evenStream = Stream.iterate(0, n -> n + 2); // 0, 2, 4, 6, ...
Stream<Double> randomStream = Stream.generate(Math::random); // 람다식
IntStream intStream = new Random().ints(5); // 난수 스트림(크기가 5)

스트림

스트림이 제공하는 기능 - 중간 연산과 최종 연산

  • 중간 연산 - 연산 결과가 스트림인 연산. 반복적으로 적용 가능
  • 최종 연산 - 연산 결과가 스트림이 아닌 연산. 단 한 번만 적용 가능(스트림의 요소를 소모)

Stream.distinct(). limit(5). sorted(). forEach(System.out::println)

. distinct() : 중간 연산,. limit(5) : 중간 연산,. sorted() : 중간 연산,. forEach(System.out::println) : 최종 연산

스트림은 데이터 소스로부터 데이터를 읽기만 할 뿐 변경하지 않는다.

스트림은 Iterator처럼 일회용이다.(필요하면 다시 스트림을 생성해야 함)

최종 연산 전까지 중간 연산이 수행되지 않는다. - 지연된 연산

 

 

728x90
728x90

숫자 카드 2 10816번


내가 떠올린 풀이 해설

이분 탐색 문제를 풀어봤었지만 조금만 응용하니까 못 푸는 문제가 발생했다. 이 문제는 이분 탐색으로 상한 과 하한을 구해서 그 길이를 빼서 같은 값의 길이를 구하는 문제이다. 하한을 구하는 메서드에서 만약 찾으려는 값이 arr배열 mid위치의 값보다 같거나 작을 때 end를 mid값으로 바꾸고 조건에 만족하지 않을 때 start를 mid + 1 값으로 바꾼다. 상한의 경우에는 찾으려는 값이 arr배열 mid 위치의 값 보다 크거나 같을 때 start 값을 mid + 1의 값으로 바꾸고 조건에 만족하지 않으면 end 값을 mid 값으로 바꿔준다. 


정확한 풀이

import java.util.*;
import java.io.*;

public class Baek10816 {
	static int[] arr;
	static int n;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		n = Integer.parseInt(br.readLine());
		arr = new int[n];
		
		StringTokenizer st = new StringTokenizer(br.readLine());
		for(int i = 0; i < n; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}
		Arrays.sort(arr);
		
		int m = Integer.parseInt(br.readLine());
		st = new StringTokenizer(br.readLine());
		for(int i = 0; i < m; i++) {
			int find = Integer.parseInt(st.nextToken());
			bw.append((right(find) - left(find)) + " ");
		}
		bw.flush();
		bw.close();
	}

	private static int left(int find) {
		int start = 0;
		int end = n;
		while(start < end) {
			int mid = (start + end) / 2;
			if(find <= arr[mid]) {
				end = mid;
			}
			else {
				start = mid + 1;
			}
		}
		return start;
	}

	private static int right(int find) {
		int start = 0;
		int end = n;
		while(start < end) {
			int mid = (start + end) / 2;
			if(find >= arr[mid]) {
				start = mid + 1;
			}
			else {
				end = mid;
			}
		}
		return start;
	}
}

직각 삼각형 4153번


내가 떠올린 풀이 해설

단순히 구현문제인것 같다. 하지만 이렇게 코드를 짜면 정답은 나오지만 좋지 않은 풀이인 것 같다. 단순이 if, else if, else로 피타고라스 정리를 이용해 풀었다. 각 변을 제곱해서 두 변을 합한 값이 다른 값과 같으면 right 다르면 wrong으로 풀었다.


정확한 풀이

import java.util.*;
import java.io.*;

public class Baek4153 {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		int h = Integer.parseInt(st.nextToken());
		while(n != 0) {
			if((n*n + m*m) == h*h) {
				System.out.println("right");
			}
			else if((h*h + m*m) == n*n) {
				System.out.println("right");
			}
			else if((n*n + h*h) == m*m) {
				System.out.println("right");
			}
			else {
				System.out.println("wrong");
			}
			st = new StringTokenizer(br.readLine());
			n = Integer.parseInt(st.nextToken());
			m = Integer.parseInt(st.nextToken());
			h = Integer.parseInt(st.nextToken());
		}
	}
}

오늘의 회고

오늘은 단순 수학문제와 이분 탐색 문제를 풀었습니다. 이분 탐색 문제를 그 전에도 풀어봐서 금방 해결할 수 있을 것이라고 생각했는데 조금만 응용해서 나오면 풀지 못하는 문제가 발생했습니다. 문제를 해결할 때 넓은 시야로 접근하는 방법에 대해 공부를 해야 될 것 같습니다. 알고리즘을 공부해도 잘 늘지 않는 것 같습니다ㅠㅠ 더 열심히 공부하겠습니다.

728x90
728x90

열거형

관련된 상수들을 같이 묶어 놓은 것. Java에는 타입에 안전한 열거형을 제공

열거형 정의 방법

  • enum 열거형 이름 { 상수명 1, 상수명 2,...}

열거형 상수의 비교는 == 과 compareTo() 사용 가능

모든 열거형은 Enum의 자손이며, 아래의 메서드를 상속받는다.

메서드 설명
Class<E> getDeclaringClass() 열거형의 class 객체를 반환
String name() 열거형 상수의 이름을 문자열로 반환
int ordinal() 열거형 상수가 정의된 순서를 반환(0부터 시작)
T valueOf(Class<T> enumType, String name) 지정된 열거형에서 name과 일치하는 열거형 상수를 반환

불연속적인 열거형 상수의 경우, 원하는 값을 괄호() 안에 적는다.

  • enum Direction { EAST(1), SOUTH(5), WEST(-1)}

괄호를 사용하려면, 인스턴스 변수와 생성자를 새로 추가해 줘야 한다.

enum Direction {
  EAST(1), SOUTH(5), WEST(-1);
  private final int value; // 정수를 저장할 필드(인스턴스 변수)를 추가
  Direction(int value) {
     this.vlaue = value;  // 생성자를 추가
  }
  public int getValue() {
     return value;
  }
}

열거형의 생성자는 묵시적으로 private이므로, 외부에서 객체 생성 불가

 

메타 애너테이션

메타 애너테이션은 애너테이션을 위한 애너테이션

메타 에너테이션은 java.lang.annotation 패키지에 포함

애너테이션 설명
@Target 애너테이션이 적용가능한 대상을 지정하는데 사용
@Documented 애너테이션 정보가 javadoc으로 작성된 문서에 포함되게 한다.
@Inherited 애너테이션 자손 클래스에 상속되도록 한다.
@Retention 애너테이션이 유지되는 범위를 지정하는데 사용한다.
@Repeatable 애너테이션을 반복해서 적용할 수 있게 한다.

@Target

대상 타입 의미
ANNOTATION_TYPE 애너테이션
CONSTRUCTOR 생성자
FIELD 필드(맴버변수, enum상수)
LOCAL_VARIABLE 지역변수
METHOD 메서드
PACKAGE 패키지
PARAMETER 매개변수
TYPE 타입(클래스, 인터페이스, enum)
TYPE_PARAMETER 타입 매개변수
TYPE_USE 타입이 사용되는 모든 곳

@Retention

유지 정책 의미
SOURCE 소스 파일에만 존재, 클래스파일에는 존재하지 않음
CLASS 클래스 파일에 존재, 실행시 사용 불가 , 기본 값
RUNTIME 클래스 파일에 존재, 실행시에 사용 가능

컴파일러에 의해 사용되는 애너테이션의 유지 정책은 SOURCE이다.

실행 시에 사용 가능한 애너테이션의 정책은 RUNTIME이다.

 

프로세스

실행 중인 프로그램, 자원과 스레드로 구성

 

쓰레드

프로세스 내에서 실제 작업을 수행

모든 프로세스는 최소한 하나의 스레드를 가지고 있다.

 

멀티 스레드의 장단점

장점

  • 시스템 자원을 보다 효율적으로 사용할 수 있다.
  • 사용자에 대한 응답성이 향상된다.
  • 작업이 분리되어 코드가 간결해진다.

단점

  • 동기화에 주의해야 한다.
  • 교착상태가 발생하지 않도록 주의해야 한다.
  • 각 스레드가 효율적으로 고르게 실행될 수 있게 해야 한다. 

쓰레드 구현과 실행

  1. Thread 클래스를 상속
  2. Runnable 인터페이스를 구현

스레드의 실행

스레드를 생성한 후에 start()를 호출해야 쓰레드가 작업을 시작한다.

ThreadEx1_1 t1 = new ThreadEx1_1(); // 쓰레드 t1을 생성한다.
ThreadEx1_1 t2 = new ThreadEx1_1(); // 쓰레드 t2을 생성한다.

t1.start(); // 쓰레드 t1을 실행시킨다.
t2.start(); // 쓰레드 t2를 실행시킨다.

 

main 쓰레드

main 메서드의 코드를 수행하는 쓰레드

스레드는 사용자의 쓰레드와 데몬 쓰레드 두 종류가 있다.

 

스레드의 우선순위

작업의 중요도에 따라 스레드의 우선순위를 다르게 하여 특정 쓰레드가 더 많은 작업시간을 갖게 할 수 있다.

setPriority(숫자);

 

쓰레드 그룹

서로 관련된 스레드를 그룹으로 묶어서 다루기 위한 것

모든 스레드는 반드시 하나의 쓰레드 그룹에 포함되어 있어야 한다.

쓰레드 그룹을 지정하지 않고 생성한 쓰레드는 main 쓰레드 그룹에 속한다.

자신을 생성한 스레드(부모 쓰레드)의 그룹과 우선순위를 상속받는다.

 

데몬 쓰레드

일반 스레드의 작업을 돕는 보조적인 역할을 수행

일반 스레드가 모두 종료되면 자동적으로 종료된다.

가비지 컬렉터, 자동 저장, 화면 자동갱신 등에 사용된다.

무한루프와 조건문을 이용해서 실행 후 대기하다가 특정 조건이 만족되면 작업을 수행하고 다시 대기하도록 작성한다.

boolean isDaemon() - 스레드가 데몬 스레드인지 확인한다.

void setDaemon(boolean on) - 스레드를 데몬 스레드로 또는 사용자 쓰레드로 변경, 매개변수 on을 true로 지정하면 데몬 스레드가 된다.

setDaemon(boolean on)은 반드시 start()를 호출하기 전에 실행되어야 한다. 그렇지 않으면 IllegalThreadStateException이 발생한다.

 

스레드의 상태

상태 설명
NEW 쓰레드가 생성되고 아직 start()가 호출되지 않은 상태
RUNNABLE 실행 중 또는 실행 가능 상태
BLOCKED 동기화블럭에 의해서 일시정지된 상태(lock이 풀릴 때까지 기다리는 상태)
WAITING, TIMED_WAITING 쓰레드의 작업이 종료되지는 않았지만 실행가능하지 않은(unrunnable) 일시정지 상태. TIMED_WAITING은 일시정지시간이 지정된 경우를 의미
TERMINATED 쓰레드의 작업이 종료된 상태

 

sleep()

현재 스레드를 지정된 시간 동안 멈추게 한다.

예외처리를 해야 한다.(InterruptedException이 발생하면 깨어남)

 

interrupt()

대기상태인 스레드를 실행 대기 상태로 만든다.

 

 

728x90
728x90

HashSet

객체를 저장하기 전에 기존에 같은 객체가 있는지 확인

같은 객체가 없으면 저장하고, 있으면 저장하지 않는다.

 

TreeSet

이진 탐색 트리로 구현. 범위 탐색과 정렬에 유리

이진트리는 모든 노드가 최대 2개의 하의 노드를 갖는다.

각 요소(Node)가 나무 형태로 연결

 

이진 탐색 트리

부모보다 작은 값은 왼쪽 큰 값은 오른쪽에 저장

데이터가 많아질수록 추가, 삭제에 시간이 더 걸림

 

HashMap

Map인터페이스를 구현한 대표적인 컬렉션 클래스

순서를 유지하려면, LinkedHashMap클래스를 사용하면 된다.

해싱 기법으로 데이터를 저장, 데이터가 많아도 검색이 빠르다.

Map인터페이스를 구현. 데이터를 키와 값의 쌍으로 저장

 

TreeMap

범위 검색과 정렬에 유리한 컬렉션 클래스

HashMap보다 데이터 추가, 삭제에 시간이 더 걸림

 

제네릭

컴파일 시 타입을 체크해 주는 기능

객체의 타입 안정성을 높이고 형 변환의 번거로움을 줄여줌

참조 변수와 생성자의 대입된 타입은 일치해야 한다.

ArrayList<Tv> list = new ArrayList<Tv>(); // ok
ArrayList<Product> list = new ArrayList<Tv>(); // error

제네릭 클래스 간의 다형성은 성립

List<Tv> list = new ArrayList<Tv>(); // ok
List<Tv> list = new LinkedList<Tv>(); // ok

매개변수의 다형성도 성립

extends로 대입할 수 있는 타입을 제한

 

제네릭 용어

Box <T> 제네릭 클래스 'T의 Box' 또는 'T Box'라고 읽는다.

T 타입 변수 또는 타입 매게 변수 (T는 타입 문자)

Box 원시 타입

 

제네릭 제약

타입 변수에 대입은 인스턴스 별로 다르게 가능

static 멤버에 타입 변수 사용 불가

배열 생성할 때 타입 변수 사용불가. 타입 변수로 배열 선언은 가능

 

와일드카드

하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능

<? extends T> : 와일드카드의 상한 제한 T와 그 자손들만 가능

<? super T> : 와일드 카드의 하한 제한 T와 그 조상들만 가능

<?> : 제한 없음. 모든 타입이 가능 

 

 

728x90

+ Recent posts