컬렉션프레임워크

서현서현·2022년 4월 4일
0

JAVA

목록 보기
13/27
post-thumbnail

컬렉션프레임워크

  • List와 Set, Map이 있다
🚨 Map은 key와 Value가 있으므로 컬렉션에 포함되지 않는다!

1. List

ArrayList

List는 인터페이스, ArrayList는 클래스

add() : 데이터 추가

import java.util.List;
import java.util.ArrayList;

public class T01_ArrayListTest {
	
	public static void main(String[] args) {
		// 기본용량 : 10
		List list1 = new ArrayList();
		
		// add() 메서드를 사용해서 데이터를 추가한다
		list1.add("aaa");
		list1.add("bbb");
		list1.add(111); 
			//111이라는 값은 int로 들어오는게 아니다!
			//int값을 integer클래스를 이용해 객체를 가져옴, 즉 여기엔 int가 아니라 
			//Integer 객체!!가 들어옴
		list1.add('k'); 
			//따라서 이것도 마찬가지로 char가 아니라 character클래스 의 객체가 들어옴
		list1.add(true);
		list1.add(12.34);
			// 모든 리스트의 컬렉션 프레임워크에는 **add메소드**가 있다 
			// 왜냐면 인터페이스를 implement했기 때문에 add가 없으면 컴파일이 안됨
			// 즉 모든 list는 add메소드를 가지고있다

size() : 데이터 개수

// size() => 데이터 개수
		System.out.println("size => "+list1.size());
		System.out.println("list1 => "+list1);

get() : 데이터 꺼내오기

// get()으로 데이터 꺼내오기 : 인덱스를 매개변수로!
		System.out.println("1번째 자료: "+list1.get(0));

add() : 데이터 끼워넣기

// 데이터 끼워넣기도 가능하다 : 매개변수 두개
		list1.add(0,"zzz");
		System.out.println("list1 => "+list1);
		

set() : 데이터 변경

// 데이터 변경하기 : set을 이용한다
		String temp = (String) list1.set(0,"YYY");
		System.out.println("temp => "+temp);
		System.out.println("list1 => "+ list1);
		

remove() : 데이터 삭제

		list1.remove(0);
		System.out.println("삭제후 : "+list1);
		
		list1.remove("bbb");
		System.out.println("bbb 삭제후: "+list1);
		//주의!!!!!!!!!!!!!!! 만약 111값과 같은 인티저를 지우고싶다?
		//list1.remove(111);
		//System.out.println("11 삭제후: "+list1); => **오류!!! 111을 index로 인식**
		list1.remove(new Integer(111)); 
		// 해결방법 : **파라미터를 다르게 오버로드해주면 됨**
		System.out.println("111 삭제후: "+list1);


리스트 출력 : Generic 맛보기

위에서 add()를 통해 어떤 타입의 값이든 list에 잘 추가되는것을 알 수 있었다.

그런데!! 나중엔 이게 문제가돼!!

⇒ 예를들어 list에 String타입만 넣고 다른타입은 못들어가게 제한하고싶을때!

⇒ 그럼 이땐 Generic을 사용한다

//제네릭을 지정하여 선언 해보자
//List list1 = new ArrayList(); << 아까는 이렇게 선언했음!
		List<String> list2 = new ArrayList<String>();
		list2.add("AAA");
		list2.add("BBB");
		list2.add("CCC");
		list2.add("DDD");
		list2.add("EEE");
	// list1.add(111); 이거 이제 안돌아감 String타입이 아니니까!
		for(int i=0; i<list2.size(); i++) {
			System.out.println(i+" : " + list2.get(i));
		}
		System.out.println("----------------------------------------------");
		//향상된 for문(for-each)으로도 list를 출력 할 수 있다
		for(String s : list2) {
			System.out.println(s);
		}
		System.out.println("----------------------------------------------");


contains() : 객체가 있으면 true 없으면 false

//contains(비교객체); => 리스트에 '비교객체'가 있으면 true 없으면 false 리턴
		System.out.println(list2.contains("DDD"));
		System.out.println(list2.contains("ZZZ"));

indexOf(): 비교객체가 있는 index값을 반환(없으면 -1 반환)

// indexOf(비교객체); => 리스트에서 '비교객체'를 찾아 '비교객체'가 있는 index값을 반환한다.없으면 -1 반환
	System.out.println("DDD의 index값: "+ list2.indexOf("DDD"));
	System.out.println("ZZZ의 index값: "+ list2.indexOf("ZZZ"));
	System.out.println("-----------------------------------------------");

toArray() : 리스트를 배열로 바꾸기 (!캐스팅불가!)

		//리스트를 배열로 만드는 toArray()에서 캐스팅은 되지 않는다
		Object[] strArr = list2.toArray();
		// String[] strArr2 = (String [])list2.toArray(); -> 캐스팅 안되므로 
		// 런타임중에(실행중에) 예외 발생
		System.out.println("배열의 갯수: "+strArr.length);
		
		// 그렇다면 리스트의 제네릭 타입에 맞는 자료형의 배열로 변환하는 방법?
		// => 제네릭타입의 0개짜리 배열을 생성해서 매개변수로 넣어준다!
		// 형식) toArray(new 제너릭타입[0]) 또는 toArray(new 제너릭타입[]{})
		String[] strArr2 = list2.toArray(new String[0]);
		System.out.println("strArr의 갯수: "+ strArr.length);
		
		// 지우기
		for(int i=0; i<list2.size();i++) {
			list2.remove(i);
		}
		System.out.println(list2.size()); 
		// 왜 0이아니라 2가 떠? 
		// = arrayList는 내부적으로 배열, 한개 지우면 다 떙겨지고, 
		// 그다음지우면 또 땡겨지고 해서 다 안지워진것(그림그려보면 느낌옴)
		// 끝에서부터 지우면 해결!
	}

}


LinkedList (stack, queue)

스택과 큐를 linkedList와 결합하여 만들어보자

import java.util.LinkedList;

public class T02_StackQueueTest {

	public static void main(String[] args) {
		/*	stack => LIFO 
		 *	queue => FIFO
		 */

		LinkedList<String> stack = new LinkedList<String>();
		
		/* 		stack의 명령
		 * 		1) 자료입력 : push(저장할 값)
		 * 		2) 자료출력 : pop() => 자료를 꺼내온 후 꺼내온 자료를 stack에서 삭제
		 */
		

stack.push()

		stack.push("홍길동");
		stack.push("일지매");
		stack.push("변학도");
		stack.push("강감찬");
		System.out.println("현재 stack 값들: "+stack);

stack.pop()

		String data = stack.pop();
		System.out.println("꺼내온 자료: "+data);
		System.out.println("꺼내온 자료: "+stack.pop());
		System.out.println("현재 stack 값들: "+stack);
		stack.push("성춘향");
		System.out.println("현재 stack 값들: "+stack);
		System.out.println("꺼내온 자료: "+stack.pop());
		
		System.out.println("==================================");
		System.out.println();

LinkedList<String> queue = new LinkedList<String>();
		
		/* 		queue의 명령
		 * 		1) 자료입력 : offer(저장할 값)
		 * 		2) 자료출력 : poll() => 자료를 Queue에서 꺼내온 후 꺼내온 자료는 Queue에서 삭제
		 */

queue.offer()

		queue.offer("홍길동");
		queue.offer("일지매");
		queue.offer("변학도");
		queue.offer("강감찬");
		System.out.println("현재 queue의 값:"+queue);

queue.poll()

String temp = queue.poll();
		System.out.println("꺼내온자료: "+temp);
		System.out.println("꺼내온자료: "+queue.poll());
		System.out.println("현재 queue의 값: "+queue);
		
		if(queue.offer("성춘향")) {
			System.out.println("신규등록자료 : 성춘향");
		}
		System.out.println("현재 queue의 값 :"+queue);
		System.out.println("꺼내온 자료 :"+queue.poll());
		
		
	}}


arrayList와 linkedList

arrayList는 내부적으로 배열이다. 따라서 인덱스만 알면 원하는 데이터에 접근 가능

그러나 데이터를 삭제할때 빈공간을 하나씩 땡겨줘야됨. 즉 0번을 지우면 뒤의 몇만개의 배열을 옮기는 일이 발생해 속도가 느려질 수 있다! (끼워넣기도 마찬가지)
linkedList는 그냥 사이에 바로 끼워넣기가 가능, 그러나 검색시 링크를 따라 계속 이동해야하므로(?) 검색시 효율적이지 않다. 따라서 일반적으로 arrayList를 많이 사용한다.


Sort(정렬)

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class T03_ListSortTest {	
	public static void main(String[] args) {
		
		List<String> list = new ArrayList<String>();
		
		list.add("일지매");
		list.add("홍길동");
		list.add("성춘향");
		list.add("변학도");
		list.add("이순신");
		System.out.println("정렬 전 :" + list);

Comparable : Collections.sort(list)

		// 정렬은 Collections.sort() 메서드를 이용하여 정렬한다.
		// 정렬은 기본적으로 '오름차순 정렬'을 수행한다.
		
		// 정렬 방식을 변경하려면 정렬방식을 결정하는 객체를 만들어서
		// Collections.sort() 메서드에 인수로 넘겨주면 된다
		
		// 컬렉션은 인터페이스, 컬렉션스는 클래스(컬렉션에 관련한 메소드 있음)

		Collections.sort(list); 
		// 오름차순 정렬 (java.doc에서 String객체 문서 보면 **Comparable**에 정의 되어있음, 
		// 즉 list안의 애들이 오름차순으로 구현 되어있음.. 리스트안에 객체 넣는순간 자동정렬)
		System.out.println("정렬 후 :"+ list);
		
		Collections.shuffle(list); // 데이터를 섞어준다
		System.out.println("자료 섞기 후 :"+list);

Comparator : Collections.sort(list, new Desc())

		// 정렬방식을 결정하는 객체(정렬자)를 이용하여 정렬하기
		
		Collections.sort(list, new Desc()); 
		// compare메소드를 갖고있음 Comparator를 implement 했으니까
		System.out.println("외부정렬자 정렬 후 :"+list);
	}
}
class Desc implements Comparator<String> {

	// compare() 반환값을 결정하는 방법
	// => 이 메서드가 양수를 반환하면 두 값의 순서가 바뀐다 (오름차순이 디폴트)
	
	// 오름차순 정렬일경우,
	// => 값이 크면 양수, 같으면0, 앞의값이 작으면 음수를 반환하도록 한다.
	
	// String객체는 정렬을 위해서 compareTo() 메소드가 구현되어있는데 
	// 이 메서드의 반환값은 오름차순에 맞게 반환되도록 구현되어있다
	
	@Override
	public int compare(String str1, String str2) {
		return str1.compareTo(str2)*-1; //값을 반대로 리턴하게 만들어 내림차순 완성
	}
	
	
}


Generic 맛보기 - <사용자 정의객체>

이전엔 String클래스로 정렬했다면 이번엔 사용자정의객체로 해보자

package kr.ddiot.basic;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class T04_ListSortTest {
	public static void main(String[] args) {
		
		List<Member> memList = new ArrayList<Member>();
		
		memList.add(new Member(1,"홍길동","010-1111-1111"));
		memList.add(new Member(5,"변학도","010-1111-2222"));
		memList.add(new Member(9,"성춘향","010-1111-3333"));
		memList.add(new Member(3,"이순신","010-1111-4444"));
		memList.add(new Member(6,"강감찬","010-1111-5555"));
		memList.add(new Member(2,"일지매","010-1111-6666"));
		
		System.out.println("정렬전 ");
		for(Member mem : memList) {
			System.out.println(mem);
		}
		System.out.println("-------------------------------------------------");
		
class Member implements Comparable<Member> {
	private int num;
	private String name;
	private String tel;
	public Member(int num, String name, String tel) {
		super();
		this.num = num;
		this.name = name;
		this.tel = tel;
	}
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	@Override
	public String toString() {
		return "Member [num=" + num + ", name=" + name + ", tel=" + tel + "]";
	}

	//Comparable을 임플리먼트하면 결국 compareTo()를 구현해야한다는 뜻
	
	//이름을 기준으로 오름차순정렬이 되도록 설정한다.
	@Override
	public int compareTo(Member mem) {
		// String에 compare가 이미 구현이 되어있지. 그래서int인 애들은 compareTo가 안되네
		//나랑 mem을 비교하므로, 나자신은 getter를 통해 얻어온다
		// compareTo()메소드는 String객체에 저장되어있음. 오름차순으로!
		return this.getName().compareTo(mem.getName());
	}
	
}

		Collections.sort(memList);
		
		System.out.println("정렬후 (이름 오름차순) ");
		for(Member mem : memList) {
			System.out.println(mem);
		}
		System.out.println("-------------------------------------------------");

		// 외부정렬자 사용하기
		Collections.sort(memList, new SortNumDesc());
		
		System.out.println("정렬후 (번호 내림차순) ");
		for(Member mem : memList) {
			System.out.println(mem);
		}
		System.out.println("-------------------------------------------------");		
	}
}
// 외부정렬자 사용하여
// Member의 번호(num)의 내림차순으로 정렬하기
class SortNumDesc implements Comparator<Member>{
	@Override
	public int compare(Member mem1, Member mem2) {
//		if(mem1.getNum() > mem2.getNum()) {
//			return -1;
//		}else if(mem1.getNum() == mem2.getNum()){
//			return 0;
//		}else {
//			return 1;
//		}
//	}	
	
	// Integer에도 Comparable<>이 구현되어있음
	// Wrapper클래스에서 제공하는 메서드를 이용하는 방법도 있다
	return new Integer(mem1.getNum()).compareTo(mem2.getNum())*-1;
	}
}


2. Set

HashSet

add()

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class T05_SetTest {
	public static void main(String[] args) {
		
		
		Set hs1 = new HashSet();
		
		//Set에 데이터를 추가할 때도 add()메서드를 사용
		hs1.add("DD");
		hs1.add("AA");
		hs1.add(2);
		hs1.add("CC");
		hs1.add("BB");
		hs1.add(1);
		hs1.add(3);
		
		System.out.println("Set 데이터 : "+hs1);
		System.out.println();
		

//Set은 데이터의 순서(인덱스)가 없고, 중복을 허용하지 않는다
		// 그래서 이미 있는 데이터를 add하면 false를 반환하고, 데이터는 추가되지 않는다
		boolean isAdded = hs1.add("FF");
		System.out.println("중복되지않을때 : "+isAdded);
		System.out.println("Set 데이터: "+hs1);
		System.out.println();
		
		isAdded = hs1.add("CC");
		System.out.println("중복 될 때 : "+isAdded);
		System.out.println("Set 데이터 : "+hs1);

clear(), remove(삭제할자료)

//Set의 데이터를 수정하려면 수정하는 명령이 따로 없기 때문에 해당 자료를
		//삭제한 후 새로운 데이터를 추가해주어야 한다
		
		//삭제하는 메서드
		//1)clear() => Set데이터 전체삭제
		//2)remove(삭제할자료) => 해당자료삭제
		
		// 예) 'FF'를 'EE'로 수정하기
		hs1.remove("FF"); //'FF'자료 삭제
		System.out.println("삭제후 Set데이터: "+hs1);
		System.out.println();
		
		hs1.add("EE"); //EE자료추가
		System.out.println("Set 데이터: "+hs1);
		System.out.println();
		
		//hs1.clear(); 전체자료 삭제
		//System.out.println("clear후 Set 데이터: "+hs1);
		System.out.println("Set의 자료 개수 : "+hs1.size());
		System.out.println();

iterator() : 데이터 하나씩 얻기

//Set은 데이터의 순서가 없기 떄문에 List처럼 인덱스를 이용해 하나씩 불러올 수 없다
		//그래서 데이터를 하나씩 얻기 위해서는 Iterator객체를 이용해야 한다
		//=>Set객체의 iterator() 메서드를 호출하면 된다
		Iterator it = hs1.iterator();
		
//데이터 갯수만큼 반복하기
		//hashNext() => 포인터 다음위치에 데이터가 있으면 true, 
		// 없으면 false 반환
		while(it.hasNext()) {
			// 다음자료가 있는지 검사
			// next() => 포인터를 다음 자료위치로 이동하고 이동한 위치의 자료를 반환한다
			System.out.println(it.next());
		}
		
		

		// 1~100 사이의 중복되지 않는 정수 5개 만들기
		Set<Integer> intRnd = new HashSet<Integer>();
		
		while(intRnd.size()<5) {
			int num = (int) (Math.random()*100+1);
			intRnd.add(num);
		}
		
		System.out.println("만들어진 난수들: "+intRnd);
		

자료구조 변경 (HashSet→ArrayList)

//Collection유형의 객체들은 서로다른 자료구조로 쉽게 변경해서 사용할 수 있다.
		// 다른종류의 객체를 생성할 때 매개변수에 변경할 데이터를 넣어주면 된다
		List<Integer> intRndList = new ArrayList<Integer>(intRnd);
		System.out.println("List의 자료 출력...");
		
		for(int i = 1; i<intRndList.size(); i++) {
			System.out.println(intRndList.get(i));
		}
	}
}


Sort(정렬)

TreeSet 예제- TreeSet자동정렬기능이 들어가있다.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

public class T06_SetTest {
	
	public static void main(String[] args) {

		TreeSet<String> ts = new TreeSet<String>();
		List<String> abcList = new ArrayList<String>();
		
		// 영어대문자를 문자열로 변환하여 List에 저장
		for(char ch='A'; ch<='Z'; ch++) {
			String temp = String.valueOf(ch);
			abcList.add(temp);
		}
		
		Collections.shuffle(abcList);
		
		System.out.println("abcList 자료: "+abcList);
		
		for(String str:abcList) {
			ts.add(str);
		}
		
		System.out.println("TreeSet자료: "+ts);
		

조건에맞는 자료 찾기 : headSet(), tailSet(), subSet()

		// TreeSet에 저장된 자료 중 특정한 자료보다 작은 자료를 찾아 
		// SortedSet으로 반환하는 메서드가 있다
		
		// 이진 트리 그리면 왼쪽이 작은값 오른쪽이 큰값이 들어오는데 
		// 이때 왼쪽을 headSet 오른쪽은 tailSet으로 한다
		// 사이의 값을 가져올수도 있을텐데, 이때는 subSet(부분집합)을 사용한다
		// => headSet(기준값) => 기본적으로 **'기준값'은 포함시키지 않는다**
		// => headSet(기준값,논리값) => 논리값이 **true**이면, '기준값' 포함함
		
		SortedSet<String> ss1 = ts.headSet("K");
		System.out.println("K 이전자료: "+ss1); // 기준값 미포함
		System.out.println("K 이전자료(기준값 포함): " 
				+ ts.headSet("K", true));
		
		// 기준값 보다 큰 자료를 찾아 SortedSet으로 반환하는 메소드
		// tailSet(기준값) => **기본적**으로 **기준값을 포함**시킨다
		// tailSet(기준값,논리값) => 논리값이 true이면 기준값 포함함
		
		SortedSet<String> ss2 = ts.tailSet("K");
		System.out.println("K 이후자료: "+ss2); // 기준값 포함
		System.out.println("K 이후자료: "
				+ ts.tailSet("K",false));
		
		
		// subSet(기준값1,기준값2) => 기준값1 ~ 기준값2 사이의 값을 가져옴 
		// ('기준값1' 포함, '기준값2' 미포함)

		// subSet(기준값1,논리값1,기준값2,논리값2) => 각 기준값을 포함할지 여부를 설정한다 
		// (논리값이 true이면 포함, false이면 미포함)
		
		System.out.println("K(포함)부터 N(미포함)까지 :"
				+ ts.subSet("K","N"));
		
		System.out.println("K(포함)부터 N(포함)까지 :"
				+ ts.subSet("K",true,"N",true));
		
		System.out.println("K(포함)부터 N(미포함)까지 :"
				+ ts.subSet("K",false,"N",false));
		
		System.out.println("K(포함)부터 N(포함)까지 :"
				+ ts.subSet("K",false,"N",true));
		
	}
}

HashSet 예제 - equals(), hashCode()

package kr.ddiot.basic;

import java.util.HashSet;
import java.util.Set;

public class T07_equals_hashCodeTest {
	public static void main(String[] args) {
		
		// 해시함수는 임의의 길이의 데이터를 고정된길이의 데이터로 매핑하는 함수이다
		// 해시함수에 의해 얻어지는 해시값, 해시코드, 해시체크썸 또는 간단하게 해시라고 한다
		// HashSet, HashMap, Hashtable과 같은 객체들을 사용할경우
		// 객체가 서로 같은지 비교하기위해 **equals()메서드와 hashCode()메서드를 호출**한다
		// 그래서 객체가 서로 같은지 여부를 결정하려면 두 메서드를 재정의 해야한다
		// HashSet, HashMap, Hashtable에서는 객체가 같은지 여부는 **데이터를 추가할때 검사**한다
		
		// - equals()는 두 객체의 내용(값)이 같은지 비교하는 메서드이고
		// - hashCode()는 객체에 대한 해시코드값을 반환하는 메서드이다
		// => 해시테이블 생성시 사용된다
		
		// -equals()와 hashCode()에 관련된 규칙(Convention)
		// 1. 두 객체가 같으면 반드시 같은 hashCode를 가져야한다.
		// 2. 두 객체가 같으면 equals()를 호출했을때 true를 반환해야한다.
		//	즉, 객체 a,b가 같다면 a.equals(b)와 b.equals(a) 둘다 true여야 한다
		// 3. **두 객체의 hashCode가 같다고 해서 두 객체가 반드시 같은 객체는 아니다
		//	하지만 두 객체가 같으면 반드시 hashCode가 같아야한다**
		// 4. equals()를 override하면 반드시 hashCode()도 override해야 한다
		// 5. hashCode()는 기본적으로 Heap메모리에 있는 각 객체에 대한 메모리 주소 매핑 정보를 기반으로 한 정수값을 반환한다
		//	그러므로, 클래스에서 hashCode()를 override하지 않으면 절대로 두 객체가 같은것으로 간주 될 수 없다
		
		// -hashCode()에서 사용하는 **'해싱알고리즘'에서 서로다른 객체에 대하여 같은 hashCode값을 만들어 낼 수 있다**
		// 그래서 객체가 같지 않더라도 hashCode가 같을 수 있다
		
		
		System.out.println("Aa".hashCode()); //2112
		System.out.println("BB".hashCode()); //2112
		// 해쉬코드가 같다고해서 같은객체라고 말하지 못한다, 따라서 내부적으로 equals()를 이용해 판단해줘야한다
		
		Person p1 = new Person(1,"홍길동");
		Person p2 = new Person(1,"홍길동");
		Person p3 = new Person(1,"이순신");
		
		System.out.println("p1.equals(p2) : "+p1.equals(p2));
		System.out.println("p1==p2 : "+(p1==p2));
		
		Set<Person> set = new HashSet<Person>();
		set.add(p1);
		set.add(p2);
		System.out.println("p1,p2 등록 후 데이터");
		for(Person p : set) {
			System.out.println(p.getId()+" : "+p.getName());
		}
		
	}

}

class Person{
	private int id;
	private String name;

	public Person(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	
}

새로 클래스 만들었을때 해쉬코드와 이퀄스를 정상적으로 사용하고 싶으면 equals() 해쉬코드 메소드 오버라이드 필요하다

오브젝트에 있는 이 기능을 그대로 쓰면 중복체크가 잘 안돼!

3. Map

  • Collection 인터페이스와는 다른 저장 방식을 가진다.

put()

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class T08_MapTest {
	
//	Map => key값과 value값을 한쌍으로 관리하는 객체
//			key값은 중복을 허용하지않고 순서가 없다 (Set의 특징)
//			value값은 중복을 허용한다.
			
	public static void main(String[] args) {
		Map<String, String>map = new HashMap<String, String>();
		
		//자료추가 => put(key값, value값);
		map.put("name", "홍길동");
		map.put("addr", "대전");
		map.put("tel", "010-1234-5678");
		
		System.out.println("map=> "+map);
		
		//자료수정 => 데이터를 저장할때 key값이 같으면 나중에 입력한 값이 저장된다
		// put(수정할 key값, 새로운key값);
		map.put("addr","서울");
		System.out.println("map=> "+map);
		

remove()

// 자료삭제 => remove (삭제할key값)
		map.remove("name");
		System.out.println("map=> "+map);

get()

// 자료읽기 => get(key값);
		System.out.println("addr=> "+map.get("addr"));
		System.out.println("==================================");

읽어오기(4가지 방법)

1. iterator() : 순회

// key값들을 순회하며 읽어와 자료를 출력하는 방법
		
		// 방법1 => keySet() 이용하기 (key만 모아놓은 집합. Set이니 Iterator 무조건 존재)
		//		=> Map의 key값들만 읽어와 Set형으로 반환한다
		Set<String> keySet = map.keySet();
		
		System.out.println("Iterator를 사용하는 방법");
		Iterator<String>it=keySet.iterator(); //Iterator 이용해서 key 얻어와서 순회
		
		while(it.hasNext()) {
			String key = it.next();
			System.out.println(key+" : "+map.get(key));
		}

2. 향상된for문

// 방법2 => Set형의 데이터를 향상된 for문; 으로 처리하면 Iterator를 사용하지 않아도 된다
		// 향상된for문은 자바문서에서 Iterable<E>이 상위인터페이스일때 쓸 수 있다
		System.out.println("향상된 for문을 이용한 방법");
		for(String key : keySet) {
			System.out.println(key+" : "+map.get(key));
		}
		System.out.println("---------------------------------");
		

3. value() : value값만 읽어오기

// 방법3 => value값만 읽어와 출력하기 => value() 이용하기
		System.out.println("values() 이용한 방법");
		for(String value:map.values()) {
			System.out.println(value);
		}
		System.out.println("-----------------------------------");

4. entrySet()

		// 방법4 => Map관련클래스에는 Map.Entry 타입의 내부 Class가 만들어져 있다
		// 이 내부 클래스는 key와 value라는 멤버변수로 구성되어 있다.
		// Map에서 이 Map.Entry타입(키와 벨류 묶어줌)의 객체들을 Set형식으로 저장하여 관리한다
		
		// Map.Entry 타입의 객체 모두 가져오기 => entrySet() 이용하기
		Set<Map.Entry<String, String>> mapSet = map.entrySet();
		
		// 가져온 Entry객체들을 순서대로 처리하기 위해서 Iterator 객체를 가져온다
		Iterator<Map.Entry<String, String>> entryIt = mapSet.iterator();
		
		while(entryIt.hasNext()) {
			Map.Entry<String, String> entry = entryIt.next();
			
			System.out.println("key 값 : "+entry.getKey());
			System.out.println("Value 값 : "+entry.getValue());
			System.out.println();
		}
	}
}
// Iterator는 향상된 for문으로 대체될 수 있다
CRUD 해보자
package kr.ddiot.basic;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

/*
문제) 이름, 주소, 전화번호 속성을 갖는 Phone클래스를 만들고, 이 Phone클래스를 이용하여 
	  전화번호 정보를 관리하는 프로그램을 완성하시오.
	  이 프로그램에는 전화번호를 등록, 수정, 삭제, 검색, 전체출력하는 기능이 있다.
	  
	  전체의 전화번호 정보는 Map을 이용하여 관리한다.
	  (key는 '이름'으로 하고 value는 'Phone클래스의 인스턴스'로 한다.)

실행예시)
===============================================
   전화번호 관리 프로그램(파일로 저장되지 않음)
===============================================

  메뉴를 선택하세요.
  1. 전화번호 등록
  2. 전화번호 수정
  3. 전화번호 삭제
  4. 전화번호 검색
  5. 전화번호 전체 출력
  0. 프로그램 종료
  번호입력 >> 1  <-- 직접 입력
  
  새롭게 등록할 전화번호 정보를 입력하세요.
  이름 >> 홍길동  <-- 직접 입력
  전화번호 >> 010-1234-5678  <-- 직접 입력
  주소 >> 대전시 중구 대흥동 111  <-- 직접 입력
  
  메뉴를 선택하세요.
  1. 전화번호 등록
  2. 전화번호 수정
  3. 전화번호 삭제
  4. 전화번호 검색
  5. 전화번호 전체 출력
  0. 프로그램 종료
  번호입력 >> 5  <-- 직접 입력
  
  =======================================
  번호   이름       전화번호         주소
  =======================================
   1    홍길동   010-1234-5678    대전시
   ~~~~~
   
  =======================================
  출력완료...
  
  메뉴를 선택하세요.
  1. 전화번호 등록
  2. 전화번호 수정
  3. 전화번호 삭제
  4. 전화번호 검색
  5. 전화번호 전체 출력
  0. 프로그램 종료
  번호입력 >> 0  <-- 직접 입력
  
  프로그램을 종료합니다...
  
*/
public class T09_PhoneBookTest {
	private Scanner scan;
	private Map<String, Phone> phoneBookMap;
	
	public T09_PhoneBookTest() {
		scan = new Scanner(System.in);
		phoneBookMap = new HashMap<String, Phone>();
	}
	
	// 메뉴를 출력하는 메서드
	public void displayMenu(){
		System.out.println();
		System.out.println("메뉴를 선택하세요.");
		System.out.println(" 1. 전화번호 등록");
		System.out.println(" 2. 전화번호 수정");
		System.out.println(" 3. 전화번호 삭제");
		System.out.println(" 4. 전화번호 검색");
		System.out.println(" 5. 전화번호 전체 출력");
		System.out.println(" 0. 프로그램 종료");
		System.out.print(" 번호입력 >> ");		
	}
	
	// 프로그램을 시작하는 메서드
	public void phoneBookStart(){
		System.out.println("===============================================");
		System.out.println("   전화번호 관리 프로그램(파일로 저장되지 않음)");
		System.out.println("===============================================");
		
		while(true){
			
			displayMenu();  // 메뉴 출력
			
			int menuNum = scan.nextInt();   // 메뉴 번호 입력
			
			switch(menuNum){
				case 1 : insert();		// 등록
					break;
				case 2 : update();		// 수정
					break;
				case 3 : delete();		// 삭제
					break;
				case 4 : search();		// 검색
					break;
				case 5 : displayAll();	// 전체 출력
					break;
				case 0 :
					System.out.println("프로그램을 종료합니다...");
					return;
				default :
					System.out.println("잘못 입력했습니다. 다시입력하세요.");
			} // switch문
		} // while문
	}

	// 새로운 전화번호 정보를 등록하는 메소드
	// 이미 등록된 사람은 등록하지 않는다
	private void insert() {
		System.out.println();
		System.out.println("새로 등록할 전화번호 정보를 입력하세요 ");
		System.out.println("이름 >> ");
		
		String name = scan.next();
		
		// 이미 등록된 사람인지 검사
		// get()으로 값을 가져올때 자료가 없으면 null을 반환한다
		if(phoneBookMap.get(name)!=null) {
			System.out.println(name+"씨는 이미 등록된 사람입니다");
			return;
		}
		
		System.out.println("전화번호 >> ");
		String tel = scan.next();
		scan.nextLine(); //입력버퍼에 남아있는 엔터키값까지 읽어와 버리는 역할을 수행한다
		
		System.out.println("주소 >> ");
		String addr = scan.nextLine();
		
		phoneBookMap.put(name, new Phone(name,tel,addr));
		System.out.println(name+"씨 등록완료");
	}
	
	// 기존 전화번호 정보를 수정하는 메소드
	private void update() {
		System.out.println();
		System.out.println("수정할 전화번호 정보를 입력하세요 ");
		System.out.println("이름 >> ");
		
		String name = scan.next();
		
		// 이미 등록된 사람인지 검사
		// get()으로 값을 가져올때 자료가 없으면 null을 반환한다
		if(phoneBookMap.get(name)!=null) {
			System.out.println(name+"씨 정보는 존재하지 않습니다");
			return;
		}
		
		System.out.println("전화번호 >> ");
		String tel = scan.next();
		scan.nextLine(); //입력버퍼에 남아있는 엔터키값까지 읽어와 버리는 역할을 수행한다
		
		System.out.println("주소 >> ");
		String addr = scan.nextLine();
		
		phoneBookMap.put(name, new Phone(name,tel,addr));
		System.out.println(name+"씨 수정완료");
	}
	
	
	// 전화번호 정보를 삭제하는 메소드
	private void delete() {
		System.out.println();
		System.out.println("삭제할 전화번호 정보를 입력하세요");
		System.out.println("이름 >> ");
		
		String name = scan.next();
		
		if(phoneBookMap.remove(name)==null) {
			System.out.println(name+"씨는 등록된 사람이 아닙니다");
		} else {
			System.out.println(name+"씨 정보를 삭제했습니다.");
		}
		System.out.println("삭제 완료");
	}
	
	
	// 이름을 이용한 전화번호 정보룰 검색하는 메서드
	private void search() {
		System.out.println();
		System.out.println("검색할 전화번호 정보를 입력하세요");
		System.out.println("이름 >> ");
		
		String name = scan.next();
		
		Phone p = phoneBookMap.get(name);
		
		if(p == null) {
			System.out.println(name+"씨의 전화번호 정보가 없습니다");
		} else {
			System.out.println(name+"씨의 정보");
			System.out.println("이름: "+p.getName());
			System.out.println("전화: "+p.getTel());
			System.out.println("주소: "+p.getAddr());
		}
		System.out.println("검색작업 완료");
		
	}
	
	
	
	private void displayAll() {
		Set<String> keySet = phoneBookMap.keySet();
		System.out.println("============================================");
		System.out.println("번호\t이름\t전화번호\t주소");
		System.out.println("============================================");
		
		if(keySet.size() ==0) {
			System.out.println("등록된 전화번호 정보가 하나도 없습니다");
		}else {
			int cnt =1;
			for(String key : keySet) {
				Phone p = phoneBookMap.get(key);
				System.out.println(" "+cnt+"\t"+p.getName()+"\t"+p.getTel()+"\t"+p.getAddr());
				cnt++;
			}
		}
		System.out.println("===============================================");
		System.out.println("출력완료 ㅋㅋ");
	}
	public static void main(String[] args) {
		new T09_PhoneBookTest().phoneBookStart();
	}

}

// 전화번호 정보를 저장 할 수 있는 VO클래스

class Phone {
	private String name;
	private String tel;
	private String addr;
	
	
	public Phone(String name, String tel, String addr) {
		super();
		this.name = name;
		this.tel = tel;
		this.addr = addr;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public String getAddr() {
		return addr;
	}

	public void setAddr(String addr) {
		this.addr = addr;
	}

	@Override
	public String toString() {
		return "Phone [name=" + name + ", tel=" + tel + ", addr=" + addr + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((addr == null) ? 0 : addr.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((tel == null) ? 0 : tel.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Phone other = (Phone) obj;
		if (addr == null) {
			if (other.addr != null)
				return false;
		} else if (!addr.equals(other.addr))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (tel == null) {
			if (other.tel != null)
				return false;
		} else if (!tel.equals(other.tel))
			return false;
		return true;
	}
	
	
	
}

Properties

  • Properties는 Map보다 축소된 기능의 객체라고 할 수 있다
  • Map은 모든형태의 객체데이터를 key와 value값으로 사용 할 수 있지만 Properties는 key와 value값으로 String만 사용 할 수 있다
  • Map은 put(), get()을 이용하여 데이터를 입출력 하지만, Properties는 setProperty(), getProperty() 메서드를 통해 데이터를 입출력한다
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class T10_PropertiesTest {
	
	public static void main(String[] args) throws IOException {

		Properties prop = new Properties();
		
		prop.setProperty("name","홍길동");
		prop.setProperty("tel","010-1234-5678");
		prop.setProperty("addr","대전");
		
		String name = prop.getProperty("name");
		String tel = prop.getProperty("tel");
		
		System.out.println("이름: "+name);
		System.out.println("전화번호: "+tel);
		System.out.println("주소: "+prop.getProperty("addr"));
		
		//내용 파일로 저장하기
		prop.store(new FileOutputStream("src/kr/ddiot/basic/test.properties"), "코멘트입니다");
		
	}

}

0개의 댓글