study/java

자바/Java 컬렉션 강의 정리(1)

올스왑 2021. 1. 21. 21:55

이 글은 뉴렉쳐님의 강의를 듣고 정리하는 글입니다. youtube.com/playlist?list=PLq8wAnVUcTFWKOIbvo18pJZ9zsxtXz_-k

 

 

컬렉션이란 데이터를 (배열형태로?) 수집하고 관리해주는 객체이다. 간단히 말해서 가변 길이를 가진 배열이다.

 

대표적인 기능들은 다음과 같은 것이 있다.

  • .add(value) 요소 추가
  • .remove(index) 요소 제거
  • .clear() 전체 삭제
  • .size() 전체 길이 반환
  • .get(index) index에 있는 값 반환

 

그럼 컬렉션은 왜 사용할까?

  1. 데이터 관리를 직접할 필요 없다. 제공하는 메소드를 통해 쉽게 값을 추가하고 뺄 수 있다.
  2. 배열의 크기를 알아서 늘려준다.

 

직접 만들어본 컬렉션. 정수형을 담는 컬렉션이다.

package app.util;

public class IntList {
	
	private int[] numbers;
	private int current;
	
	public IntList() {
		numbers = new int[3]; //크기는 3으로 한다.
		current = 0;
	}

	public void add(int num) {
		numbers[current] = num; //값을 추가하면 현재 위치를 가리키는 변수를 +1 한다.
		current += 1;
	}

	public void clear() {
//		for (int i=0; i<current; i++)
//			numbers[i] = 0;
//		이렇게 for문으로 지워도 되지만 어차피 current로 접근하는 거라서
//		current값만 0으로 초기화해도 된다.
//
//		numbers = new int[3]; 또는 새롭게 배열을 생성해줘도 된다.
		
		current = 0;
	}

	public int size() {
		return current;
	}

	public int get(int index) {
		if(current <= index)
			throw new IndexOutOfBoundsException();
            //리스트의 크기보다 더 큰 값을 요청하면 예외처리를 한다.
		return numbers[index];
	}
}

 

다음은 실행 코드와 결과이다.

public static void main(String[] args) {
		IntList list = new IntList();
		list.add(3);
		list.add(5);
		int size = list.size();
		System.out.println(size);	// 2
		
		list.clear();
		size = list.size();
		System.out.println(size);	//0
		
		list.add(7);
		int num = list.get(0);
		System.out.println("num: "+ num); // num: 7
        
        list.get(1); // 예외 발생. IndexOutOfBoundsException
	}

 

 

 

그러나 위에서 만든 배열은 정수형 밖에 담지 못한다. 여러 타입의, 서로 다른 타입의 데이터를 담을 수 있는 방법이 있다. 

 

모든 클래스는 Object 클래스의 하위 클래스이다. 따라서 Object 타입의 배열을 만든다면 모든 객체를 Object 클래스로 업캐스팅하여 참조하게 할 수 있다.

 

하지만 여기서 또 한가지 문제가 생긴다. Object 클래스에는 객체를 담을 수는 있어도 기본값을 넣을 수는 없다. 10이라는 숫자를 Object 객체로 업캐스팅할 수는 없다. 그래서 Wrapper 클래스를 사용한다.(Wrapper 클래스에 대한 기본 설명: jang-sn.tistory.com/21)

 

Wrapper클래스를 기본값들을 래핑하여 Object 클래스로 업캐스팅이 가능해져 배열에서 참조할 수 있게 된다. 기본형 데이터에는 각각 Wrapper 클래스가 있다. 그 Wrapper 클래스는 Number 추상 클래스의 하위 클래스이고, Number 클래스는 Object의 하위 클래스가 된다. 

 

Object obj = new Integer(3); // 3을 박싱한 후 Object 클래스에 담았다.

//현재는 Auto Boxing 기능이 제공되 다음과 같이 바로 사용할 수 있다.

Object obj = 3; // -> Object obj = new Integer(3);와 동일.

int x = obj.intValue(); // 언박싱

int x = 3; // 변수에 직접 값을 담았다.
Integer x = 3; // 3이라는 값을 박싱했다. -> Integer x = new Integer(3);

 

이렇게 하면 Object 배열의 모든 타입의 값을 넣을 수 있다. 이런 컬렉션을 범용 컬렉션이라고 한다.

 

그러면 간단하게 위에 코드를 수정해보자

package app.util;

public class ObjectList {
	
	private Object[] numbers;
	private int current;
	
	public ObjectList() {
		numbers = new Object[3];
		current = 0;
	}

	public void add(Object num) {
		numbers[current] = num; //값을 추가하면 현재 위치를 가리키는 변수를 +1 한다.
		current += 1;
	}

	public void clear() {	
		current = 0;
	}

	public int size() {
		return current;
	}

	public Object get(int index) {
		if(current <= index)
			throw new IndexOutOfBoundsException();
		return numbers[index];
	}
}

 

이렇게 수정하면 모든 타입의 데이터를 담을 수 있는 배열이 완성된다. 그러나 이 배열의 문제점은 데이터를 배열로부터 꺼낼 때 어떤 타입으로 받아야 할 지 모른다는 것다. 배열의 3번 인덱스가 정수인지, 문자열인지 모른다면 값을 받을 수가 없다. 그래서 등장한 것이 제네릭이다.