제육's 휘발성 코딩
Published 2021. 10. 10. 10:03
[JAVA] - Collection 🔷 Java/Basic
반응형

Collection Framework

image

  • 값들을 담아주는 형태 - NonPrimitive 타입만 저장이 가능
    • Primitive 형을 Wrapper 클래스를 통해 Boxing - Integer
  • Collection(List, Set), Map 으로 나뉜다. (인터페이스)
  • Hash : 값이 중복될 수 없는 유니크한 특징
  • Tree : 이진 트리 순회 방법 중 중위 순회 방식

Collection

  • 기본 자료형이나 자료형의 그룹 형태로 저장 및 관리를 해주는 인터페이스
  • List (순서 o, 중복 o) - ArrayList, LinkedList, Vector, Stack
  • Set (순서x, 중복 x) - HashSet, SortedSet, TreeSet

ArrayList

  • Collection에서 제일 많이 사용 하는 리스트
  • 삽입, 삭제가 많을 경우는 LinkedList를 사용 하자.
ArrayList<String> data = new ArrayList<>();
data.add("A");
data.add("B");
data.add("C");
data.set(2, "T");
for (String idx : data) System.out.println(idx);

[출력]
A
T
C
  • set : 지정한 인덱스의 값 변경
data.get(0); // 0번 인덱스 꺼내기
data.remove(2); // 2번 인덱스 삭제
data.removeAll(data); // 모두 삭제
data.size(); // 리스트 크기
  • removeAll : 지정한 컬렉션의 모든 요소를 제거

LinkedList

  • 양방향 포인터 구조로, 각각마다 인접하는 노드를 관리한다.
  • 큐나 스택을 구현하는데 자주 쓰인다.
LinkedList<Integer> queue = new LinkedList<>();
queue.offer(5);
queue.offer(11);
queue.offer(13);
queue.offer(12);
System.out.println(queue);
System.out.println(queue.poll()); // 값을 반환 후 삭제
System.out.println(queue.peek()); // 값을 반환 후 그대로
System.out.println(queue);

ListIterator<Integer> it = queue.listIterator();
if (it.hasNext()) {
    System.out.println(it.next());
    System.out.println(it.next());
    System.out.println(it.nextIndex());
    System.out.println(it.previous());
    System.out.println(it.previous());
}
[출력]
[5, 11, 13, 12]
5
11
[11, 13, 12]
11
  • ListIterator 를 사용하면 이전의 값, 인덱스를 알 수 있다.

Stack

  • LIFO - 후입선출법
Stack<String> stack = new Stack<>();
stack.push("dog");
stack.push("cat");
stack.push("lion");
System.out.println(stack.size());

while (!stack.empty()) {
    System.out.println(stack.pop());
}
System.out.println(stack.size());

[출력]
3
lion
cat
dog
0
  • !stack.empty() : 스택의 공간이 비어있지 않으면

Iterator

  • Collection에 대한 반복자 , JDK 1.2부터 제공
  • for 문으로 차례대로 조회하는 것을 Iterator로 쉽게 조회할 수 있다.
List<String> list = new ArrayList<>();
list.add("dog");
list.add("cat");
list.add("lion");

list.forEach((x) -> System.out.println(x)); // 람다식

Iterator<String> it1 = list.iterator(); //Iterator 이용
while (it1.hasNext()) {
    String item = it1.next();
    if ("cat".equals()) it1.remove(); // 제거 remove   
    System.out.println(item);
}

Iterator<String> it2 = list.iterator(); // Iterator 와 람다식 활용
it2.forEachRemaining((x) -> System.out.println(x));

Iterator<String> it3 = list.iterator(); // Iterator 와 참조 메서드 활용
it3.forEachRemaining(System.out::println);

Collections.sort(list);
Collections.sort(list, Collections.reverseOrder());
  • 만약 Collection 정렬에서 class 객체가 배열로 들어오게 되면 Comparable 인터페이스를 사용
  • class A implements Comparable
  • 람다식은 JDK 1.8부터 사용 가능

Set

  • 순서 X , 중복 X의 특징을 갖고 있는 인터페이스
  • HashSet 과 TreeSet 이 존재
ArrayList<String> list2 = new ArrayList<>();
list2.add("a");
list2.add("a");
list2.add("b");
list2.add("b");
list2.add("c");
System.out.println(list2);

HashSet<String> list3 = new HashSet<>();
list3.addAll(list2);
System.out.println(list3);
list3.add("c");
list3.forEach(System.out::println);

System.out.println("<<Spliterator>>");
Spliterator<String> names = list3.spliterator();
names.forEachRemaining(System.out::println);

[출력]
[a, a, b, b, c]
[a, b, c]
a
b
c
<<Spliterator>>
a
b
c
  • HashSet에 중복 제거 확인
  • addAll 을 통해 컬렉션 복사가 가능하다.
var trs = new TreeSet<String>();
trs.addAll(list2);
trs.add("f");
System.out.println(trs);
System.out.println(trs.ceiling("e")); //e 보다 크거나 같은 값 중 제일 가까운 값
System.out.println(trs.floor("e")); // e 보다 작거나 같은 값 중 제일 가까운 값
System.out.println(trs.higher("b"));
System.out.println(trs.lower("b"));
System.out.println(trs.first()); // 첫번째 값 출력
System.out.println(trs.last()); 
System.out.println(trs.pollFirst()); // 첫번째 값 반환 후 삭제
System.out.println(trs.pollLast()); 
System.out.println(trs);

Iterator<String> it = trs.descendingIterator(); //내림차순 iterator

[출력]
[a, b, c, f]
f
c
c
a
a
f
a
f
[b, c]
  • TreeSet 주요 메서드 사용
  • TreeSet 은 이진 트리로 데이터를 저장 (자식 노드는 부모 노드보다 각각 작고 커야 한다.)
  • 이동 시간은 많이 걸리지만, 검색 시간이 빠른 장점이 있다.
  • 검색 시 중위 순회 탐색 사용 (왼쪽 자식 - 부모 노드 - 오른쪽 자식 노드 순서 방문)

Map

  • Key 와 Value의 단위로 저장되는 형태
  • HashMap, HashTable, TreeMap

HashMap

HashMap<String, Integer> map = new HashMap<>();
map.put("Java", 1);
map.put("C", 2);
map.put("C++", 3);
map.put("Python", 4);

Map beforeMap = (Map) map.clone(); //전체 복사
System.out.println(beforeMap);

Set<String> keys = map.keySet(); // key 만 복사
System.out.println(keys);

System.out.println("==== keys 출력");
keys.forEach(x -> System.out.println(x));
map.keySet().forEach(System.out::println);

if (map.containsKey("Python")) {
    System.out.println("Key : Python 값이 있습니다.");
    map.remove("Python");
    System.out.println(map);
}
if (map.containsValue(1)) System.out.println("Value : 1이 있습니다.");

map.computeIfPresent("Java", (String key, Integer value) -> ++value);
map.computeIfPresent("C", (String key, Integer value) -> --value);
System.out.println(map);

[출력]
{Java=1, C++=3, C=2, Python=4}
[Java, C++, C, Python]
==== keys 출력
Java
C++
C
Python
Java
C++
C
Python
Key : Python 값이 있습니다.
{Java=1, C++=3, C=2}
Value : 1이 있습니다.
{Java=2, C++=3, C=1}
  • HashMap 은 기본적으로 put, get() 메서드를 사용하여 넣고 뺀다.
  • computeIfPresent() 메서드는 조회된 키와 값을 인자로 함수의 결과 값에 반영할 수 있다.
  • compute() 도 동일하지만, 키가 존재하지 않을 경우 오류 발생
  • 순서 보장을 받고 싶을 땐 LinkedHashMap을 사용하면 넣은 순서대로 보장 된다.
  • 키 목록을 얻어올 때는 keySet을 사용한다.
    • Object[] arr = hash.keySet().toArray();
HashMap<String, Integer> hash = new HashMap<>();
hash.put("A", 3);
String[] ranks = new String[3];
ranks[0] = "A";
ranks[1] = "B";
ranks[2] = "C";

for (String rank : ranks){
    hash.put(rank, hash.getOrDefault(rank, 0));
}
System.out.println(hash);
  • hashMap 은 같은 key 값을 추가로 넣을 경우 덮어 씌운다. 즉, value가 마지막에 들어온 것으로 변경
  • 기존의 value를 유지하고 싶으면 getOrDefault(key, default 값을 지정)을 사용하자.
  • Value를 기준으로 내림차순
    • List keySetList = new ArrayList<>(arr.keySet());
    • Collections.sort(keySetList, (o1, o2) -> (arr.get(o2).compareTo(arr.get(o1))));

TreeMap

HashMap<String, String> has = new HashMap<>();
has.put("001", "연필");
has.put("002", "지우개");
has.put("003", "샤프");
has.put("004", "필통");
has.put("005", "샤프심");

TreeMap<String, String> treeMap = new TreeMap<>();
treeMap.putAll(has);
System.out.println(treeMap);
System.out.println(treeMap.ceilingEntry("000")); // key-value 형태로 출력
System.out.println(treeMap.ceilingKey("000")); // key 출력
System.out.println(treeMap.get(treeMap.ceilingKey("001"))); //value 출력
if (treeMap.containsKey("001")) {
    System.out.println("001 존재");
}

[출력]
{001=연필, 002=지우개, 003=샤프, 004=필통, 005=샤프심}
001=연필
001
연필
001 존재
  • TreeSet과 비슷하면서 Key, Value 형태인 Entry로 저장된 Map
반응형
profile

제육's 휘발성 코딩

@sasca37

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요! 맞구독은 언제나 환영입니다^^