해결된 질문
작성
·
616
0
안녕하세요, 나도코딩 선생님...ㅎ 어제 나도코딩 자바편에서 남은 나머지 강의인 Thread 부분과 섹션 10. 제네릭스 (Java Collections Framework)를 다 듣고 완강한 다음 복습 중에 궁금증이 생겨 이렇게 질문을 남깁니다. 나도코딩 파이썬 강의를 완강한 이후로 또 다른 강의를 다 끝내고 나니 기분이 매우 좋습니다 ㅎㅎ
(1) 우선 add와 set과 관련된 질문입니다. Java documentation을 보면서 java.util.List에서 add는 object를 추가하는 것 외에도, add(int index, object e)를 통해 특정 위치(index)에 특정 객체(object)를 넣기도 가능하고, set도 마찬가지로 set(int index, object e) 형태로 같은 역할을 수행하는데, add와 set를 따로 나눈 것은 add는 단순하게 리스트 안에 객체를 넣는 것이 초점인 반면, set는 리스트 안에 들어있는 '기존 데이터들이 가진 순서 변경의 목적'이라서 그런건가요?
(2) 지금까지 제네릭스를 공부하고 제가 이해한 바로는 LinkedList랑 ArrayList 두 가지 리스트 모두 데이터 순서를 가지고, ArrayList는 데이터를 쓰고 저장하는 것은 알고리즘 시간 복잡도상 O(n)이기 때문에 속도가 느리지만, 읽기(O(1))는 빠른 반면, LinkedList는 데이터를 읽는 속도(O(n))는 느리지만, 리스트 중간에 데이터를 쓰고 저장하는 것(O(1))은 빠르다면, 이 둘의 특성들을 어느 때 쓰는 것이 가장 적합한가요?
또한 ArrayList와 LinkedList를 각각 '메모가 많은 공책', 예전에 있었던 '포털 사이트 실시간 검색어 순위'로 비유해서 개념을 이해하는 것도 괜찮을까요? - 제 스스로 이해를 돕기위해 나름 저만의 비유를 적어봤습니다...ㅎ
메모가 많은 공책 (ArrayList) : 책 한 장안에 많은 메모들을 볼 수 있어서 읽기는 빠르지만, 메모를 쓰려면 최소 6-7장은 넘겨야 한다.
실시간 검색어 순위 (LinkedList) : 순위가 주기적으로 (주로 1시간 단위) 변해서 자료들을 빨리 반영하기는 힘들지만, 실시간 순위인 만큼 빠른 자료 수집 및 추가는 확실하다.
(3) HashMap도 또한 일반적으로 어디에 가장 적합 한가요? 이를 테면 제가 원하는 특정 문자에, 특정 정수(Integer) 값을 할당하는 용도로 HashMap을 써도 괜찮을까요? 혹시 몰라 아래처럼 제 나름대로 코드를 적어봤습니다...ㅎ
... // 이미 import java.util.Map; 되어있음.
HashMap<String, Integer> gameMoves = new HashMap<>();
gameMoves.put("R", 0); // gameMoves.remove("R"); 이렇게 키도 삭제 가능
gameMoves.put("D", 1);
gameMoves.put("L", 2);
gameMoves.put("U", 3);
System.out.println(gameMoves.size()); // 4
그리고 위의 예시 처럼 remove("R");을 통해 키 값을 없애면 (HashMap gameMoves에 저장된 String), HashMap gameMoves의 value값은 그대로 살아있는가요? 아니면 null로 처리가 되나요? 스스로 공부하면서 얼핏 본 바로는 key값이 사라지더라도 map의 value는 계속해서 쓸 수 있다고 본거 같은데, 이 부분도 확실하게 제 스스로 짚고 넘어가고 싶습니다! 추가적으로 강의를 들으면서 제네릭스 전반적인 개념을 제 나름대로 그림도 그려가면서 이해를 해봤습니다...ㅎ 제대로 이해했는지 알고 싶어서요...ㅎ 앞으로도 강의 많이 찍어주세요!...ㅎ 항상 감사합니다!
답변 1
1
안녕하세요?
먼저 파이썬에 이어 자바도 완강하신 점을 진심으로 축하드립니다. 정말 대단한 노력이자 열정입니다 😊 질문에 대해서는 아래와 같이 답변 드립니다.
(1) List 는 데이터의 순서를 보장하며 중복을 허용합니다. 그래서 add 를 통해 원하는 위치에 값을 추가할 수 있습니다. Set 는 데이터의 순서를 보장하지 않으며 중복을 허용하지 않습니다. 그래서 add 를 통해 값을 추가하되 원하는 위치에 값을 추가할 수는 없습니다. set(int index, object e) 또는 add(int index, object e) 가 제공되지 않을텐데, 제가 잘못 알고있는 부분이 있다면 공식 문서의 링크를 보내주시면 확인해보겠습니다.
(2) LinkedList 와 ArrayList 모두 List 에 속하며 데이터의 순서를 보장하며 중복을 허용합니다. 둘의 구현 방식이 다르기 때문에 말씀하신대로 조회 및 삽입/삭제 작업에서의 성능 차이가 발생할 수 있는데요. 과거에 다른 분이 질문해주신 내용을 참고하시면 보다 수월하게 이해하실 수 있을 것 같아 링크를 남기니 확인해주세요 🙏
👉 https://www.inflearn.com/questions/778338
위 링크 내용의 결론은,
ArrayList 는 데이터를 조회하는 작업이 많은 경우에 적합합니다.
LinkedList 는 데이터 삽입/삭제 작업이 많은 경우에 적합합니다.
하지만 현실적으로는 대부분의 경우 ArrayList 를 사용하시면 크게 문제는 없습니다. '어떤 것을 쓰면 좋을지 잘 모르겠다' 하시는 경우 큰 고민하지 마시고 ArrayList 의 사용을 권장드립니다.
작성해주신 예제는 아래와 같이 바꿔봤습니다.
1. 메모가 많은 공책(ArrayList) : 공책 한 장 안에 많은 메모들을 볼 수 있어서 읽기도 빠르고 페이지가 있으니 찾기도 빠르지만, 중간에 누락된 메모가 있어서 삽입해야 하는 경우 그 페이지 및 이후에 작성된 모든 메모를 지우고 한 장씩 뒤로 옮겨 적은 다음에 누락된 메모를 삽입해야 한다.
2. 실시간 검색어 순위(LinkedList) : 순위가 주기적으로 변하지만 중간에 새로운 순위 항목이 추가되더라도 그 이전 순위, 그 이후 순위와 선만 하나 연결해주면 되므로 다른 순위 항목들을 삭제하거나 이동하는 작업 없이 빨리 반영할 수 있다.
(3) HashMap 은 (Key, Value) 쌍으로 이루어진 형태입니다. Key 값은 문자나 숫자 등 다양한 형태가 될 수 있으나 중복을 허용하지 않으며 하나의 Key 에는 반드시 그에 상응하는 Value 가 있게 됩니다. 실생활에서는 본인 확인을 위해 사용되는 주민등록번호, 학번 또는 전자제품이 가지는 시리얼 넘버 등이 예시가 될 수 있습니다. 이들은 모두 고유의 값이기 때문에 Key 로 사용할 수 있는 거죠. 말씀하신 것처럼 게임에서 사용되는 버튼에 따른 값에도 HashMap 을 이용할 수 있겠네요.
HashMap 에서 특정 Key 를 삭제하고 나서도 Value 를 쓸 수 있다는 것은 아래와 예시와 같이 map 에 추가하기 위해 생성된 객체를 다른 참조변수가 참조하고 있는 경우인 것 같아요.
import java.util.*;
public class Sample {
public static void main(String[] args) {
HashMap<Integer, A> map = new HashMap<>();
map.put(1, new A("test")); // A 객체 생성
A newA = map.get(1); // A 객체 참조
System.out.println(newA.name); // 참조변수로 접근
map.remove(1); // Key 값 삭제
System.out.println(newA.name); // 여전히 참조변수로 접근
}
}
class A {
public String name;
public A(String name) {
this.name = name;
}
}
HashMap 에서는 key 가 삭제되더라도 해당 객체를 참조하고 있는 변수가 있다면, 그래서 접근이 가능하다면 한 번씩 불필요한 쓰레기들을 주워가는 역할을 하는 가비지 컬렉터(GC : Garbage Collector)에 의해 삭제되지는 않습니다. 그러나 HashMap 에서 key 를 삭제한다는 것은 보통 value 도 함께 삭제되기를 원하므로 이런 식의 코드가 권장되지는 않습니다 😊
감사합니다.
답변 감사합니다 ㅎㅎ 사실 제가 이전에 쓴 글에서 set이랑 add를 언급한 것은, java.util.List package에서 쓰인 add 및 set메소드 void add (int index, E element)와, E set(int index, E element)의 차이를 알고 싶어서 쓴 글이었습니다. (지금 다시 보니 완전히 잘못 적었네요 ㅎㅎ ㅠㅠ, 혹시 몰라서 사진도 같이 올립니다.)
이 링크가 제가 참고한 사이트이구요...ㅎ:
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/List.html
그래도 덕분에 제가 몰랐던 부분도 파악할 수 있었고, Collections Framework에서 List와 Set을 자세하게 알 수 있어서 좋았습니다. 감사합니다 ㅎㅎㅎ