Java 컬렉션, List, Queue, Stack, Set, Map

앞고기랑 소금·2024년 7월 23일

스파르타 TIL

목록 보기
7/43

7일차

컬렉션

  • 컬렉션은 배열보다 다수의 참조형 데이터를 더 쉽고 효과적으로 처리할 수 있는 기능을 많이 가지고 있습니다.

  • 컬렉션기능 : 크기 자동 조정/ 추가/ 수정/ 삭제/ 반복/ 순회/ 필터/ 포함 확인 등..

  • 컬렉션의 종류

    • Collection에는 List, Set , Queue , Map 이 있습니다.

    • List : 순서가 있는 데이터의 집합 (데이터 중복 허용) - 배열과 비슷

    • Queue : 빨대🥤처럼 한쪽에서 데이터를 넣고 반대쪽에서 데이터를 뺄 수 있는 집합

      • First In First Out : 먼저 들어간 순서대로 값을 조회할 수 있다.
      • stack (후입선출) 과 반대개념
    • Set : 순서가 없는 데이터의 집합 (데이터 중복 허용 안 함) - 순서 없고 중복 없는 배열

    • Map : 순서가 없는 (Key, Value) 쌍으로 이루어진 데이터의 집합 (Key값 중복 허용 안 함)

    ListQueueStackSetMap
    추가.add().add().push().add().put()
    읽기/꺼내기.get().poll().pop()--
    삭제.remove()--.remove(삭제할 값).remove(삭제할 key값)
    맨처음 조회-.peek().peek()--
    값 수정.set()----
    값 전체삭제.clear()----

List

순서가 있는 데이터의 집합 (데이터 중복 허용) - 배열과 비슷

- ArrayList

ArrayList는 배열(Array)처럼 일렬로 데이터를 저장하고 조회하여 순번 값(인덱스)로 값을 하나씩 조회할 수 있습니다.

  • 특징
    - 배열(Array)처럼 크기가 정해져 있지 않고 필요할 때마다 크기가 점점 더 늘어납니다.

    Array 와 어떤 점이 다르길래 ArrayList는 크기를 지정하지 않아도 되는 건가요?
    먼저, Array처럼 크기를 고정하여 생성하는 것을 정적 배열 이라면
    ArrayList처럼 크기가 가변적으로 늘어나는 것을 동적 배열 이라고 합니다.

    • Array은 메모리에 연속된 공간을 요청한 사이즈만큼 받아서 실제 값을 저장하는 기본형 변수로 저장하기 때문에 정적 배열 입니다.
    • ArrayList는 생성시점에 작은 연속된 공간을 요청해서 참조형 변수들을 담아놓고, 값이 추가될 때 더 큰 공간이 필요하면 더 큰 공간을 받아서 저장하기 때문에 동적 배열 입니다.
      따라서, 기본형 변수로 저장하는 Array는 정적 배열이고, 참조형 변수로 저장하는 ArrayList는 동적 배열이라고 기억하시면 됩니다!
  • 기능

    • 선언 : ArrayList<Integer> intList 형태로 선언합니다.

    • 생성 : new ArrayList<Integer>(); 형태로 생성합니다.

    • 초기화 : 사이즈를 지정하는 것이 없기 때문에 초기화가 필요 없습니다.

    • 값 추가 : intList.add({추가할 값}) 형태로 값을 추가합니다.

    • 값 수정 : intList.set({수정할 순번}, {수정할 값}) 형태로 값을 수정합니다.

    • 값 삭제 : intList.remove({삭제할 순번}) 형태로 값을 삭제합니다.

    • 전체 출력 : intList.toString() 형태로 전체 값을 대괄호[]로 묶어서 출력합니다.

    • 전체 제거 : intList.clear() 형태로 전체 값을 삭제합니다.

- LinkedList

📌 LinkedList는 메모리에 남는 공간을 요청해서 여기저기 나누어서 실제 값을 담아 놓고, 실제 값이 있는 주소값으로 목록을 구성하고 저장합니다.

  • 특징

    • 기본적인 기능은 ArrayList 와 동일하지만 LinkedList는 값을 나누어 담기 때문에 모든 값을 조회하는 속도가 느립니다. 대신에, 값을 중간에 추가하거나 삭제할 때는 속도가 빠릅니다.

      • 중간에 값을 추가하는 기능이 있습니다. (속도 빠름)
  • 기능

    • 선언 : LinkedList<Integer> linkedList 형태로 선언합니다.

    • 생성 : new LinkedList<Integer>(); 형태로 생성합니다.

    • 초기화 : 사이즈를 지정하는 것이 없기 때문에 초기화가 필요 없습니다.

    • 값 추가 : linkedList.add({추가할 값}) 형태로 값을 추가합니다.

    • 값 중간에 추가 : linkedList.add({추가할 순번}, {추가할 값}) 형태로 값을 중간에 추가합니다.

    • 값 수정 : linkedList.set({수정할 순번}, {수정할 값}) 형태로 값을 수정합니다.

    • 값 삭제 : linkedList.remove({삭제할 순번}) 형태로 값을 삭제합니다.

    • 전체 출력 : linkedList.toString() 형태로 전체 값을 대괄호[]로 묶어서 출력합니다.

    • 전체 제거 : linkedList.clear() 형태로 전체 값을 삭제합니다.

Queue

Queue은 빨대🥤처럼 한쪽에서 데이터를 넣고 반대쪽에서 데이터를 뺄 수 있는 집합입니다.
선입선출(First-In-First-Out)

  • 특징

    • First In First Out : 먼저 들어간 순서대로 값을 조회할 수 있다.

    • 그렇기 때문에 넣는 기능(add()), 조회(peek()), 꺼내는(poll()) 기능만 존재합니다.

    • Queue는 생성자가 없는 껍데기라서 바로 생성할 수는 없습니다. (껍데기 = 인터페이스)

    • 생성자가 존재하는 클래스인 LinkedList를 사용하여 Queue를 생성해서 받을 수 있습니다.

    // LinkedList 를 생성하면 Queue 기능을 할 수 있습니다.
    // (Queue 가 부모/ LinkedList 가 자식이기 떄문)
    Queue<Integer> intQueue = new LinkedList<Integer>();
  • 기능

    • 선언 : Queue<Integer> intQueue 형태로 선언합니다.

    • 생성 : new LinkedList<Integer>(); 형태로 생성합니다.

    • 추가 : intQueue.add({추가할 값}) 형태로 값을 맨 위에 추가합니다.

    • 조회 : intQueue.peek() 형태로 맨 아래 값을 조회합니다.

    • 꺼내기 : intQueue.poll() 형태로 맨 아래 값을 꺼냅니다. (꺼내고 나면 삭제됨)

Stack

📌 Stack 은 값을 수직으로 쌓아놓고 넣었다가 빼서 조회하는 형식으로 데이터를 관리합니다.
“후입선출(Last-In-First-out)” 성질을 가졌다고 표현하며, 주로 상자와 비유해서 설명합니다.

  • 특징

    • 상자에 물건을 넣고 빼는 것처럼 밑에서 위로 쌓고, 꺼낼 때는 위에서부터 꺼내는 형식입니다.

    • 그렇기 때문에 넣는 기능(push()) 과 조회(peek()), 꺼내는(pop()) 기능만 존재합니다.

    • 이렇게 불편하게 쓰는 이유는 최근 저장된 데이터를 나열하고 싶거나 데이터의 중복 처리를 막고 싶을 때 사용합니다.

  • 기능

    • 선언 : Stack<Integer> intStack 형태로 선언합니다.

    • 생성 : new Stack<Integer>(); 형태로 생성합니다.

    • 추가 : intStack.push({추가할 값}) 형태로 값을 추가합니다.

    • 조회 : intStack.peek() 형태로 맨 위값을 조회합니다.

    • 꺼내기 : intStack.pop() 형태로 맨 위값을 꺼냅니다. (꺼내고 나면 삭제됨)

Set

Set 은 순서가 없는 데이터의 집합 (데이터 중복 허용 안 함) - 순서 없고 중복 없는 배열

  • 특징

    • 순서가 보장되지 않는 대신 중복을 허용하지 않도록 유지할 수 있습니다.
    • Set은 그냥 Set으로 쓸 수도 있지만 HashSet, TreeSet 등으로 응용하여 사용할 수 있습니다.
    • Set는 생성자가 없는 껍데기라서 바로 생성할 수는 없습니다. (껍데기 = 인터페이스)
    • 생성자가 존재하는 클래스인 HashSet를 사용하여 Set를 생성해서 받을 수 있습니다.
  • 기능

    • 선언 : Set<Integer> intSet 형태로 선언합니다.

    • 생성 : new HashSet<Integer>(); 형태로 생성합니다.

    • 추가 : intSet.add({추가할 값}) 형태로 값을 맨 위에 추가합니다.

    • 삭제 : intSet.remove({삭제할 값}) 형태로 삭제할 값을 직접 지정합니다.

    • 포함 확인 : intSet.contains({포함 확인 할 값}) 형태로 해당 값이 포함되어있는지 boolean 값으로 응답받습니다.

HashSet 외에도 TreeSet, LinkedHashSet 이 있습니다.

  • HashSet : 가장 빠르며 순서를 전혀 예측할 수 없음
  • TreeSet : 정렬된 순서대로 보관하며 정렬 방법을 지정할 수 있음
  • LinkedHashSet : 추가된 순서, 또는 가장 최근에 접근한 순서대로 접근 가능
    즉, 보통 HashSet 을 쓰는데 순서 보장이 필요하면 LinkedHashSet 을 주로 사용합니다.

Map

여태까지 value 값들만 넣어서 관리하는 분류통(자료구조)를 배웠다면 Mapkey-value 구조로 구성된 데이터를 저장할 수 있습니다.

  • 특징

    • key-value 형태로 데이터를 저장하기 때문에 기존에 순번으로만 조회하던 방식에서, key 값을 기준으로 value를 조회할 수 있습니다.

    • key 값 단위로 중복을 허용하지 않는 기능을 가지고 있습니다.

    • Map 은 그냥 Map으로 쓸 수도 있지만 HashMap, TreeMap등으로 응용하여 사용할 수 있습니다.

    • Map으로 쓸 수도 있지만 HashSet, TreeSet 등으로 응용하여 사용할 수 있습니다.

  • 기능

    • 선언 : Map<String, Integer> intMap 형태로 Key타입과 Value타입을 지정해서 선언합니다.

    • 생성 : new HashMap<>(); 형태로 생성합니다.

    • 추가 : intMap.put({추가할 Key값},{추가할 Value값}) 형태로 Key에 Value값을 추가합니다.

    • 조회 : intMap.get({조회할 Key값}) 형태로 Key에 있는 Value값을 조회합니다.

    • 전체 key 조회 : intMap.keySet() 형태로 전체 key 값들을 조회합니다.

    • 전체 value 조회 : intMap.values() 형태로 전체 value 값들을 조회합니다.

    • 삭제 : intMap.remove({삭제할 Key값}) 형태로 Key에 있는 Value값을 삭제합니다.

HashMap 외에도 TreeMap 이 있습니다.

  • HashMap : 중복을 허용하지 않고 순서를 보장하지 않음, 키와 값으로 null이 허용
  • TreeMap : key 값을 기준으로 정렬을 할 수 있습니다. 다만, 저장 시 정렬(오름차순)을 하기 때문에 저장시간이 다소 오래 걸림

2주차 숙제 오류해결

자료구조 요리 레시피 메모장 만들기

  • 입력값
    • 저장할 자료구조명을 입력합니다. (List / Set / Map)
    • 내가 좋아하는 요리 제목을 먼저 입력합니다.
    • 이어서 내가 좋아하는 요리 레시피를 한 문장씩 입력합니다.
    • 입력을 마쳤으면 마지막에 “끝” 문자를 입력합니다.
  • 출력값
    • 입력이 종료되면 저장한 자료구조 이름과 요리 제목을 괄호로 감싸서 먼저 출력해 줍니다.
    • 이어서, 입력한 모든 문장 앞에 번호를 붙여서 입력 순서에 맞게 모두 출력해 줍니다.
  • 입력의 두번째 값만 출력됨

import java.util.ArrayList;
import java.util.Scanner;

public class W02 {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        ArrayList<String> strList = new ArrayList<String>();
        int count = 1;
        String str = "";

        while (!sc.nextLine().equals("끝")) {
            str = sc.nextLine();
            strList.add(str);
        }
        System.out.println("[" + strList.get(0) + " 으로 저장된 " + strList.get(1) + "]");
        for (int i = 2; !strList.get(i).equals("끝"); i++) {
            System.out.println(count++ + ". " + strList.get(i));
        }
    }
}
  • 입력
    1
    2
    3
    4
    5
    6
    7
    8
    9

  • 출력
    [2 으로 저장된 4]
  1. 6
  2. 8
  • 해결
    • while 조건에 !sc.nextLine().equals("끝") "끝"이 입력되면 나오게 하려함.
    • 조건부에서 입력한번, str = sc.nextLine()에서 입력한번 이라 두번째값만 출력되게됨.
    • !sc.nextLine().equals("끝")을 !str.equals("끝")으로 변경
import java.util.ArrayList;
import java.util.Scanner;

public class W02 {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        ArrayList<String> strList = new ArrayList<String>();
        int count = 1;
        String str = "";

        while (!str.equals("끝")) {
            str = sc.nextLine();
            strList.add(str);
        }
        System.out.println("[" + strList.get(0) + " 으로 저장된 " + strList.get(1) + "]");
        for (int i = 2; !strList.get(i).equals("끝"); i++) {
            System.out.println(count++ + ". " + strList.get(i));
        }
    }
}

0개의 댓글