본문 바로가기

백앤드 개발/Java & Spring

[Java] 컬렉션 프레임워크

1. Generics 

클래스에서 사용할 데이터 타입을 외부에서 지정하는 기법

제네릭스가 Integer를 사용하면 해당 컬렉션 프레임워크엔 Int 타입만 들어올 수 있음

컬렉션 프레임워크에서 많이 사용됨

지정하는 데이터 타입을 타입 파라미터라 함

타입 파라미터가 할당 받을 수 있는 데이터 타입은 참조형 타입 뿐이다.

(Byte, Short, Integer, Long, Plot, Double, Character ... )

 

package lec13_generics02;

public class ExeA<T> {
	private T t;
	
	public  ExeA(T t) {
		this.t = t;
	}
	
	public T getT() {
		return t;
	}
}

 

package lec13_generics02;

public class ExeB {
	public <T> T method1(T t) {
		return t;
	}
	
	public static <T> T method2(T t) {
		return t;
	}
	
	public <T> T method3(ExeA<T> exeA) {
		return exeA.getT();
	}
	
	public static <T>T method4(ExeA<T> exeA){
		return exeA.getT();
	}
}

 

package lec13_generics02;

public class ExeMain {
	public static void main(String[] args) {
		
		ExeB b = new ExeB();
		String method1 = b.method1("테스트1");
		
		// 객체 생성 없이 바로 메서드 사용
		String method2 = ExeB.method2("테스트2");
		
		System.out.println("method1 : " + method1);
		System.out.println("method2 : " + method2);
		
		// String 으로 리턴값 지정
		// T의 형태로 지정해 여러가지 Type 을 활용할 수도 있다
		ExeA<String> exeA1 = new ExeA<>("1");
		String t1 = exeA1.getT();
		String method3 = b.method3(exeA1);
		String method4 = ExeB.method4(exeA1);
		
		System.out.println("t1 : " + t1);
		System.out.println("method3 : "+ method3);
		System.out.println("method4 : "+ method4);
		
		ExeA exeA2 = new ExeA("2");
		Object t2 = exeA2.getT();
		Object method6 = b.method3(exeA2);
		Object method5 = ExeB.method4(exeA2);
		
		System.out.println("t2 : " + t2);
		System.out.println("method6 : "+ method6);
		System.out.println("method5 : "+ method5);
		
		
		ExeA<Integer> exeAInt = new ExeA<>(100);
		Integer getIntT = exeAInt.getT();
		System.out.println("getInt : " + getIntT);
		Integer intExeAInt1 = b.method3(exeAInt);
		Integer intExeAInt2 = ExeB.method4(exeAInt);
		
		System.out.println("intExeAInt1 : " + intExeAInt1);
		System.out.println("intExeAInt2 : " + intExeAInt2);
		
	}
}

// 출력 결과
//method2 : 테스트2
//t1 : 1
//method3 : 1
//method4 : 1
//t2 : 2
//method6 : 2
//method5 : 2
//getInt : 100
//intExeAInt1 : 100
//intExeAInt2 : 100

 

2. 컬렉션 프레임워크

데이터를 효율적으로 관리하기 위해 구조를 짜는 것

Java 에서는 다수의 데이터를 효과적으로 처리할 수 있도록 표준화된 방법을 제공함

현업에서는 map(hash map) 과 list(Arraylist)를 많이 씀


1) List: 순서 있음. 데이터 중복 허용


- ArrayList (가장 많이 쓰임): 순차적인 데이터 입력. 입출력 데이터의 순서가 일정할때 쓰기 좋음
어떤 특징 분류값을 가지지않고 목록 형태로 데이터를 담을때
- LinkedList : 데이터의 입력 수정 삭제가 매우 빠름. 데이터가 바뀔때 서로 연결된 링크를 통해 구성된 리스트. 
하지만 순차적인 데이터 삽입시 속도가 느려질수 있음
- Vector, Stack

 

// arraylist 예시
package lec14.collectionframework;

import java.util.ArrayList;

public class ArrayLIist03 {
	
public static void main(String[] args) {
        ArrayList<Integer> intArrayList = new ArrayList<Integer>();
        System.out.println("--- add(): data 삽입 ---");
        intArrayList.add(1);
        intArrayList.add(2);
        intArrayList.add(3);
        intArrayList.add(4);
        intArrayList.add(5);

        int intArraySize = intArrayList.size();

        System.out.println("--- get(): data 추출 ---");
        for (int x=0; x<intArraySize; x++) {
            Integer o = intArrayList.get(x);
            System.out.println(x + "번째 get int ::: " + o);
    }

        System.out.println("--- contains(): data 존재유무 ---");
        System.out.println("1을 포함하는가?: " + intArrayList.contains(1));
        System.out.println("6을 포함하는가?: " + intArrayList.contains(6));

        System.out.println("--- remove(index값): index 해당 요소 삭제 ---");
        intArrayList.remove(4);

        System.out.println("--- size(): 요소개수 ---");
        System.out.println("요소개수: " + intArrayList.size());
 }
}

// 출력결과
//        --- add(): data 삽입 ---

//        --- get(): data 추출 ---
//        0번째 get int ::: 1
//        1번째 get int ::: 2
//        2번째 get int ::: 3
//        3번째 get int ::: 4
//        4번째 get int ::: 5

//        --- toArray(): 문자열 출력 ---
//        [Ljava.lang.Object;@51016012

//        --- contains(): data 존재유무 ---
//        1을 포함하는가?: true
//        6을 포함하는가?: false

//        --- remove(index값): index 해당 요소 삭제 ---

//        --- size(): 요소개수 ---
//        요소개수: 4

 

2) Set: 중복된 값을 입력 받지 않음. 순서 없음. 중복된 데이터를 걸러낼 수 있음.

package lec14.collectionframework;

import java.util.HashSet;

// HashSet
public class Set06 {
		
        HashSet hset = new HashSet();

        System.out.println("--- add(): data 삽입 ---");

        hset.add(1);
        hset.add(1);
        hset.add(1);
        hset.add(1);
        hset.add(2);

        System.out.println("--- contains(): data 존재유무 ---");
        System.out.println("1을 포함하는가?: " + hset.contains(1));
        System.out.println("6을 포함하는가?: " + hset.contains(6));

        System.out.println("--- remove(value): 해당 요소 삭제 ---");
        hset.remove(1);

        System.out.println("--- size(): 요소개수 ---");
        System.out.println("요소개수: " + hset.size());

        System.out.println(hset.toString());
	}
}

// 출력결과
//        --- add(): data 삽입 ---
//        --- contains(): data 존재유무 ---
//        1을 포함하는가?: true
//        6을 포함하는가?: false
//        --- remove(value): 해당 요소 삭제 ---
//        --- size(): 요소개수 ---
//        요소개수: 1
//        [2]


3) Map: 키/값 한 쌍, 순서 없음, 키 중복 X

package lec14.collectionframework;

import java.util.HashMap;
import java.util.LinkedHashMap;

public class Map07 {
	public static void main(String[] args) {
		// hashcode: 객체를 식별하기 위한 정수값
		// 모든 객체는 hashCode() 매서드를 상속받음
		
		
		// map 은 key, value 형태를 가지며 HashMap, LinkedHashMap은 map을 상속받은 형태
		
		// HashMap: 순서에 상관없이 삽입 (많이 씀)
		HashMap hashmap = new HashMap();
		hashmap.put("국가1", "한국");
		hashmap.put("국가2", "미국");
		hashmap.put("국가3", "중국");
		hashmap.put("국가4", "러시아");
		hashmap.put("국가5", "일본");
		
		System.out.println(hashmap.toString());
		
		
		// LinkedHashMap : 순서가 있음. HashMap 을 순차적으로 정렬
		LinkedHashMap lkHashMap = new LinkedHashMap();
		lkHashMap.put("국가1", "한국");
		lkHashMap.put("국가2", "미국");
		lkHashMap.put("국가3", "중국");
		lkHashMap.put("국가4", "러시아");
		lkHashMap.put("국가5", "일본");
		
		System.out.println(lkHashMap.toString());
		
		
		// 해쉬코드 출력1
		String testA1 = "a";
		String testA2 = "a";
		
		int hc1 = testA1.hashCode();
		int hc2 = testA2.hashCode();
		
		System.out.println("hc1 ::: " + hc1);
		System.out.println("hc2 ::: " + hc2);
		
		
		// 해쉬코드 출력2
		String nationName1 = String.valueOf("한국");
		String nationName2 = String.valueOf("한국");
		
		int nn1hc = nationName1.hashCode();
		int nn2hc = nationName2.hashCode();
		
		System.out.println("nn1hc ::: " + nn1hc);
		System.out.println("nn2hc ::: " + nn2hc);
		
	}
}

 

 

3. 배열 vs 리스트

1) 크기의 가변성:

- 배열: 배열의 크기는 선언할 때 결정되며 동적으로 변경할 수 없다.

- 리스트: 동적으로 조정될 수 있다. 따라서 리스트는 새로운 요소를 추가하거나 제거할 때 자동으로 조절된다

 

2) 데이터 타입의 가변성: 

- 배열: 한 가지 데이터 타입으로만 구성된다. 

- 리스트: Generic 을 사용해 여러 데이터 타입을 담을 수 있다.

 

3) 매서드 지원

길이, 인덱스 외에 리스트는 다양한 메서드를 제공한다