관리 메뉴

거니의 velog

230822_컬렉션 프레임워크 1 본문

대덕인재개발원_자바기반 애플리케이션

230822_컬렉션 프레임워크 1

Unlimited00 2023. 8. 22. 19:19
1. 컬렉션 프레임워크

2. 스레드(동시에 여러 개의 작업을 실행할 수 있는 기술)

3. 자바 입출력 – 파일에 데이터 저장하고 읽어오는 기술

4. 네트워크 – 통신으로 다른 컴퓨터와 데이터를 주고 받는 기술, 데이터베이스와 연동해서 작업. 마이바티스 사용.

5. 웹 서블릿.

6. 중간 프로젝트 시작

 

<컬렉션 프레임워크>

List, Set, Map

100이란 데이터 하나를 저장해서 쓰려면? 변수 선언해야 함.

숫자가 여러 개가 있다면? 한 묶음으로 저장하기 위해서는 배열을 사용.

배열의 단점? 배열은 크기를 한 번 정하면 변동 불가.

이러한 단점을 상쇄시키기 위해서 만들어진 것이 컬렉션.

특히 이 중에서도 List가 배열을 대신해서 쓰는 객체.

컬렉션은 쉽게 생각하면 많은 데이터를 저장하기 위한 객체.

Set도 배열과 비슷하나 데이터를 중복시킬 수 없음. 데이터 자체가 키 값이 되기 때문.

 

그 중에 우리가 맨 처음할 것이 List 계열.


[VectorTest.java]

package kr.or.ddit.basic;

import java.util.Vector;

public class VectorTest {

	public static void main(String[] args) {
		
		// 컬렉션에는 기본적으로 객체만 저장 가능.
		// Vector? List와 같다.
		// 컬렉션이 자바 맨 처음 만들어질 때부터 제공된 것이 아닌, 많은 양의 데이터를 저장하는 편한 객체가 필요할 것이라 생각해서 벡터를 만듦.
		// 처음부터 컬렉션 그룹 안에 포함된 것이 아니고 체계화해서 만든 것이 아닌, List 객체, Map 객체, Set 객체 따로 관리.
		// 자바 설계자들이 따로 놓는 것보다 공통점을 찾아서 한 묶음으로 컬렉션을 만든 것.
		// 컬렉션 그룹이 만들어 지기 이전에 만들어진 것. List와 사용하는 명령이 거의 같다.
		
		// 동기화 처리. 스레드에서 여러 개의 객체가 한 개의 데이터를 동시에 사용하는 것. 
		// 이 동시에 이루어지는 작업이 하나의 데이터를 바라보면 변질될 가능성이 있다. 이를 방지하기 위해 쓰는 기술이 동기화.
		// 동기화 처리가 벡터에는 자동으로 되어 있다. 기능이 좋을 것 같지만, 동기화 처리를 위해 컴퓨터 자원을 더 많이 사용한다.
		// 메모리 자원이 더 낭비될 가능성이 있으므로, 평상시에는 리스트에는 동기화 처리가 안 되어 있다.
		// 지금은 자원을 좀 더 활용하는 차원에서 리스트를 쓰고, 벡터를 잘 사용하지 않음.
		
		// 객체 생성
		Vector<Object> v1 = new Vector<Object>();
		
		// 배열의 단점을 해소하기 위해 만들어짐(배열 크기 변경 가능)
		// 객체를 만들면 저 안에 10개 짜리 배열이 만들어짐. 데이터 추가하다가 10개가 넘어가면 현재 배열의 크기 2배의 배열을 추가로 만들고, 11번째 배열에 넣는다.
		// 우리가 보기에는 데이터를 계속 추가하고 삭제하면 벡터의 크기가 자동으로 조절되는 것처럼 보이는 것.
		System.out.println("처음 크기 : " + v1.size()); // 처음 크기 : 0. 객체는 있으나 데이터가 없는 상태
		
		// 데이터 추가하기 1 : add(추가할 데이터)
		// 반환값 : 추가 성공(true), 추가 실패(false)
		v1.add("aaaa"); // String 객체가 1개 들어감.
		v1.add(new Integer(111)); // 이전에는 new Integer(111)로 객체화 해야 들어갔다. 
		v1.add(123); // 요즘은 메서드의 매개 변수가 데이터를 받아들여서 데이터 타입을 판단하고 해당 타입에 맞게 데이터를 객체로 auto boxing 해 준다. auto unboxing도 자동으로 들어감.
		
		// 오토 박싱, 오토 언박싱이 지원된다.
		v1.add('a');
		v1.add(true);
		
		boolean r = v1.add(3.14);
		
		System.out.println("현재 크기 : " + v1.size()); // 현재 크기 : 5
		System.out.println("float형 데이터가 Vector에 잘 들어갔는가? : " + r); // float형 데이터가 Vector에 잘 들어갔는가? : true
		
		// 데이터 추가하기2 : addElement(추가할 데이터)
		// 		==> 이전 버전의 프로그램과 호환성을 위해서 남아 있는 메서드
		v1.addElement("CCC");
		
		System.out.println("v1 ==> " + v1.toString()); // v1 ==> [aaaa, 111, 123, a, true, 3.14, CCC]. 출력시 toString() 생략 가능.
		
		// 데이터 추가하기3 : add(index, 추가할 데이터)
		// 		==> 'index'번째에 '추가할데이터'를 끼워 넣는다.
		// 		==> 'index'는 0부터 시작한다.
		// 		==> 반환값은 없다.
		v1.add(1, "KKK");
		System.out.println("v1 ==> " + v1); // v1 ==> [aaaa, KKK, 111, 123, a, true, 3.14, CCC]
		
		// 데이터 꺼내오기 : get(index)
		// 		==> 'index'번째의 데이터를 꺼내서 반환한다.
		System.out.println("0번째 데이터 : " + v1.get(0)); // 0번째 데이터 : aaaa
		
		Integer iTemp = (Integer) v1.get(2); // 꺼내온 111은 Object 객체형 데이터 이므로 (Integer) 로 다운 캐스팅해야 한다.
		int iTemp2 = (int) v1.get(2); // 꺼내온 111은 Integer 객체형 데이터 이므로 (int) 로 다운 캐스팅해야 한다.
		System.out.println("iTemp : " + iTemp); // iTemp : 111
		System.out.println("2번째 데이터 : " + iTemp2); // 2번째 데이터 : 111
		
		System.out.println();
		
		// 데이터 수정(변경)하기 : set(index, 새로운데이터)
		// 		==> 'index'번째의 데이터를 '새로운데이터'로 변경한다.
		// 		==> 반환값 : 변경되기 전의 원래 데이터가 반환된다.
		String sTemp = (String) v1.set(0, "zzzz"); // 변경되기 전 값이 String 객체이므로 (String)으로 다운캐스팅 해야 함.
		System.out.println("v1 ==> " + v1); // v1 ==> [zzzz, KKK, 111, 123, a, true, 3.14, CCC]
		System.out.println("원래의 데이터 : " + sTemp); // 원래의 데이터 : aaaa
		
		// 데이터 삭제하기1 : remove(index) -> 메소드 오버로드
		// 		==> 'index'번째의 데이터를 삭제한다.
		// 		==> 반환값 : 삭제된 데이터
		v1.remove(0);
		System.out.println("삭제 후 v1 ==> " + v1); // 삭제 후 v1 ==> [KKK, 111, 123, a, true, 3.14, CCC]
		
		sTemp = (String) v1.remove(0);
		System.out.println("2번째 삭제 후 v1 ==> " + v1); // 2번째 삭제 후 v1 ==> [111, 123, a, true, 3.14, CCC]
		System.out.println("삭제된 데이터 : " + sTemp); // 삭제된 데이터 : KKK
		
		// 데이터 삭제하기2 : remove(삭제할데이터) -> 메소드 오버로드
		// 		==> '삭제할데이터'를 찾아서 삭제한다.
		// 		==> '삭제할데이터'가 여러 개이면 이 중에 제일 첫번째 자료가 삭제된다.
		// 		==> 반환값 : 삭제성공(true), 삭제실패(false)
		// 		==> '삭제할데이터'가 'Integer형'이거나 'char형'일 경우에는 반드시 객체.valueOf()로 변환해서 사용해야 한다.
		
		v1.remove("CCC");
		System.out.println("CCC 삭제 후 v1 ==> " + v1); // CCC 삭제 후 v1 ==> [111, 123, a, true, 3.14]
		
		// Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 123
//		v1.remove(123); // 메소드 오버로딩으로 인해 123 이라는 숫자를 index로 인식.
		
//		v1.remove(new Integer(123)); // 방법 1 : v1 안에 들어간 데이터는 Integer(123)이므로 매개변수 값을 동일하게 바꾸면 가능. ==> 자바버전 1.9 이상에서 사용 불가로 변경되었다.
		v1.remove(Integer.valueOf(123)); // 방법 2. 더 선호되는 방법.
		
		System.out.println("123 삭제 후 v1 ==> " + v1); // 123 삭제 후 v1 ==> [111, a, true, 3.14]
		
		// Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 97
//		v1.remove('a'); // char는 'a'를 97로 인식하므로 자동으로 int 형변환이 일어남. 따라서 index로 메소드 오버로딩이 일어난 것.
		v1.remove(Character.valueOf('a'));
		System.out.println("'a' 삭제 후 v1 ==> " + v1); // 'a' 삭제 후 v1 ==> [111, true, 3.14]
		
		v1.remove(3.14);
		System.out.println("3.14 삭제 후 v1 ==> " + v1); // 3.14 삭제 후 v1 ==> [111, true]
		
		v1.remove(true);
		System.out.println("true 삭제 후 v1 ==> " + v1); // true 삭제 후 v1 ==> [111]
		
		// 전체 데이터 삭제하기 : clear();
		v1.clear();
		System.out.println("clear() 후 v1 ==> " + v1); // clear() 후 v1 ==> []
		System.out.println("현재 크기 : " + v1.size()); // 현재 크기 : 0
		System.out.println();
		
		//-------------------------------------------------
		
		/* 
		 * 제네릭타입(Generic Type) ==> 클래스 내부에서 사용할 데이터 타입을 객체를 생성할 때 외부에서 지정해 주는 기법으로
		 * 							  객체를 선언할 때 (<  >) 안에 그 객체의 내부에서 사용할 데이터의 타입을 지정해 주는 것을 말한다. 
		 *							 - 이런 식으로 선언하게 되면 그 데이터 타입 이외의 다른 종류의 데이터를 저장할 수 없다.
		 * 							 - 이 때 제네릭으로 선언 될 수 있는 데이터 타입은 클래스형 이어야 한다.
		 * 							      그래서 int는 Integer, boolean은 Boolean, char는 Character 등으로 대체해서 사용해야 한다.
		 * 							 - 제네릭 타입으로 선언하게 되면 데이터를 꺼내올 때 별도의 형변환이 필요하지 않는다.
		*/
		
		Vector<Integer> v2 = new Vector<Integer>(); // int형 자료만 저장할 수 있는 Vector
		Vector<String> v3 = new Vector<String>(); // String형 자료만 저장할 수 있는 Vector
		
		v3.add("안녕하세요");
//		v3.add(123); // 오류 : 지정한 제네릭 타입과 다른 종류의 데이터를 저장할 수 없다.
		
		String sTemp2 = v3.get(0); // 형변환 없이 데이터를 꺼내올 수 있다.
		
		Vector<Vector> vv = new Vector<Vector>(); // 2차원 배열.
		Vector<Vector<Vector>> vvv = new Vector<Vector<Vector>>(); // 3차원 배열.
		
		System.out.println("-------------------------------------");
		System.out.println();
		
		//-------------------------------------------------
		
		v3.clear();
		System.out.println("v3의 size : " + v3.size()); // v3의 size : 0
		
		v3.add("AAA");
		v3.add("BBB");
		v3.add("CCC");
		v3.add("DDD");
		v3.add("EEE");
		
		Vector<String> v4 = new Vector<String>();
		v4.add("BBB");
		v4.add("EEE");
		
		System.out.println("v3 ==> " + v3); // v3 ==> [AAA, BBB, CCC, DDD, EEE]
		System.out.println("v4 ==> " + v4); // v4 ==> [BBB, EEE]

		// 데이터 삭제하기3 : removeAll(Collection객체)
		// 			 ==> 벡터의 데이터 중에서 'Collection객체'가 가지고 있는 모든 데이터를 삭제한다.
		// 			 ==> 반환값 : 삭제성공(true), 삭제실패(false)
		v3.removeAll(v4);
		
		System.out.println("삭제 작업 후 v3 ==> " + v3); // 삭제 작업 후 v3 ==> [AAA, CCC, DDD]
		System.out.println("삭제 작업 후 v4 ==> " + v4); // 삭제 작업 후 v4 ==> [BBB, EEE]
		
		System.out.println("-------------------------------------");
		System.out.println();
		v3.clear();
		
		v3.add("AAA");
		v3.add("BBB");
		v3.add("CCC");
		v3.add("DDD");
		v3.add("EEE");
		
		// 벡터에 저장된 데이터들을 순서대로 가져와 사용하고 싶으면 반복문을 사용하면 된다.
		// (주로 for문 사용)
		for(int i=0; i<v3.size(); i++) {
			System.out.println(i + "번째 데이터 : " + v3.get(i));
		}
		
//		0번째 데이터 : AAA
//		1번째 데이터 : BBB
//		2번째 데이터 : CCC
//		3번째 데이터 : DDD
//		4번째 데이터 : EEE
		
		System.out.println("-------------------------------------");
		
		for(String str : v3) {
			System.out.println(str);
		}
		
//		AAA
//		BBB
//		CCC
//		DDD
//		EEE
		
		System.out.println("-------------------------------------");
	}

}

[ArrayTest01.java]

package kr.or.ddit.basic;

import java.util.ArrayList;

public class ArrayTest01 {

	public static void main(String[] args) {
		
		// ArrayList의 기본적인 사용법은 Vector와 같다.
		ArrayList<Object> list1 = new ArrayList<Object>();
		
		// add()메서드로 데이터를 추가한다.
		list1.add("aaa");
		list1.add("bbb");
		list1.add(123);
		list1.add('k');
		list1.add(false);
		list1.add(12.34);
		
		System.out.println("size : " + list1.size()); // size : 6
		System.out.println("list1 ==> " + list1); // list1 ==> [aaa, bbb, 123, k, false, 12.34]
		System.out.println();
		
		// get()메서드를 이용해서 데이터를 꺼내온다.
		System.out.println("1번째 자료 : " + list1.get(1)); // 1번째 자료 : bbb
		System.out.println();
		
		// 데이터 끼워넣기도 같다.
		list1.add(3, "ZZZ");
		System.out.println("list1 ==> " + list1); // list1 ==> [aaa, bbb, 123, ZZZ, k, false, 12.34]
		System.out.println();
		
		// 데이터 변경하기
		String sTemp = (String) list1.set(3, "YYY");
		System.out.println("3번째 자료 변경 후 list1 ==> " + list1); // 3번째 자료 변경 후 list1 ==> [aaa, bbb, 123, YYY, k, false, 12.34]
		System.out.println("sTemp ==> " + sTemp); // sTemp ==> ZZZ
		System.out.println();
		
		// 삭제도 같다.
		list1.remove(3);
		System.out.println("3번째 자료 삭제 후 list1 ==> " + list1); // 3번째 자료 삭제 후 list1 ==> [aaa, bbb, 123, k, false, 12.34]
		
		list1.remove("bbb");
		System.out.println("bbb 자료 삭제 후 list1 ==> " + list1); // bbb 자료 삭제 후 list1 ==> [aaa, 123, k, false, 12.34]
		System.out.println("-------------------------------------");
		System.out.println();
		
		// 제네릭을 사용할 수 있다.
		ArrayList<String> list2 = new ArrayList<String>();
		list2.add("AAAA");
		list2.add("BBBB");
		list2.add("CCCC");
		list2.add("DDDD");
		list2.add("EEEE");
		
		for(int i=0; i<list2.size(); i++) {
			System.out.println(i + " ==> " + list2.get(i));
		}
		System.out.println("-------------------------------------");
		System.out.println();
		
//		0 ==> AAAA
//		1 ==> BBBB
//		2 ==> CCCC
//		3 ==> DDDD
//		4 ==> EEEE
		
		System.out.println("-------------------------------------");
		
		for(String str : list2) {
			System.out.println(str);
		}
		
//		AAAA
//		BBBB
//		CCCC
//		DDDD
//		EEEE
		
		System.out.println("-------------------------------------");
		
		// contains(비교객체) ==> 리스트에 저장된 데이터 중에서  '비교객체'가 있으면 true, 없으면 false
		
		System.out.println("list2 ==> " + list2); // list2 ==> [AAAA, BBBB, CCCC, DDDD, EEEE]
		System.out.println("DDDD 데이터의 존재 여부 : " + list2.contains("DDDD")); // DDDD 데이터의 존재 여부 : true
		System.out.println("ZZZZ 데이터의 존재 여부 : " + list2.contains("ZZZZ")); // ZZZZ 데이터의 존재 여부 : false
		
		// indexOf(비교객체)
		// lastIndexOf(비교객체) ==> 리스트에 '비교객체'가 있으면 '비교객체'가 저장된 index값을 반환하고
		// 					  	      없으면 -1을 반환한다.
		// - indexOf() 메서드는 앞에서 뒤쪽 방향으로 검색하고, lastIndexOf() 메서드는 뒤에서 앞쪽 방향으로 검색한다.
		// - 중복 데이터가 있는 경우 즉, 찾아진 데이터가 많으면 첫번째로 찾은 데이터의 위치(index)값을 반환한다.
		
		list2.add("AAAA");
		list2.add("BBBB");
		list2.add("CCCC");
		list2.add("DDDD");
		list2.add("EEEE");
		
		System.out.println("list2 ==> " + list2); // list2 ==> [AAAA, BBBB, CCCC, DDDD, EEEE, AAAA, BBBB, CCCC, DDDD, EEEE]
		System.out.println("DDDD의 위치값 : " + list2.indexOf("DDDD")); // DDDD의 위치값 : 3, 뒤에 DDDD가 있던 없던 1번째로 찾은 DDDD의 위치값을 반환.
		System.out.println("ZZZZ의 위치값 : " + list2.indexOf("ZZZZ")); // ZZZZ의 위치값 : -1. ZZZZ가 없으므로 -1 반환.
		System.out.println("DDDD의 위치값 : " + list2.lastIndexOf("DDDD")); // DDDD의 위치값 : 8, 뒤에서 찾으므로 8번째 위치값 반환.
		
		System.out.println("-------------------------------------");
		System.out.println();
		
		// toArray() ==> 리스트 안의 데이터를 배열로 변환해서 반환한다.
		// 			 ==> 반환되는 배열은 기본적으로 Object형 배열이 된다.
		
		// toArray(new 제네릭타입이름[0]) ==> 제네릭타입의 배열로 변환해서 반환한다.
		
		Object[] strArr = list2.toArray();
//		String[] strArr = (String[]) list2.toArray(); // 이 방법은 사용할 수 없다. Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
		System.out.println("list의 개수 : " + list2.size()); // list의 개수 : 10
		System.out.println("배열의 개수 : " + strArr.length); // 배열의 개수 : 10
		
		for(int i=0; i<strArr.length; i++) {
			System.out.println(i + "번째 자료 ==> " + strArr[i]);
		}
		
//		0번째 자료 ==> AAAA
//		1번째 자료 ==> BBBB
//		2번째 자료 ==> CCCC
//		3번째 자료 ==> DDDD
//		4번째 자료 ==> EEEE
//		5번째 자료 ==> AAAA
//		6번째 자료 ==> BBBB
//		7번째 자료 ==> CCCC
//		8번째 자료 ==> DDDD
//		9번째 자료 ==> EEEE
		
		System.out.println("-------------------------------------");
		System.out.println();
		
		// 제네릭 타입의 배열로 변환해서 가져오기
		String[] strArr2 = list2.toArray(new String[0]);
		
		for(String s : strArr2) {
			System.out.println(s);
		}
		
//		AAAA
//		BBBB
//		CCCC
//		DDDD
//		EEEE
//		AAAA
//		BBBB
//		CCCC
//		DDDD
//		EEEE
		
	}

}

[ArrayListTest02.java]

package kr.or.ddit.basic;

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

/*
 * 문제 ) 5명의 사람 이름을 입력받아 ArrayList에 추가한 후에
 * 	    ArrayList에 저장된 이름들 중에 '김'씨 성의 이름을 모두 출력하시오.
 * 		(단, 입력은 Scanner 객체를 이용한다.)
 */

public class ArrayListTest02 {
	
	static Scanner sc = new Scanner(System.in);

	public static void main(String[] args) {
		
		ArrayList<String> name = new ArrayList<String>();
		
		for(int i=0; i<5; i++) {
			System.out.print("사람 " + (i+1) + " >> ");
			name.add(sc.nextLine());
		}
		
		System.out.println("5명의 사람 이름 : " + name);
		
		String[] nameArr = name.toArray(new String[0]);
		ArrayList<String> kimArr = new ArrayList<String>();
		
		for(int j=0; j<name.size(); j++) {
			String surname = nameArr[j];
			surname = surname.substring(0, 1);
			if(surname.equals("김")) {
				kimArr.add(nameArr[j]);
			}
		}
		
		System.out.println("김씨 성을 가진 사람 : " + kimArr);
		
	}

}