S1U9 [Java] 컬렉션(Collection) 회고
[열거형]
🍟 Enum 타입. 여러 상수들을 편하게 나열해서 선언해둔다. 타입 안정성을 보장하고 가독성이 좋아진다. 상수이므로 대문자를 사용해야하고 자동으로 0부터 정수값이 순서대로 할당된다.
enum 타입을 사용해서 응답값을 관리했던 기억이 있다. enum 안에서 필드도 따로 관리했는데 그런 내용은 학습하지 않았다. enum은 잘 사용하면 타입 관리가 안정적이고 관련된 값들을 관리하는 데 편리하다. switch문에서도 enum은 빛을 발할 수 있는 것 같다. 그런데 레퍼런스 없이 구현을 하려고 하면 어려울 것 같긴 하다. enum을 적용해서 코드를 한 번 작성해보고 싶다는 생각이 든다.
[제네릭]
🍟 타입을 추후에 지정해서 코드가 일정 데이터 타입에 얽매이지 않게 한다. 제네릭 클래스를 인스턴스화할 때 참조 변수의 타입을 명시해주면 클래스 내 제네릭이 해당 타입으로 설정된다. GenericClass<String>. static 변수는 선언할 수 없다.
특정 클래스를 상속받은 타입으로만, 또는 특정 인터페이스를 구현한 타입으로만 제한할 수 있다. GenericClass <T extends Parent>.
특정 메서드만 제네릭 타입으로 설정할 수도 있다. 이는 클래스 제네릭과 별개이다. (제네릭 메서드) 매개변수를 제네릭 타입으로 설정해놓을 수 있다. 그렇기 때문에 메서드를 정의할 때 특정 타입의 메서드를 사용하는 것이 불가능 하다. (String의 length()등), Object의 메서드는 가능하다. 모든 객체의 최상위 계층이기 때문이다.
와일드 카드를 통해 타입의 상한/하한 제한이 가능하다. <? extends Parent> Parent 및 상속 받은 하위 클래스 타입만 (상한제한), <? super Child> Child 및 그 상위 클래스 타입만 (하한제한) 명시하도록 설정한다.
예전에 가장 난해했던 부분이 제네릭이었다. T,K,V... 이렇게 제네릭 기본 개념부터 세세히 공부할 수 있어서 정말 좋았다. 이것저것 만들어보고 제네릭 클래스와 static, 제네릭 메서드와 static 등등 테스트를 해보았는데 그렇게 하면서 더 이해를 빨리 할 수 있었다. 와일드카드 같은 경우에는 아직 활용해보지 못 했지만 그 관계를 설계하는 것부터 복잡할 것 같다. 특히 타입을 하한제한 해두는 경우는 어떤 게 있을지 잘 모르겠다.
아 특히 T와 E가 구분이 잘 안 됐다. 테스트를 해보면서도 차이점을 잘 이해하지 못 했는데 포스팅을 하면서 찾아보니 E는 element를 뜻하는 만큼 배열에 들어가는 요소 타입을 지정해주는데에 쓰이는 모양이다. 이렇게 또 하나 알게 되었당
[예외처리]
🍟 예외(Exception) 발생으로 인한 비정상적인 동작을 미리 방지하는 코드를 작성해둔다. 모든 예외의 최상위 클래스는 Exception. 그 아래로 런타임 예외와 그 외 일반 예외로 구분된다. 발생이 예상되는 예외 객체를 통해 예외처리를 하면 된다.
try-catch를 이용해 예외처리를 할 때, try 블럭에는 예외 발생 가능성이 있는 코드를, catch 블럭에는 예외 발생 시 실행할 코드를, finally에는 예외 발생과 상관없이 실행될 코드를 작성한다.
throws는 예외를 전가한다. 현재 메서드가 호출당한 쪽으로 에러를 전가해버리므로, 그 쪽에서 처리를 해두어야 한다.
throw는 예외를 고의로 발생시킨다.
맨 처음 예외처리에 대해 배울 때는 try는 실행할 코드, catch는 예외를 처리할 코드. 라고 하고 무조건 catch(Exception e)를 지정해 e.printStackTrace()만 주구장창 사용했던 기억이 있다. throws는 그냥 무책임한 거라며 깊게 배우지 못했다. 그런데 예상되는 예외에 따라 Exception 객체를 다르게 해서 구체적으로 처리할 수 있고, catch문을 여러 개 작성해도 된다는 사실을 알 수 있어서 좋았다. throws는 무책임하다ㅋㅋ라고만 배웠지만, 자신을 호출한 쪽으로 에러를 도로 던져주는 개념이라고 생각하니 이해하기 수월했다.
그나저나 종종 API가 throws로 예외처리를 개발자에게 위임하는 경우는 이해가 된다. 예외를 전달해서 그 예외를 알려주고 그 덕에 올바른 예외처리를 할 수 있을테니 말이다. 그런데 코드를 작성하면서 고의로 예외를 발생시키는 상황(throw)은 어떤 게 있는 걸까? 정해둔 기준에 적합하지 않은 요청값이 들어왔을 때 그에 대한 메세지를 전달하기 위해서일 것 같다. 더 자세히 공부해봐야겟다.
추가) throw는 예외 처리 할 때 주로 사용한다. 예상한 대로 올바르지 않은 값이 들어왔을 때 뿐만 아니라(이 때는 DTO 유효성 검사에서 저절로 MethodArgumentNotValidException을 던져준다.) 찾고자 하는 객체가 없을 때나 클라이언트로부터 비롯된 오류일 때 등등 어떤 에러인지를 명시해주기 위해 throw로 예외를 던지고 Exception handler를 정의해서 처리해주는 방향으로 학습했다.
[컬렉션 프레임워크]
🍟 특정 자료구조에 데이터를 묶어서 저장할 수 있는데, 그 데이터들을 쉽게 관리할 수 있도록 컬렉션 프레임워크가 제공된다. 주요 인터페이스는 List, Set, Map이 있다.
List는 index가 존재하고, 그렇기 때문에 순서가 유지되고 중복 또한 가능하다.
주요 구현 클래스는 ArrayList, LinkedList가 있다. ArrayList는 연속적인 공간에 데이터가 저장된다. 검색, 순차적인 데이터 추가와 삭제는 빠르지만 중간에 있는 데이터를 조작하려면 효율이 좋지 않다. LinkedList는 불연속적으로 저장되어있지만 서로 연결되어있다. 이전/다음 노드를 가리키는 데이터를 가지고 있다. 순차적으로 접근해야하기 때문에 검색은 비교적 느리지만 중간 데이터 삽입/삭제는 효율이 좋다. 빈번한 데이터 변경이 있을 때는 LinkedList가 유리하다.
Set은 데이터 순서가 유지되지 않고 중복도 안 된다.
HashSet 데이터 삽입 시 hashCode()와 equals()를 통한 데이터 중복검사가 이루어진다. TreeSet은 이진 탐색트리 형태로 데이터를 저장한다. 그래서 데이터가 정렬되어 저장되므로 검색에 특화되어있다. 왼쪽노드<부모노드<오른쪽노드 로 정렬된다.
Map은 key와 value로 이루어진 Entry로 구성된다. 순서는 유지되지 않는다. key는 중복될 수 없지만, value는 중복되어도 상관없다.
해싱을 사용한 HashMap은 많은 양의 데이터 검색에 유리하다. 다만 List와 Set과 달리 Collection 인터페이스를 구현하지 않기 때문에 Iterator 사용은 불가능하다. keySet을 사용하면 key 목록이 Set으로 반환되기 때문에 그 때는 Iterator를 사용한 순회가 가능하다.
흥미로운 챕터였다. 왜냐하면 예전에는 기초적인 뼈대를 알지 못하고 key를 쓰려면 HashMap을 사용했었고, 뭔가를 목록에 담아야 할 때면 ArrayList에 담고, Set은.. 사용할 일이 많이 없었다. 이렇게 그냥 무지성으로 많이 사용해왔던 것 같은데ㅎㅎ;; 인터페이스 구조부터 각 컬렉션들의 특징까지 공부할 수 있어서 정말 좋았다. Iterator도 잘 모르는 개념이었는데 이번 기회에 확실하게 배워둘 수 있어서 좋았다. 어떤 경우에 어떤 컬렉션을 사용하는 게 적합할 지는 더 살펴보고 고민해봐야겠지만 이번 챕터를 공부하면서 자료구조 자체에 대한 개념은 확실히 잡고 가는 것 같아 기쁘다.
추가) 자료구조에 따른 시간복잡도도 제각각이기 때문에 문제 컨디션에 따라 자료구조를 잘 선택하는 것도 하나의 미션이다.
📜 Unit 9. [Java] 컬렉션을 마치고!
처음에는 제대로 개념을 잡아두지 않았는데, 실무를 하면서는 또 정말 많이 사용하는 내용들이었어서 개념을 잡는 게 중요했었다. 그래서 집중해서 공부했던 유닛이다. List와 ArrayList는 어떤 차이이지 하는 무지한 생각들을 해왔었기 때문이다. 내가 스스로 일하면서 많이 부족하다고 생각했던 것들에 대한 이유는 다 이런 것들인 것 같다. 기초를 잡지 못하고 주먹구구식으로 사용하면서 깊게 알아보려고 하지 않았던 것들 말이다. 그래서 레퍼런스 없이는 스스로 코드를 만들어내기 힘들고 구조와 특성을 모르니 그것을 리팩토링 하는 것은 당연 무리였을 것이다. 그래도 나는 거기서 부족함을 느끼고 새로 배우기 위해 시작한 모든 것들이 참 잘 되어가고 있다는 생각이 든다. 그런 생각을 가장 많이 들게 해주는 유닛이었다. 옛날 생각도 가장 많이 나는 유닛이었다. 그런데 어딜 가든 아무래도 속성으로 자바를 진행하다보니 역시 나 스스로 해보고 겪어보지 않으면 익히는 데에 많이 어려움이 있을 것이라는 생각은 한다. 이건 매 유닛마다 하는 생각인 것 같다.. 직접 해보는 데에 시간을 조금 더 많이 투자할 수 있도록 하고 싶은데 생각보다 어렵다. 또 괜시리 마음이 조급해진다.😨 무튼 컬렉션 회고 끝~