SELECT A.FOOD_TYPE
, A.REST_ID
, A.REST_NAME
, A.FAVORITES
FROM REST_INFO A
INNER JOIN (
SELECT FOOD_TYPE
, MAX(FAVORITES) AS FAVORITES
FROM REST_INFO
GROUP BY FOOD_TYPE
) B
ON A.FOOD_TYPE = B.FOOD_TYPE
AND A.FAVORITES = B.FAVORITES
ORDER BY A.FOOD_TYPE DESC
public class ExceptionOccurred {
// Checked Exception : RuntimeException을 상속받지 않은 클래스
// Unchecked Exception : RuntimeException을 상속받은 클래스
// throw : 강제로 예외를 발생시킬 수 있음 단, 발생시킨 예외를 catch문에서 잡을 수 있는 처리가 되어있지 않으면 오류 발생(catch문의 Exception은 모든 예외를 잡을 수 있음)
// throws : 예외 발생 시 자신을 호출한 상위 메소드로 예외를 던짐(특정 상위 메소드에서 예외를 한 번에 처리하는 경우가 있을 수 있음, 계속 throws로 던질 경우 최종적으로 JVM이 처리를 하게 되지만, 권장하지 않음)
// 중요 : RuntimeException을 상속받은 Unchecked Exception의 경우 throws는 아무 의미 없음, throws는 Checked Exception의 처리 방법 중 하나
public void method1() throws Exception {
// 이 메소드를 호출한 부분의 catch문에 Exception에 대한 에외 처리가 있어야 함
throw new Exception("강제로 예외 발생"); // 모든 예외를 잡을 수 있는 Exception의 경우 throws Exception 필수
}
// RuntimeException을 상속받은 NullPointerException
public void method2() {
// 이 메소드를 호출한 부분의 catch문에 Exception 또는 NullPointerException에 대한 예외 처리가 있어야 함
throw new NullPointerException("강제로 NullPointerException 발생"); // NullPointerException 발생
}
// RuntimeException을 상속받은 ArithmeticException
public void method3() {
// 이 메소드를 호출한 부분의 catch문에 Exception 또는 ArithmeticException에 대한 예외 처리가 있어야 함
System.out.println(3 / 0); // ArithmeticException 발생
}
// RuntimeException을 상속받은 NullPointerException 발생이므로 throws는 아무 의미 없음
public void method4() throws ArithmeticException {
throw new NullPointerException("강제로 NullPointerException 발생"); // NullPointerException 발생
}
// RuntimeException을 상속받은 NullPointerException 발생이므로 throws는 아무 의미 없음
public void method5() throws ArithmeticException {
String name = null;
System.out.println(name.length());
}
// ArithmeticException : 어떤 수를 0으로 나눌 때 발생(RuntimeException 상속)
// NullPointerException : NULL 객체를 참조할 때 발생(RuntimeException 상속)
// ClassCastException : 적절하지 못하게 클래스를 형 변환하는 경우 발생(RuntimeException 상속)
// NegativeArraySizeException : 배열의 크기가 음수 값인 경우 발생(RuntimeException 상속)
// IndexOutOfBoundsException : 리스트형 객체에서 선언되지 않은 요소를 가져오려고 할 때 발생(RuntimeException 상속)
}
public class ExceptionTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
String name = null;
ExceptionOccurred exceptionOccurred = new ExceptionOccurred();
try {
int nameLength = name.length(); // 1. NullPointerException에 걸리고 finally 실행
int num = 3 / 0; // 2. 코드 1이 없다면 ArithmeticException에 걸리고 finally 실행
exceptionOccurred.method2(); // 3. 코드 1, 2가 없다면 NullPointerException에 걸리고 finally 실행
exceptionOccurred.method3(); // 4. 코드 1, 2, 3이 없다면 ArithmeticException에 걸리고 finally 실행
} catch (NullPointerException e) {
System.out.println("NullPointerException : " + e.getMessage());
} catch (ArithmeticException e1) {
System.out.println("ArithmeticException : " + e1.getMessage());
} catch (Exception e) { // try문 실행에서 발생하는 예외 중 NullPointerException, ArithmeticException 외의 예외는 이곳에 걸림
System.out.println("Exception : 모든 예외를 잡을 수 있음");
} finally { // 무조건 실행시킬 코드를 적는 부분
System.out.println("무조건 실행되는 부분");
}
try {
int nameLength = name.length(); // 1. Exception에 걸리고 finally 실행
int num = 3 / 0; // 2. 코드 1이 없다면 Exception에 걸리고 finally 실행
exceptionOccurred.method1(); // 3. 코드 1, 2가 없다면 Exception에 걸리고 finally 실행
throw new Exception("강제 예외 발생"); // 4. 코드 1, 2, 3이 없다면 Exception에 걸리고 finally 실행
// exceptionOccurred.method2(); // 5. 코드 1, 2, 3, 4가 없다면 Exception에 걸리고 finally 실행
// exceptionOccurred.method3(); // 6. 코드 1, 2, 3, 4, 5가 없다면 Exception에 걸리고 finally 실행
} catch (Exception e) { // try문 실행에서 발생하는 모든 예외를 잡을 수 있지만, 어떤 문제로 발생하는 예외인지 확인이 불가하다는 단점이 있다.
System.out.println("Exception : 모든 예외를 잡을 수 있음");
} finally { // 무조건 실행시킬 코드를 적는 부분
System.out.println("무조건 실행되는 부분");
}
}
}
Checked Exception : RuntimeException을 상속받지 않은 클래스
Unchecked Exception : RuntimeException을 상속받은 클래스
throw : 강제로 예외를 발생시킬 수 있음 단, 발생시킨 예외를 catch문에서 잡을 수 있는 처리가 되어있지 않으면 오류 발생(catch문의 Exception은 모든 예외를 잡을 수 있음)
throws : 예외 발생 시 자신을 호출한 상위 메소드로 예외를 던짐(특정 상위 메소드에서 예외를 한 번에 처리하는 경우가 있을 수 있음, 계속 throws로 던질 경우 최종적으로 JVM이 처리를 하게 되지만, 권장하지 않음)
중요 : RuntimeException을 상속받은 Unchecked Exception의 경우 throws는 아무 의미 없음, throws는 Checked Exception의 처리 방법 중 하나
@Service
public class ArticleService {
@Autowired
private ArticleRepository articleRepository;
}
2. private final (생성자 주입 : Constructor Injection)
@Service
public class ArticleService {
private final ArticleRepository articleRepository;
public ArticleService(ArticleRepository articleRepository) {
this.articleRepository = articleRepository;
}
}
private final 방식이 더 좋은 이유
1. 순환 참조를 방지할 수 있다. (순환 참조 발생 시, Application이 구동되지 않는다.)
import java.util.LinkedList;
public class Solution {
// [1차] 캐시
// LRU(Least Recently Used) : 가장 오랫동안 참조되지 않은 페이지를 교체하는 방식
// 캐시가 가득 찼을 때, 가장 오랫동안 참조되지 않은 페이지를 찾아서 없애는 과정이 필요
public static int solution(int cacheSize, String[] cities) {
int answer = 0;
String city = "";
LinkedList<String> cache = new LinkedList<>();
if (cacheSize == 0) {
return cities.length * 5;
}
for (int i = 0; i < cities.length; i++) {
city = cities[i].toLowerCase();
if (cache.remove(city)) { // cache hit
cache.addFirst(city); // 제거 후 다시 추가하여 최신화
answer += 1;
} else { // cache miss
if (cache.size() == cacheSize) {
cache.removeLast(); // 가장 오래된 것 제거
}
cache.addFirst(city);
answer += 5;
}
}
return answer;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int cacheSize = 3;
String[] cities = {"Jeju", "Pangyo", "Seoul", "Jeju", "Pangyo", "Seoul", "Jeju", "Pangyo", "Seoul"};
System.out.println(solution(cacheSize, cities));
}
}
문제 해결을 위해 사용한 LinkedList에 대해 조금 더 알아보자
public void linkedListTest() {
// add, remove(실패 시 Exception 발생), element
// offer, poll(실패 시 null 리턴), peek
// LinkedList의 경우 add, remove, offer, poll을 (A)로 사용해 (A), (A)First, (A)Last가 가능하다.
// remove의 경우 remove("A")와 같이 지정 삭제가 가능하지만, poll의 경우 poll("A")와 같이 지정 삭제가 불가능하다.
// 1. add & remove & element
LinkedList<String> linkedList1 = new LinkedList<>();
linkedList1.add("A"); // linkedList1.element() => A
linkedList1.add("B"); // linkedList1.element() => A
linkedList1.add("C"); // linkedList1.element() => A
linkedList1.add("D"); // linkedList1.element() => A
System.out.println(linkedList1.element()); // A
linkedList1.remove(); // A
System.out.println(linkedList1.element()); // B
linkedList1.remove("C"); // C
System.out.println(linkedList1.element()); // B
// 2. add, addFirst, addLast & remove, removeFirst, removeLast & element
LinkedList<String> linkedList2 = new LinkedList<>();
linkedList2.add("A"); // linkedList2.element() => A
linkedList2.addFirst("B"); // linkedList2.element() => B
linkedList2.add("C"); // linkedList2.element() => B
linkedList2.addLast("D"); // linkedList2.element() => B
linkedList2.add("E"); // linkedList2.element() => B
System.out.println(linkedList2.element()); // B
linkedList2.removeFirst(); // B
System.out.println(linkedList2.element()); // A
linkedList2.removeLast(); // E
linkedList2.remove("C"); // C
System.out.println(linkedList2.element()); // A
// 3. offer & poll & peek
LinkedList<String> linkedList3 = new LinkedList<>();
linkedList3.offer("A"); // linkedList3.peek() => A
linkedList3.offer("B"); // linkedList3.peek() => A
linkedList3.offer("C"); // linkedList3.peek() => A
linkedList3.offer("D"); // linkedList3.peek() => A
System.out.println(linkedList3.peek()); // A
linkedList3.poll(); // A
System.out.println(linkedList3.peek()); // B
// linkedList3.poll("C"); // 지정 삭제 불가
// 4. offer, offerFirst, offerLast & poll, pollFirst, pollLast & peek
LinkedList<String> linkedList4 = new LinkedList<>();
linkedList4.offer("A"); // linkedList4.peek() => A
linkedList4.offerFirst("B"); // linkedList4.peek() => B
linkedList4.offer("C"); // linkedList4.peek() => B
linkedList4.offerLast("D"); // linkedList4.peek() => B
linkedList4.offer("E"); // linkedList4.peek() => B
System.out.println(linkedList4.peek()); // B
linkedList4.pollFirst(); // B
System.out.println(linkedList4.peek()); // A
linkedList4.pollLast(); // E
// linkedList4.poll("C"); // 지정 삭제 불가
System.out.println(linkedList4.peek()); // A
}