27. 컬렉션

Jan 04, 2024
27. 컬렉션
💡
컬렉션은 애플리케이션의 작성을 도와주는 중요한 도구로써 자료를 저장 하기 위한 구조다. 크기가 동적으로 바뀌는 것들은 컬렉션을 쓴다. 많이 사용되는 자료 구조로는 list,stack,queue,set,hash table등이 있다.
 

컬렉션의 종류(중요한 것들)

💡
List(ArrayList, LinkedList)는 동적 배열을 정의하고 있다. Set(HashSet)은 집합을 정의하고 있다. Map(hasMap)은 키가 주어지면 값을 반환하는 사전과 같은 자료구조를 정의하고 있다.
 

벡터

💡
컬렉션의 일종으로 가변 크기의 배열을 구현하고 있다. 즉 요소의 개수(인덱스 값)이 늘어나면 자동으로 배열의 크기가 늘어난다. 또한 제네릭 기법을 사용하고 있어 어떤 객체라도 저장 가능하며 정수와 같은 기초형 데이터도 오토박싱 기능을 이용하여서 객체로 변환되어 저장 할 수 있다. 스레드간의 동기화를 지원한다.
  • 문법으로는
    • 값을 추가하려면 add(),
    • 값을 집어넣을때는add(index, object),
    • 값을 추출 할 때는 get()
    • 값들의 개수를 반환 할때는 size()
    •  
예제
package ex13; import java.util.Collections; import java.util.Vector; public class VectorExample1 { public static void main(String[] args) { Vector<String> vec = new Vector(); vec.add("Apple"); vec.add("Orange"); vec.add("Mango"); // 크기 System.out.println(vec.size()); // 인덱스 접근 System.out.println(vec.get(1)); // 정렬 (오름차순) Collections.sort(vec); for (String s : vec) { System.out.print(s + " "); } System.out.println(); // 정렬 (내림차순) Collections.sort(vec, Collections.reverseOrder()); for (String s : vec) { System.out.print(s + " "); } System.out.println(); // 다른 방법의 정렬(일반 배열) // Arrays.sort(); // 삭제 String result = vec.remove(2); System.out.println(result); System.out.println(vec.size()); // 값 찾기 boolean search =vec.contains("Mango"); System.out.println(search); String a = "Mango"; boolean check = a.equalsIgnoreCase("mAngo"); System.out.println(check); } }
notion image

AraayList(내가 찾으려는 값을 바로 찾아낼 수 있다.)(중요)

💡
동시에 접근이 가능하다. 스레드간의 동기화를 하지 않는다. 제네릭 클래스로 제공이 되기 때문에 생성하려면 타입 매개 변수를 지정 해야 한다. 일반 클래스로 저장 타입을 가져 갈 수 도 있다. 생성 문법으로는 ArrayList<저장 타입> list = new ArrayList<저장 타입>(): 배열을 리스트로 변경 할 때는 (밑 문법 )사용
List<String> list = Arrays.asList(new String[size]);
  • 문법으로는
    • 데이터를 저장 하려면 add(저장할 값),
    • 기존의 데이터가 들어 있는 위치를 지정해서 add(index, object),를 호출하면 새로운 데이터는 중간에 삽입
    • 값을 변경하고 싶을 때는 set(index, object)을 사용한다.
    • 인덱스의 저장된 값을 추출 할 때는 자료타입 변수명 = get(index)을 사용한다.
      • 만일 이때 범위를 벗어나는 인덱스를 사용하면
    • 데이터를 삭제하려면 remove(index)를 사용한다.
    •  
      예제
      package ex13; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ArrayListEx01 { public static void main(String[] args) { List<Integer>arr = new ArrayList(); List<Integer>arr2 = Arrays.asList(1,2); } }
      notion image
       
       

      LinkedList(왠만해서 사용 x 앞의 인덱스를 들려서 내가 찾으려는 인덱스를 찾는다)

      💡
      각 인덱스 값을 링크로 연결한다. 이렇게 해서 linkedlist는 중간에 값을 삽입하거나 삭제되는 위치의 바로 앞에 있는 값의 링크 값 만을 변경하면 된다. 즉 배열의 값을 넣을 때 앞에 인덱스 번호를 붙인다. 그러므로 삽입이나 삭제가 빈번하게 일어날 때는 LinkedList를 사용하는게 좋다.
      그러나 인덱스를 가지고 원소를 접근하는 연산은 ArrayList가 더 빠르다.
      예제
      package ex13; import java.util.LinkedList; public class LinkedListTest { public static void main(String[] args) { LinkedList<String>list = new LinkedList<String>(); list.add("MILK"); list.add("BREAD"); list.add("BUTTER"); list.add(1,"APPLE"); // 인덱스 1에 "APPLE"을 삽입 list.add(2,"GRAPE"); // 인덱스 2에 "GRAPE"를 삽입 list.remove(3); // 인덱스 3의 값을 삭제 한다. for (int i = 0; i< list.size(); i++) System.out.println(list.get(i)+""); } }
       

      Set(중요)

      💡
      앞에서 설명한것들은 다 순서의 의해서 값이 저장되지만 순서의 상관없이 값을 저장할때는 Set(집합) 을 사용한다. Set은 동일한 데이터를 중복해서 가질 수 없다. HashSet은 해쉬 테이블에 값을 저장한다. 수학에서 집합연산에 합집합, 교집합이 있는 것처럼 , Set에도 addAll()과 retainAll()이라는 메소드로 각각 합집합, 교집합을 구현한다.
      예제
      package ex13; import java.util.Arrays; import java.util.HashSet; import java.util.Set; public class SetTest { public static void main(String[] args) { HashSet<String>set = new HashSet<String>(); set.add("Milk"); set.add("Bread"); set.add("Butter"); set.add("Cheese"); set.add("Ham"); set.add("Ham"); System.out.println(set); if (set.contains("Ham")){ System.out.println("Ham도 포함되어 있음"); Set<Integer> s1 = new HashSet<>(Arrays.asList(1,2,3,4,5,7,9)); Set<Integer> s2 = new HashSet<>(Arrays.asList(2,4,6,8)); s1.retainAll(s2); //교집합 계산 System.out.println(s1); } } }
      교집합
      notion image
       

      Map(HashMap)(중요)

      💡
      Map은 키-값을 하나의 쌍으로 묶어서 저장하는 자료구조이며 키(단어), 값(단어에 대한 설명)이 있다. 제한적으로는 중복된 키를 가질 수 없다. 각 키는 오직 하나의 값에만 매핑 될 수 있다. 키가 제시되면Map은 값을 반환한다. list와 같은 자료구조와는 다르기 때문에 Collecttion 인터페이스를 사용하지 않고 별도의 Map이라는 이름의 인터페이스가 제공된다. HashMap 은 해싱 테이블에 데이터를 저장하고 키들을 정렬된 순서로 방문할 필요가 없을때 사용한다. 데이터를 저장하려면 put()메소드를 사용한다. 초기화 할때는 (밑 코드)를 사용한다.
      Map<INTEGER,String> map = Map.of("kim","1234","park","pass","lee","world")
      예제
      package ex13; import java.util.HashMap; import java.util.Map; public class MapTest { public static void main(String[] args) { Map<String,String> map = new HashMap<String,String>(); map.put("kim","1234"); map.put("park","pass"); map.put("lee","word"); System.out.println(map.get("lee")); // 키를 가지고 값을 참조한다. for (String key:map.keySet()){ //keySet()은 키들의 집합을 반환한다. 모든 항목을 방문한다. String value = map.get(key); System.out.println("key="+key+",vlaue="+value); } map.remove(3); //하나의 항목을 삭제한다. map.put("choi","password"); //하나의 항목을 대치한다. System.out.println(map); } }
      notion image
       
      💡
      Map에 저장된 데이터를 꺼내는 코드는 다른 컬렉션과는 다르다.
      예제
      for (String key: map.keySet()){ System.out.println("key="+key+", value="+map.get(key)); //for-each 구문과 keySet()을 사용하는 방법
       
      map.forEach((key, value) -> { System.out.println("key="+key+", value="+value); }); //람다 표현식
       
       

      Queue

      💡
      큐는 데이터를 처리하기 전에 잠시 저장하고 있는 자료 구조로 후단 에서 원소를 추가하고 전단에서 값을 추가하여 FIFO(first-in-first-out)형식으로 저장한다. 예외적으로 우선순위 큐는 값들을 우선순위에 따라 저장한다. 큐는 인터페이스 이며 3개 클래스(ArrayDeque, LinkedList, PriorityQueue)가 있다. 이중에서 다큐는 전단과 후단에서 모든 값을 추가하거나 삭제 할 수 있다.
       

      Queue 메서드

    • add( )메서드: 새로운 값의 추가가 큐의 용량을 넘어서지 않으면 값을 추가한다.
    • reomove( )와 poll( )은 큐의 처음에 있는 값을 제거하거나 가져온다. 어떤 값이 제거가 되냐는 큐의 정렬 정책에 따라 달라진다.
    • element( )와 peek( )는 큐의 처음에 있는 값을 삭제하지 않고 가져온다.
    •  
      예제
      package ex13; import java.util.LinkedList; import java.util.Queue; public class QueueTest { public static void main(String[] args) { Queue<Integer> q = new LinkedList<>(); for (int i = 0; i < 5; i++) { q.add(i); } System.out.println("큐의 요소: "+q); int e = q.remove(); System.out.println("삭제된 요소:"+ e); System.out.println(q); } }
      notion image
       
       

      Collections 클래스

      💡
      Collections 클래스는 여러 알고리즘을 알고리즘을 구현한 메서드들을 제공한다. 이 메서드들은 제네릭 기술을 사용하여서 작성되었으며 정적 메서드의 형태로 되어 있다. 메서드의 첫 번째 매개 변수는 알고리즘이 적용되는 컬렉션이 되며 이중에서 중요한 알고리즘은 정렬(Sorting), 섞기(Shuffling), 탐색(Searching)이 있다.
       

      정렬

      💡
      • 정렬은 데이터를 어떤 기준에 의하여 순서대로 나열 하는 것이다
      • 정렬 알고리즘에는 퀵 정렬, 합병 정렬, 히프 정렬 등의 다양한 방법이 존재한다.
      • Collections 클래스의 정렬은 합병 정렬을 이용한다.
      • 합병 정렬은 시간복잡도가 O(nlog(n))이며 정렬된 리스트에 대해서는 상당히 빠르다.
      • Collections 클래스의 sort( )는 List인터페이스를 구현하는 컬렉션에 대하여 정렬을 수행 한다.
        • String 타입이면 알파벳 순서대로 Date타입이라면 시간 순서대로 이렇게 가능한 이유는 Comprable 인터페이스를 구현 하기 때문이다. Comprable 인터페이스는 메서드(밑 코드)만을 가지고 있다.
          • public interface Comprable<T> { public int compareTo(T o); }
            compareTo()메서드는 매게 변수 객체를 현재의 객체와 비교하여 음수 (작을때)
            0(같을때),양수(클때)를 반환한다.
      문자열 정렬
      package ex13; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; public class Sort { public static void main(String[] args) { String[] sample = {"i", "walk", "the", "line"}; List<String>list = Arrays.asList(sample); // 배열을 리스트로 변경 asList()사용 Collections.sort(list); System.out.println(list); } }
       
      StudentEmployee(compareTo( ))를 구현)
      package ex13; import java.util.Arrays; import java.util.Collections; import java.util.List; class Student implements Comparable<Student>{ int number; String name; public Student(int number, String name){ this.number=number; this.name=name; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + '}'; } public int compareTo(Student s){ return s.number-number; } } public class SortTest { public static void main(String[] args) { Student array[]= { new Student(2,"김철수"), new Student(3,"이철수"), new Student(1,"박철수"), }; List<Student> list = Arrays.asList(array); Collections.sort(list);// 만약 역순으로 정렬하기를 원한다면 Collections.sort(list,Collections.reverseOrder())를 사용 System.out.println(list); } }
       
       

      섞기

      💡
      리스트에 존재하는 정렬을 파괴하여서 값들의 순서를 랜덤 하게 만든다. 게임을 구현할 때 유용하게 사용 된다.
      예제
      package ex13; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Shuffle { public static void main(String[] args) { List<Integer>list = new ArrayList<Integer>(); for (int i=1; i<=10; i++){ list.add(i); } Collections.shuffle(list); System.out.println(list); } }
      notion image
       

      탐색

      💡
      탐색이란 리스트 안에서 원하는 값을 찾는 것 이다. 만약 리스트가 정렬돼있지 않다면 처음부터 모든 값을 방문 할 수 밖에 없다(선형 탐색) 하지만 리스트가 정렬 돼있다면 중간에 있는 원소와 먼저 비교 하는 것 이 좋다(이진탐색) 만약 중간 원소보다 찾고자 하는 원소가 크면 뒷 부분에 있고 반대이면 앞 부분에 있다. 만약 반환값이 양수이면 탐색이 성공한 객체의 위치이다collec.get(index)하면 원하는 객체를 얻을 수 있다. 만약 반환값이 음수이면 탐색이 실패했다. 그러나 도움이 되는 정보가 반환 되는데 반환 값에서 현재의 데이터가 삽입될 수 있는 위치를 알아낼 수 있다. 반환 값이pos이면 (-pos -1)이 삽입 위치가 된다.(밑 코드 문법)
      int pos = Collections.binarySearch(list,key); if(pos<0) list.add(-pos-1);
      예제
      package ex13; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Search { public static void main(String[] args) { int key = 50; List<Integer> list = new ArrayList<Integer>(); for (int i =0; i<100; i++){ list.add(i); } int index = Collections.binarySearch(list,key); System.out.println("탐색의 반환 값 ="+index); } }
      notion image
       
Share article
RSSPowered by inblog