Collection Framework[Java]

SnowCat·2023년 6월 7일
0

Java - Language

목록 보기
12/17
post-thumbnail

컬렉션 프레임워크란?

  • 다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스 집합을 컬렉션 프레임워크라 함
  • 컬렉션 프레임워크에는 List, Set, Map 인터페이스가 구현되어 있음
  • 컬렉션 프레임워크에 속하는 인터페이스들을 구현한 것을 컬렉션 클래스라고 함

List

  • List 컬렉션 클래스는 요소의 저장 순서가 유지되며, 같은 요소의 중복 저장을 허용한다는 특징이 있음
  • List 컬렉션 클래스에는 대표적으로 ArrayList, LinkedList, Stack이 속해있음

ArrayList

  • 배열을 사용해 요소를 저장하는 List 컬렉션 클래스
  • 인덱스를 이용해 배열 요소에 빠르게 접근할 수 있지만, 크기 변경이 필요할때 새로운 배열을 생성해야해 속도가 저하됨
ArrayList<Integer> arrList = new ArrayList<Integer>();

// 요소의 추가
arrList.add(40);
arrList.add(20);
arrList.add(30);
arrList.add(10);

// getter 사용
for (int i = 0; i < arrList.size(); i++) {
    System.out.print(arrList.get(i) + " "); // 40 20 30 10
}

// 특정 인덱스의 요소 제거
arrList.remove(1);

for (int e : arrList) {
    System.out.print(e + " "); // 40 30 10
}

// 정렬
Collections.sort(arrList);

// iterator를 사용한 반복문 출력
Iterator<Integer> iter = arrList.iterator();
while (iter.hasNext()) {
    System.out.print(iter.next() + " "); // 10 30 40
}

// 특정 위치의 요소 변경
arrList.set(0, 20);

for (int e : arrList) {
    System.out.print(e + " "); // 20 30 40
}

// 크기 출력
System.out.println("리스트의 크기 : " + arrList.size()); // 3
  • 사용가능한 메서드는 아래와 같음

LinkedList

  • ArrayList와 거의 동일한 기능을 가지나, 배열이 아닌 연결 리스트를 사용하는 방식
  • 동적인 크기변경에 유리하나, 요소의 참조에 있어서는 불리함

Stack

  • List 컬렉션의 Vector 클래스 일부를 상속받아 스택 메모리 구조를 제공하는 클래스
Stack<Integer> st = new Stack<Integer>(); // 스택의 생성

/*
아래와 같이 ArrayDeque를 사용하면 속도상에 이득을 보나, search()메서드는 사용 불가능해짐에 유의
Deque<Integer> st = new ArrayDeque<Integer>();
*/

// push() 메소드를 이용한 요소의 저장
st.push(4);
st.push(2);
st.push(3);
st.push(1);

System.out.println(st.peek()); // 1
System.out.println(st); // [4, 2, 3, 1]

System.out.println(st.pop()); // 1
System.out.println(st); // [4, 2, 3]


System.out.println(st.search(4)); // 3
System.out.println(st.search(3)); // 1

Queue

  • Queue 인터페이스는 별도의 인터페이스로 제공되며 이를 상속받는 하위 인터페이스로는 Deque, BlockingDeque, BlockingQueue, TransferQueue가 있음
  • 큐 메모리 구조를 표현하기 위해 컬렉션 인터페이스의 일부만을 상속받아 사용함
  • 빠른 큐를 구현하기 위해서는 Deque 인터페이스를 구현한 ArrayDeque 클래스를 사용하면 됨
Deque<Integer> qu = new ArrayDeque<Integer>();

qu.add(4);
qu.add(2);
qu.add(3);
qu.add(1);

System.out.println(qu.peek()); // 4
System.out.println(qu); // [4, 2, 3, 1]

 

System.out.println(qu.poll()); // 4
System.out.println(qu); // [2, 3, 1]

 
// remove는 값 반환은 하지 않음
qu.remove("하나");
System.out.println(qu); // [2, 3]

Set

  • Set 컬렉션 클래스는 요소의 저장 순서를 유지하지 않고, 같은 요소의 중복저장을 허용하지 않는 특징을 가짐
  • 대표적인 Set 컬렉션 클래스로는 HashSet, TreeSet이 있음

HashSet

  • 해시 자료구조를 사용해 구현된 Set 클래스
  • 해시 알고리즘 사용으로 검색 속도가 매우 빠르다는 장점이 있음
  • 요소의 저장순서를 기록해야 하는 경우 LinkedHashSet 클래스를 사용해야 함
HashSet<String> hs01 = new HashSet<String>();
HashSet<String> hs02 = new HashSet<String>();

hs01.add("홍길동");
hs01.add("이순신");

System.out.println(hs01.add("임꺽정")); // true
System.out.println(hs01.add("임꺽정")); // false
for (String e : hs01) {
    System.out.print(e + " "); // 홍길동 이순신 임꺽정
}

hs02.add("임꺽정");
hs02.add("홍길동");
hs02.add("이순신");

Iterator<String> iter02 = hs02.iterator();
while (iter02.hasNext()) {
    System.out.print(iter02.next() + " "); // 홍길동 이순신 임꺽정
}

System.out.println(hs02.size()); // 3

TreeSet

  • 데이터를 이진 트리 형태로 저장하는 Set 컬렉션 클래스
  • 인스턴스에 저장되는 요소들은 모두 정렬된 상태로 저장됨
TreeSet<Integer> ts = new TreeSet<Integer>();

ts.add(30);
ts.add(40);
ts.add(20);
ts.add(10);

for (int e : ts) {
    System.out.print(e + " ");
}

ts.remove(40);

Iterator<Integer> iter = ts.iterator();
while (iter.hasNext()) {
    System.out.print(iter.next() + " ");
}

System.out.println(ts.size());

System.out.println(ts.subSet(10, 20));
// boolean값은 해당 요소값을 포함할건지 여부이며 기본값은 true, false
System.out.println(ts.subSet(10, true, 20, true)); // [10, 20]

Map

  • map 컬렉션은 key-value 방식을 사용해 컬렉션의 데이터를 저장해둠
  • 키의 중복을 허용하지 않으며, 요소의 저장 순서를 유지하지 않는다는 특징을 가짐
  • Map 컬렉션 클래스에 속하는 클래스로는 HashMap, TreeMap이 있음

HashMap

  • 해시 알고리즘을 사용한 Map 자료구조
HashMap<String, Integer> hm = new HashMap<String, Integer>();

hm.put("삼십", 30);
hm.put("십", 10);
hm.put("사십", 40);
hm.put("이십", 20);

System.out.println(hm.keySet()); // [이십, 삼십, 사십, 십]
for (String key : hm.keySet()) {
	/*
    key : 이십, value : 20
    key : 삼십, value : 30
    key : 사십, value : 40
    key : 십, value : 10
    */
    System.out.println(String.format("key : %s, value : %s", key, hm.get(key)));
}

hm.remove("사십");
Iterator<String> keys = hm.keySet().iterator();
while (keys.hasNext()) {
    String key = keys.next();
    /*
    key : 이십, value : 20
    key : 삼십, value : 30
    key : 십, value : 10
    */
    System.out.println(String.format("key : %s, value : %s", key, hm.get(key)));
}

hm.replace("이십", 200);
for (String key : hm.keySet()) {
	/*
    key : 이십, value : 200
    key : 사십, value : 40
    key : 십, value : 10
    */
    System.out.println(String.format("key : %s, value : %s", key, hm.get(key)));
}

System.out.println("맵의 크기 : " + hm.size()); // 3

Iterator

  • 컬렉션에 저장된 요소들을 읽어오기 위해서 Iterator 메서드를 사용할 수 있음
LinkedList<Integer> lnkList = new LinkedList<Integer>();

lnkList.add(4);
lnkList.add(2);
lnkList.add(3);
lnkList.add(1);

Iterator<Integer> iter = lnkList.iterator();
while (iter.hasNext()) {
    System.out.print(iter.next() + " "); // 4 2 3 1
}
  • List 사용시에는 역방향 이동이 가능한 listIterator 메서드를 지원함
LinkedList<Integer> lnkList = new LinkedList<Integer>();

lnkList.add(4);
lnkList.add(2);
lnkList.add(3);
lnkList.add(1);

ListIterator<Integer> iter = lnkList.listIterator();
while (iter.hasNext()) {
    System.out.print(iter.next() + " ");
}

while (iter.hasPrevious()) {
    System.out.print(iter.previous() + " ");
}
  • 실제 코드 작성시에는 Enhannced for문 사용을 권장함

Comparable

  • 자바에서는 Boolean을 제외한 래퍼 클래스나 클래스의 인스턴스들을 정렬하기 위해 Comparable 인터페이스를 사용할 수 있음
  • 인터페이스 내부의 compareTo 메서드를 구현해 객체를 정렬할 수 있음
class Car implements Comparable<Car> {
    private String modelName;
    private int modelYear;
    private String color;

    Car(String mn, int my, String c) {
        this.modelName = mn;
        this.modelYear = my;
        this.color = c;
    }

    public String getModel() {
        return this.modelYear + ", " + this.modelName + " " + this.color;
    }

    public int compareTo(Car obj) {
        if (this.modelYear == obj.modelYear) {
            return 0;
        } else if(this.modelYear < obj.modelYear) {
            return -1;
        } else {
            return 1;
        }
    }
}

 

public class Comparable01 {
    public static void main(String[] args) {
        Car car01 = new Car("아반떼", 2016, "노란색");
        Car car02 = new Car("소나타", 2010, "흰색");

        System.out.println(car01.compareTo(car02)); // 1
    }
}
  • Comparable 인터페이스를 구현한 클래스는 기본적으로 구현의 오름차순으로 정렬됨
  • 만약 다른 기준으로 정렬이 필요하다면 Comparator 인터페이스를 사용
  • Comparator 인터페이스를 구현한 클래스에서는 compart() 메서드를 오버라이딩 해 사용하게 됨
import java.util.*;

class DescendingOrder implements Comparator<Integer> {
    public int compare(Integer o1, Integer o2) {
        if(o1 instanceof Comparable && o2 instanceof Comparable) {
            Integer c1 = (Integer)o1;
            Integer c2 = (Integer)o2;
            return c2.compareTo(c1);
        }
        return -1;
    }
}

public class Comparable02 {
    public static void main(String[] args) {
        TreeSet<Integer> ts = new TreeSet<Integer>(new DescendingOrder());

        ts.add(30);
        ts.add(40);
        ts.add(20);
        ts.add(10);

        Iterator<Integer> iter = ts.iterator();
        while(iter.hasNext()) {
            System.out.println(iter.next()); // 40 30 20 10
        }
    }
}
profile
냐아아아아아아아아앙

0개의 댓글