Real Vectorism. 훨씬 더 입체적으로...
Collection 개념 정리 본문
List, Set, Map 개념이 있다.
1. List
int index 를 통해 번호로 접근하면서 데이터를 삽입/조회/제거 할 수 있다.
최초 데이터는 0번 인덱스부터 채워지고, 중간에 항목이 제거될 경우 앞으로 당겨진다.
예:
@Test
public void arrayListTest() {
List<String> stringList = new ArrayList<>();
stringList.add("0");
stringList.add("1");
stringList.add("2");
stringList.add("3");
stringList.add("4");
stringList.add("5");
stringList.add("6");
stringList.add("7");
stringList.add("8");
stringList.add("9");
System.out.println("before remove: " + stringList);
stringList.remove(3);
System.out.println("after remove: " + stringList);
}
0, 1, 2, 3, 4, 5, 6, 7, 8, 9 에서 3번 인덱스의 항목을 제외할 경우
3번 인덱스의 항목을 제거한 다음, 뒤에 있는 항목은 빈틈이 없도록 앞으로 당긴다.
따라서, 한번 삭제한 인덱스라고 해서 그 자리가 null 로 유지되는 것은 아니다.
또한, 3번 인덱스에 null 을 넣더라도 null 값이 3번 인덱스 항목으로 유지된다.
이 상태에서 null 값이 있는 3번 인덱스 항목을 삭제하면 null 값 역시 삭제한 후 뒷 데이터들은 모두 앞으로 빈틈없이 메운다.
사용방법은 간단하다.
List<T> list = new ArrayList<T>();
List 인터페이스는 가변배열로써 구현되어있어야 하는 기본적인 기능들을 구비해놓고 있다.
List 인터페이스를 사용하게 될 경우 그 안에는 ArrayList, LinkedList 를 사용할 수 있다.
ArrayList 는 데이터를 순서를 선형으로 관리할 수 있다.
// 데이터를 List 객체 안에 삽입
List<String> stringList = new ArrayList<>(); // new ArrayList<String>() 도 가능하나 1.7 버전부터는 다이아몬드 연산자(<>)를 사용 가능
stringList.add("1"); // 0 번 인덱스에 "1" 데이터가 삽입
stringList.add("3"); // 1 번 인덱스에 "3" 데이터가 삽입
stringList.add("5"); // 2 번 인덱스에 "5" 데이터가 삽입
stringList.add("7"); // 3 번 인덱스에 "7" 데이터가 삽입
// 데이터를 List 객체 안에 덮어쓰기
String value = stringList.get(0); // "1"
value = "2";
stringList.set(0, value); // 0 번 인덱스 자리에 기존데이터("1")가 아닌 새로운데이터("2")를 덮어쓰기
// 단, List 변수를 만들고나서 데이터를 삽입/적재한 다음 제공만 하는 유형이라면 set 메소드는 그다지 활용도가 낮거나 없음
// 데이터를 List 객체 안에서 제거
stringList.remove(0); // "1"
System.out.println(stringList); // "3", "5", "7"
// 데이터를 순차적으로 조회(1)
for(int index=0 ; index<stringList.size() ; index++) {
String stringItem = stringList.get(index);
System.out.println(stringItem);
}
// 데이터를 순차적으로 조회(2)
for(String stringItem: stringList) {
System.out.println(stringItem);
}
// 데이터를 순차적으로 조회(3), 이는 생각보다 잘 안씀
stringList.forEach(stringItem -> {
System.out.println(stringItem);
})
LinkedList 는 순서를 통한 전체 데이터 접근보다는 바로 앞 데이터, 바로 뒤 데이터만을 획득하는데 유리하다.
자주 써보지는 않았는데 일단 적어도 확실한건
new LinkedList<>();
// 이렇게 선언해도
List<String> stringList = new LinkedList<>();
// 이렇게 선언한 것이라면 그냥 List 객체를 사용하는거지 LinkedList 객체를 사용하는것이 아님
// LinkedList 객체의 기능을 이용하기 위해서는
LinkedList<String> stringList = new LinkedList<>();
LinkedList 객체의 기능을 사용하기 위해서는 변수 타입을 LinkedList 로 사용을 해야함
어쨌거나 나는 자주 사용할 일은 없을것으로 보임
특징은 select 보다는 insert/delete 에 특화된 성능이라던가... 잘 모름
2. Set
Set 은 순서 개념이 없다. 그래서 동일 데이터가 여러개 들어가면 이를 구분할 방법이 없기 때문에 중복 데이터는 1개를 유지하게 된다.
HashSet<String> stringSet = new HashSet<>();
stringSet.add("0");
stringSet.add("0");
stringSet.add("0");
stringSet.add("0");
stringSet.add("1");
stringSet.add("1");
stringSet.add("1");
stringSet.add("2");
stringSet.add("2");
stringSet.add("3");
System.out.println("hashSet: " + stringSet);
이렇게 굴려보면
삽입/적재 한 데이터가 10개인데도 불구하고 4개만 들어있는것을 볼 수 있다.
그렇다면 순서 개념이 없기 때문에 당연히 색인번호(index)가 불필요해지며, 삭제 또한 하나의 데이터 뿐이기 때문에 갯수 상관없이 그냥 바로 삭제가 이루어진다.
그런데 순서개념이 없다면서? 왜 적재한 순서대로 0, 1, 2, 3 이 찍힌거임?
HashSet<String> stringSet = new HashSet<>();
stringSet.add("3");
stringSet.add("2");
stringSet.add("2");
stringSet.add("1");
stringSet.add("1");
stringSet.add("1");
stringSet.add("0");
stringSet.add("0");
stringSet.add("0");
stringSet.add("0");
System.out.println("hashSet: " + stringSet);
add 를 역순으로 해도 0부터 나온다. 그냥 compare 기능이 있다고 생각하면 된다.
안타깝게도 나는 TreeSet 을 사용해본 적은 없다. HashSet 만 사용을 해봤을 뿐.
3. Map
Map 도 마찬가지로, HashMap 만 사용을 했을 뿐 TreeMap, LinkedHashMap 까지는 사용해본 적은 없다. 대충 LinkedHashMap 은 순서가 보장된다고까지만 들어봤다.
Map<String, Integer> stringValueMap = new HashMap<>();
stringValueMap.put("0", 3);
stringValueMap.put("0", 2);
stringValueMap.put("0", 1);
stringValueMap.put("0", 0);
stringValueMap.put("1", 3);
stringValueMap.put("1", 2);
stringValueMap.put("1", 1);
stringValueMap.put("2", 3);
stringValueMap.put("2", 2);
stringValueMap.put("3", 3);
System.out.println("stringValueMap: " + stringValueMap);
Map 의 특징은 key 를 통해 value 를 가져온다는 방식인데, 이 때문에 List, Set 과는 달리 타입 패러미터가 K, V 로 지정되어있다. 그래서 HashMap 또는 다른 종류의 Map 을 사용할 때는 반드시 타입 패러미텨를 2종류를 사용해야 한다. (단, K 와 V 로 구분되는 타입 패러미터 간의 구분관계는 불필요하다. 굳이 String 키 타입을 사용한다고 해서 Object 로만 써야한다는 강제적이거나 권장되는 타입 상관관계는 없다는 뜻.)
여기서 짱구를 잘 굴려보면
Map<Integer, String> 은 결국 List<String> 이 아니냐고 물을 수 있다. 그러나
Map<String, Integer> stringValueMap = new HashMap<>();
stringValueMap.put("1", 1);
stringValueMap.put("10", 10);
stringValueMap.put("100", 100);
stringValueMap.put("1000", 1000);
System.out.println("stringValueMap: " + stringValueMap);
순서를 보장하고 앞 자리의 빈공간이 있다면 뒷 항목들을 순차적으로 앞으로 당겨 빈 공간을 없애버린다는 특성을 가진 List 와는 다르게 Map 은 키가 순서 없이 고유하며, Key 값이 함부로 변동되어버리면 값을 찾을 수 없게 되어버리기 때문에 List 처럼 사용할 수가 없게 된다. 애초에 Map 의 Key 타입이 무조건 Integer 가 아닌 String, 더 나아가 HttpServerRequest 나 HttpSession 까지도 들어갈 수 있다는 것을 염두해야한다. 이들은 대소크기를 판별할 만한 객체가 아닌 타입이라는 것을 알아두자.
// 생성하는 방법 (1)
HashMap<String, Object> resultMap = new HashMap<>();
resultMap.put("result", true);
resultMap.put("data", new ArrayList<>());
// 생성하는 방법 (2), Java9 이후부터만 사용 가능
HashMap<String, Object> resultMap = Map.of("result", true, "data", new ArrayList<>());
// 생성하는 방법 (3), 데이터가 단건인 객체를 생성할 때만 사용 가능
// 해당 방법은 단건 데이터만 넣는것이 불가능하며, 이렇게 생성된 객체는 immutable 특성을 가지기 때문에 변경할 수가 없다.
// immutable: (형용사) 변하지 않는, 불변한
HashMap<String, Object> resultMap = Collections.singletonMap("result", true);
정리하자면
1. List 는 순서보장이 요구되는 경우에 사용한다.
게시판 기능을 구현한다고 가정할 때, 작성시간에 따라 최신글이 첫번째로 오는 조건이 요구될 경우에는 List 를 검토할 수 있다.
2. Set 은 존재/종북의 판단이 요구되는 경우에 사용한다.
주의해야할 점은 Set 에서 가능한 기능은 모두 List 에서 가능하다. 그러나 Set 에서 요구되는 기능을 List 는 만족하지 못하는 경우가 있을 수 있다는 점이다. 사용자의 정보보다는 시스템에서 고유하게 생성한 값과 관련된 기능을 처리할 때 쓰인다.
3. Map 은 데이터 그 자체를 관리/취급하는 기능이 요구되는 경우에 사용한다.
Key/Value 형태는 돌려서 말하자면 한 클래스에 변수가 있고, 그 변수에 특정 값이 정의되어있는 그 상태 그대로를 변수화 시킨것이라고 보면 된다. 변수명이 곧 key 이고, 변수값이 value 인 형태를 객체로 취급하는 형태이며, 이를 통신 형태로 주거니 받거니 할 때 Java 의 클래스보다는 조금 더 유연한 형태로 다룰 수 있도록 사용하기 위함이라고 생각하면 편하다. (단, 이것이 정답은 아니다.)
'Java (based by 1.8, Lambda)' 카테고리의 다른 글
여태 한번도 안해봐서 몰랐던 사실 (0) | 2021.08.09 |
---|---|
치킨을 Java 볼까 : 작성분 링크 총집 (0) | 2020.06.02 |
아주 간단한 Collectors.groupingBy 사용방법 (0) | 2020.05.28 |
진짜 지랄맞다 (0) | 2020.05.11 |
자바 10 이상의 버전에서 사용이 가능한 var에 대한 학습 (0) | 2020.04.20 |