너굴 개발 일지

TIL_210330_Collection 인터페이스 본문

Java

TIL_210330_Collection 인터페이스

너굴냥 2021. 3. 30. 23:25

Collection FrameWork

자료(데이터) 수집하는 api 프레임 워크로 '데이터 군을 저장하는 클래스들을 표준화한 설계'를 뜻한다.

컬렉션 프레임웍에서는 컬렉션 데이터 그룹을 3가지로 나누었다.

List, Set, Map이 대표적인 인터페이스며 List, Set의 공통 부분을 뽑아 다시 Collection 인터페이스로 추가 정의하였다.

 

 

 

컬렉션 프레임웍의 핵심 인터페이스간 상속계층도

1. List Interface

순서(인덱스)가 있는 데이터의 집합, 데이터 중복 허용 

구현 클래스 : ArrayList, LinkedList, Stack, Vector

예 : 음식집 대기 명단 리스트 (사람들마다 순서가 있고, 중복된 이름이 있을 수도 있어)

 

 

List 상속 계층도

2. Set Interface

 

순서가 없는 데이터의 집합, 중복 허용 X

구현 클래스 : HashSet, TreeSet..

예 : 네발동물 집합 ( 개, 고양이... 집합 요소들이 중복도 안되며 순서 또한 없다)

 

 

Set 상속 계층도

 

3. Map Interface

[ (key), (value) ]의 쌍으로 이루어진 데이터 집합, 순서 X, 중복(키 - X, 값 - O)

구현 클래스 : HashMap, HashTable, Properties...

예 : 사이트 아이디/ 비밀번호 (아이디는 중복되지 않으나 비밀번호는 중복 가능)

 

 

Map 상속 계층도 

 

Collection Interface Method

메서드 설명
booelan add(Object o) Collection에 지정된 객체 추가
boolean contains() Collection에 지정된 객체 포함되었는지 여부 반환
boolean isEmpty() Collection이 비었는지 여부 반환
Iterator iterator() Collection을 itetator 객체로 반환
void clear() Collection의 모든 객체 삭제 
boolean remove(Object o) 지정된 객체 삭제 및 반환 가능
boolean retainAll(Collection c) 지정된 Collection에 포함된 객체만을 남기고 다른 객체들은 Collection에서 삭제
이 작업으로 인해 Collection에 변화가 있으면 true,
아니면 false를 반환
int size() Collection에 저장된 객체의 개수를 반환

 

1-1. ArrayList Class

List 인터페이스를 구현한 클래스로 저장순서가 유지되고, 중복이 허용된다. 데이터 저장 공간은 배열 기반으로 기존의 Vector(동기화)를 개선하였다. 크기가 정해져있지 않고 동적이며 비동기 방식이다. 

 

ArrayList 관련 Method와 예시 

 

메서드 설명
boolean add(Object o) ArrayList의 마지막 객체를 추가, 성공하면 true
int indexOf(Object o) 지정된 객체가 저장된 위치를 반환
int lastIndexOf(Object o) 객체가 저장된 위치를 끝부터 역방향으로 검색해 반환
(오른쪽 -> 왼쪽)
Object set(int index, Object element) 주어진 객체(element)를 지정된 위치(index)에 저장
Object remove(int index / Object o) 지정된 위치나 객체를 제거하고 반환 가능
Iterator iterator() ArrayList의 Iterator 객체를 반환
package com.bjy.list;

import java.util.ArrayList;
import java.util.Iterator;

/** List계열 : 자료 순차적, 중복가능, ex: ArrayList
 * List : 빈틈없는 데이터의 적재라는 장점 취함 (java에서는 허용하는 경우 있음 ) 
 * Array : 크기 정해짐 (정적)
 * ArrayList : 크기가 변동, 동적, 나중에 많이 사용 (비동기: 속도효율 높음)
 * 
 * Vector : 초기 사용 (old ver) 동기적 (속도효율 낮음)**/
public class ArrayListTestClass {

	public ArrayListTestClass() {
		
	}
	
	public static void arrayListTest() {
		ArrayList<String> list = new ArrayList<String>();
		
		 
		list.add("grape");    // index 0
		list.add("orange");   // index 1
		list.add("orange");   // index 2
		list.add("peach");    // index 3
		
		
		System.out.println(list.size()); // 4
		// list = [ grape, orange, orange peach ]
		
		list.add(1, "kiwi");
		// list = [ grape, kiwi, orange, orange peach ]
		
		
		list.set(2, "apple");
		// list = [ grape, kiwi, apple, orange peach ]
		
		list.remove(0);
		list.remove("kiwi");
		// list = [ kiwi, apple, orange peach ]
		// list = [ apple, orange peach ]
		
		int index = list.indexOf("peach");
		// 2
		
		list.add("apple");
		// list = [ apple, orange peach, apple ]
		
		int index2 = list.lastIndexOf("apple");
		// 특정 데이터 중 맨 마지막에 있는 데이터 인덱스 반환  => 3
		
		/** ArrayList 데이터 추출 방법 **/
		
		/** 1. 인덱스 번호가 필요할 경우**/
		for(int i=0;i<list.size();i++) {
			String s = list.get(i);
			System.out.print(s+ " ");
		}
		System.out.println();
		System.out.println("--------------------------");
		
		
		/** 2. 인덱스 번호 필요 없는 경우 **/
		for(String s : list) {
			System.out.print(s + " ");
		}
		System.out.println();
		System.out.println("--------------------------");
		
		/** 3. Iterator 사용 **/
		// iterator() : ArrayList 데이터 순차적(열거)으로 변경
		// boolean hasNext() : 추출할 다음 데이터 있는 지 확인 
		// Collection c.next() : 다음 데이터 추출
		Iterator <String> itr = list.iterator();
		while(itr.hasNext()) {
			System.out.print(itr.next() + " ");
		}
		System.out.println();
		System.out.println("--------------------------");
	
	
	
	
	} // end of arrayListTest()

}

 

1-2. LinkedList Class

배열의 단점인 크기 변경 불가, 비순차적 데이터 추가/삭제에 시간이 걸리는 점을 보완하기 위해 나온 자료구조로 불연속적으로 존재하는 데이터를 서로 연결하는 형태로 되어있다. 또한 자료 변동이 많은 작업에 유리하다.

 

ArrayList, LinkedList 속도 비교 클래스 

package com.bjy.list.linked;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/** List 계열 (public interface List(~~) List 인터페이스 구현 )
 * ArrayList : 자료 변동(추가,삭제) 적을때 유리 , 데이터 추가 삭제시 데이터 자체가 이동 ? (데이터가 담긴 박스 자체를 이동) 
 * 데이터 추가/삭제시 불필요한 데이터 복사 과정 필요 
 * LinkedList : 삽입, 삭제 많은 작업에 유리 ( 자료 변동 많을 때 ) 데이터 추가 삭제시 데이터의 인덱스가 이동 
 * 데이터 추가 삭제시 참조 노드 주소만 변경해주면 되기에 추가, 삭제 편리(연결고리만 바꿔준다고 생각) **/

public class LinkedListTestClass {

	public LinkedListTestClass() {
		
	}
	
	public static void linkedListTet() {
		LinkedList<Character> list = new LinkedList<Character>();
		list.add('a');
		list.add('b');
		list.add('c');
		
		for(Character c : list) {
			System.out.print(c + "\t");
		}
		
		System.out.println();
		
		Iterator<Character> itr = list.iterator();
		while(itr.hasNext()) {
			System.out.print(itr.next() + "\t");
		}
	}
	
	// arraylist, linkedlist 속도 비교 메서드 
	public static void linkedListExample() {
		List<String> arraylist = new ArrayList<String>(); // java.util.List
		List<String> linklist = new LinkedList<String>();
		
		long startTime, endTime;
		
		// arraylist 처리 시간 
		startTime = System.nanoTime();
		
		for(int i=0;i<10000;i++) {
			arraylist.add(String.valueOf(i));
		}
		
		endTime = System.nanoTime();
		
		System.out.println("arraylist 처리 시간 : " + (endTime - startTime));
		
		// linkedlist 처리 시간 
		startTime = System.nanoTime();
		
		for(int i=0;i<10000;i++) {
			linklist.add(String.valueOf(i));
		}

		endTime = System.nanoTime();
		System.out.println("linkedlist 처리 시간 : " + (endTime - startTime));
		
		// 결과는 자료 추가, 삭제에 있어서 LinkedList가 조금 더 빠르다.
	}

}

 

<ArrayList와 LinkedList 비교>

컬렉션 읽기(접근시간) 추가/삭제 비고
ArrayList
(배열기반, 연속적)
빠르다 느리다 순차적 추가 삭제는 더 빠름
비효율적 메모리 사용
( 배열 크게 사용해야 하기 때문에)
LinkedList
(연결기반, 불연속적)
느리다 (바로 다음 요소만 알고
멀리 있는 요소는 모르기에)
빠르다 데이터 많을수록 접근성 떨어짐 

 

 

- ArrayList의 추가와 삭제 

ArrayList의 data[2] (세번째 데이터) 삭제 하는 과정

 

1) 삭제할 데이터의 아래에 있는 데이터를 한 칸씩 위로 복사해 삭제할 데이터를 덮어쓴다

2) 데이터가 모두 한 칸씩 위로 이동하였으므로 마지막 데이터는 null로 변경한다

3) 데이터가 삭제되어 데이터의 size가 줄었으므로 size -1을 해준다.

 

위의 과정을 보면 알겠지만 ArrayList의 add, remove() 는 추가, 삭제만 하고 끝나는 게 아닌 불필요한 데이터 복사 과정을 거쳐 다른 데이터의 위치를 이동시켜줘야 하기 때문에 다루는 데이터 개수가 많을수록 작업시간이 오래 걸린다.

 

 

-  LinkedList 추가와 삭제 

 

링크드 리스트 각 요소(node) 구조

 

데이터 삭제 : 단한번의 참조변경만으로 가능하다.

먼저 링크드 리스트의 각 요소(node) 구조를 보면 다음 요소 주소를 저장하는 Node next; 와 해당 노드의 데이터를 저장하는 Object obj; 로 구성되어 있다. 노드들을 연결한 링크드 리스트의 구조는 위의 사진에 나와있다.

중간에 데이터를 추가/삭제하고 싶으면 연결된 노드의 next, 즉 한번의 참조변경만으로 해주면 쉽게 가능한 것이다.

 

1-3. Stack Class 

list 계열의 클래스로 LIFO (Last In, First Out) 구조를 가지고 있다. 선입 후출의 개념이며 위쪽만 뚫려 있는 박스 형태라고 생각하면 쉽다 .

stack 구조를 옆으로 돌려보면 배열과 비슷하며 배열로 구현하는 것이 좋다.

 

Stack 구조인 LIFO 

Stack Class Method

메서드 설명
Object pop() Stack의 맨 위 저장된 객체를 꺼낸다
(꺼내면 Stack에 저장된 객체수는 감소)
Object peek() Stack의 맨 위 저장된 객체를 반환
pop()처럼 객체를 꺼내진 않는다
Object push(Object item) Stack에 객체(item)를 저장한다
booelan empty() Stack이 비어있는지 알려준다

 

- Queue Interface extends Collection Interface, Iterable Interface

list 인터페이스에 속해 있지는 않지만 큐 인터페이스가 LinkedList에 구현된다. 

Queue의 구조는 FIFO (First In, First Out) 구조로 선입선출되며, 일련의 작업들을 순차적으로 처리하고 싶을 때 사용한다.( 예 : 인터넷 최근 기록 5개 보여주기...용량이 가득 차면 가장 첫번째로 저장된 기록이 첫번째로 삭제된다)

 

Queue의 FIFO 구조 

메서드 설명
boolean add(Object o) 지정된 객체를 Queue에 추가, 성공하면 true 반환
저장공간 부족하면 IIIegalStateException 발생
Object remove() Queue에서 객체를 꺼내 반환, 비어있으면 
NoSuchElementException 발생
Object element() 삭제 없이 요소를 읽어온다. peek과 달리 Queue가 비었을 때
NoSuchElementException 발생
boolean offer(Object o) Queue에 객체를 저장, 성공하면 true 반환
Object poll() Queue에서 객체를 꺼내 반환, 비어있으면 null 반환
Object peek() 삭제 없이 요소를 읽어 온다. Queue가 비어있으면 null 반환

 

- Stack, Queue 예시 코드 

package com.bjy.list.stack;

import java.util.Stack;

/**Stack 클래스  - List 계열
 * 구조 : Last In, First Out(LIFO구조) : 마지막으로 들어가고 첫번째로 나간다
 *       (위쪽만 뚫려 있는 박스 형태인셈)
 *  **/

public class StackTestClass {

	public StackTestClass() {
		
	}
	
	public static void stackTest() {
		Stack<String> s = new Stack<String>();
		s.push("abc");
		s.push("def");
		s.push("ghi");
		// Object push(Object item) : Stack에 객체(item) 추가
		// [abc , def, ghi]
		
		System.out.println(s.peek());
		System.out.println(s.peek());
		System.out.println(s.peek());
		// Object peek() : Stack의 맨 위에 저장된 객체 반환, pop()과 달리 객체를 꺼내지는 않음 
		// 세문장 결과는 다 ghi
		
		System.out.println();
		
		System.out.println(s.pop());	// ghi
		System.out.println(s.pop());	// def
		System.out.println(s.pop());	// abc 
		// pop() : Stack의 맨 위에 저장된 객체 꺼낸다.
		
		
		System.out.println(s.size());
		// 0
	}

}
package com.bjy.list.stack;

import java.util.LinkedList;
import java.util.Queue;

/**LinkedList를 이용하여 Queue 구현하기
 * Queue 인터페이스 - First In, First Out (FIFO구조) 선입선출  
 * 일련의 작업들을 순차적으로 처리하고 싶을 떄 많이 사용 ex) 인터넷 최근 기록 5개 보여주기 ...
 * Collection, Iterable 인터페이스 상속 **/
public class QueueTestClass {

	public QueueTestClass() {
		
	}
	
	public static void queueTest() {
		Queue<String> q = new LinkedList<String>();
		q.add("오늘은 ");
		q.add("자바 ");
		q.add("컬렉션에 ");
		q.add("대하여 ");
		q.add("공부 합니다.");
		
		System.out.print(q.poll());
		System.out.print(q.poll());
		System.out.print(q.poll());
		System.out.print(q.poll());
		System.out.print(q.poll());
		
		System.out.println(q.isEmpty());
		// boolean isEmpty() : 값이 있는지 없는지를 반환하는 메서드 
	}

}

1-4.  Vector Class

ArrayList의 구버전으로 Vector는 동기적이며 관련 메서드로 [ addElement(Object o) : 지정된 객체를 vector 배열에 추가 ] 가 있다.

배열의 각 요소를 출력할 땐 Iterator가 아닌 Enumeration을 이용한다.

 

Vector 관련 메서드 코드 

package com.bjy.list.vector;

public class Board {
	public String subject;
	public String content;
	public String writer;
	
	public Board() {
		
	}

	public Board(String subject, String content, String writer) {
		this.subject = subject;
		this.content = content;
		this.writer = writer;
	}
	
	
	
}
package com.bjy.list.vector;

import java.util.Enumeration;
import java.util.List;
import java.util.Vector;

/**List 계열 : 자료 순차적, 중복일때 사용
 * ArrayList 비동기적(효율적)
 * Vector 동기적 
 * 
 * 비동기적, 동기적 방식 - 예를 들어 a버튼(7000원 출금) , b버튼(5000원 입금)이 있고 계좌엔 만원이 있다 
 * 비동기적 - a,b 동시에 하면 (동시에 일어나지 않는, 둘중 하나가 끝나야 나머지 하나를 실행) 
 * 동기적 - a,b, 동시에 눌러도 계좌 : 8000원 (동시에 일어나는) 
 * **/
public class VectorTestClass {

	public VectorTestClass() {
		// TODO Auto-generated constructor stub
	}
	
	public static void vectorTest() {
		Vector<String> v1 = new Vector<String>();
		v1.add("Samsung"); 
		// add(Object o) : List 인터페이스에 의해 강제 구현 메서드
		v1.addElement("Samsung2"); 
		v1.addElement("LG");
		v1.addElement("Google");
		// addElement(Object o) : Vector 클래스가 정의한 메서드 
		
		System.out.println(v1);
		// Vector는 일반 배열 단점인 크기 보강하고자 만들어진 클래스 (old ver이라 잘 사용 x)
		
		/** Vector 각요소 출력하는 방법 **/
		/** 1. for문 **/
		for(int i=0;i<v1.size();i++) {
			System.out.print(v1.elementAt(i) + "\t");
			// elementAt(int) : 설정된 인덱스에 해당 하는 값 반환
		}
		
		System.out.println();
		
		/** 2. 향상된 for문 **/
		for(String s:v1) {
			System.out.print(s + "\t");
		}
		
		System.out.println();
		
		/** 3. Enumeration 사용 (Iterator 대신)**/
		Enumeration<String> e = v1.elements();
		while(e.hasMoreElements()) {
			System.out.print(e.nextElement() + "\t");
		}
		
		
		
	}
	
	public static void vectorExample() {
		List<Board> list = new Vector<Board>();
		
		list.add(new Board("title1", "content1", "write1"));
		list.add(new Board("title2", "content2", "write2"));
		list.add(new Board("title3", "content3", "write3"));
		list.add(new Board("title4", "content4", "write4"));
		
		list.remove(2);
		list.remove(1);
		
		for(int i=0;i<list.size();i++) {
			Board b = list.get(i);
			// Board 객체 추출 
			System.out.println(b.subject + "\t" + b.content + "\t" + b.writer);
		}
		
		System.out.println();
		
		for(Board b : list) {
			System.out.println(b.subject + "\t" + b.content + "\t" + b.writer);
		}
		
		
		
	}

}

 

 

2-1. HashSet Class 

set 인터페이스를 구현한 가장 대표적 컬렉션으로, set의 특징처럼 중복된 요소를 저장하지 않고 순서가 따로 없다.

ArrayList와 같은 List 인터페이스를 구현한 컬렉션과 달리 HastSet은 저장 순서를 유지하지 않기에

저장순서를 유지하고 싶다면 LinkedHastSet을 사용해야 한다.

 

HashSet 클래스 관련 메서드 코드

package com.bjy.set.hastset;

import java.util.HashSet;
import java.util.Iterator;

/** Set 계열 : 자료가 주머니 속에 저장. 순서 없음, 중복 불가 <== 값(데이터)만 저장
 *         : Iterable-Collection-Set-HastSet/TreeSet **/
public class HashSetTestClass {

	public HashSetTestClass() {
		
	}
	
	public static void hashSetTest() {
		HashSet<String> h = new HashSet<String>();
		h.add("test1");
		h.add("test2");
		h.add("test3");
		h.add("test3");
		// 중복된 값이 있다면 저장 안함 (덮어쓰기 X) 
		// [ "test1", "test2", "test3" ]
		
		System.out.println(h.size());
		// 3
		
		Iterator<String> itr = h.iterator();
		while(itr.hasNext()) {
			System.out.println(itr.next());
			// 저장한대로 순서 유지 보장 X 
			
		}
	}

}
package com.bjy.set.hastset;

import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

public class HashLotto {

	public HashLotto() {
		
	}
	
	public static void lotto() {
		// List가 아닌 Set 사용 이유 : 숫자 중복되면 안되기에 
		HashSet<Integer> c= new HashSet<Integer>();
		
		// 수학 관련된 static 메서드들만 보유 : Math 클래스 
		System.out.println(Math.ceil(0.1234567)); 
		System.out.println(Math.ceil(0.7235566));
		// ceil() : 소수점 첫째자리에서 올림 
		// => 게시글 페이지 번호 : 게시글(35) 한번 출력 갯수(10) 일때 사용, 페이지가 3.5 => 4페이지여야 하니까
		
		System.out.println(Math.floor(0.1234567));
		System.out.println(Math.floor(0.6234567));
		// floor() : 소수점 첫째자리에서 내림
		
		
		System.out.println(Math.round(0.1234567));
		System.out.println(Math.round(0.7235566));
		// round() : 소수점 첫째자리에서 반올림
		
		System.out.println(Math.random());
		// random() : 0<= x < 1 사이의 임의의 실수 출력 
		
		// 로또 번호 6개 출력하고 HashSet c에 저장 
		for(int i=0;c.size()<6 ;i++) {
			int num = (int)(Math.random() * 45 + 1);
			System.out.println(num);
			c.add(new Integer(num));
		}
		
		
		// 숫자를 정렬해주기 위해  순서가 없는 Set -> 순서가 있는  List 형태로 변경 
		// ArrayList가 아닌 LinkedList 사용 이유 : 데이터 추가,삭제에는 링크드 리스트가 더 편리 
		List<Integer> list = new LinkedList<Integer>(c);
		Collections.sort(list);
		System.out.println(list);
		
		
	}

}

 

3-1. HashMap Class

Map 인터페이스를 구현한 클래스로 키(key)값(value)을 묶어서 하나의 데이터(entry)로 저장한다는 게 특징이다. 

그리고 Map의 또다른 특징처럼 key는 중복이 불가능하나 , value는 중복이 가능하다.

HashTable의 발전된 버전으로 해싱을 사용하기 때문에 많은 양의 데이터를 검색하는데 있어서 뛰어나다.

 

HashMap 클래스 관련 메서드 코드 

package com.bjy.map.hashmap;

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

/**Map 계열 : 자료가 (key,value) 한쌍으로 되어 있는 형태일 때 사용
 * 			중복 (key - X, value - O), 순서 X
 * 하위 클래스 : HashMap(자주 사용) , TreeMap(군집분석 -  페북 알수도 있는 친구...), 
 * 			 HashTable, Properties(웹 db관련) 
 * HashTable : old ver (동기화)
 * HashMap : new ver (비동기화)
 * **/
public class HashMapTestClass {

	public HashMapTestClass() {
		
	}
	
	public static void hashampTest() {
		Map<String, Integer> m = new HashMap<String, Integer>();
		m.put("a", 10);
		m.put("b", 20);
		m.put("c", 30);
		m.put("c", 40);
		// key값은 중복이 안되므로 마지막에 넣은 key의 value값이 저장 (덮어쓰기)
		
		System.out.println(m.size());
		
		/** 모든 데이터 추출 후 출력 방법 **/ 
		// 1) Key 애들을 Set 타입의 객체에 저장 2) set을 iterator로 순서 만들어줘 3) Iterator로 key값들, value값들 얻을 수 있어 
		// 1. Set keyset() : HashMap에 저장된 모든 키가 저장된 Set을 반환 , 키의 값들을 Set타입으로 저장하여 반환 
		Set<String> s = m.keySet();
		Iterator<String> itr = s.iterator();	
		// 키명을 특정 순서대로 배치, Set타입은 순서가 없기에 자체적으로 순서를 만들어줘야 함 
		// 그래서 Iterator 사용 
		
		while(itr.hasNext()) {
			String keyName = itr.next();
			Integer value = m.get(keyName);
			System.out.println(keyName + ":" + value);
		}
		
	}
	
	public static void hashMapExample() {
		Map<String, Student> m = new HashMap<String, Student>();
		
		m.put("a", new Student(10, "test1"));
		m.put("b", new Student(20, "test2"));
		m.put("c", new Student(30, "test3"));
		m.put("d", new Student(40, "test4"));
		
		System.out.println(m);
		
	}

}
package com.bjy.map.hashmap;

public class Student {
	private int sno;
	private String name;
	
	public Student(int sno, String name ) {
		this.sno = sno;
		this.name = name;
	}
	
	
	public void testToString() {
		System.out.println(this.sno + ":" + this.name);
	}

}

 

- Properties Class

DB에 대한 연결 정보를 파일로 저장해놓고 사용하는 용도로 쓰이는 클래스로 보통 HashMap 같은 형태로 처리할 때 쓰여 유지보수가 용이하게 하기 위해 존재하며 보통 db.properties라는 파일명으로 작명된다.(만약 DB에 대한 연결 정보를 자바 코드 내에 작성했다면 연결 DB 정보를 변경할 시 코드를 다 뜯어내고 수정해야 하기에 납품에도 적합하지 않은 프로젝트가 된다)

 

이 파일에 db에 대한 연결 정보는 다음과 같다.

 

 

이제 이 database.properties에 담겨진 정보를 읽기 위해 PropertiesTestClass 라는 클래스를 사용하는 코드는 다음과 같다.

package com.bjy.map.properties;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

public class PropertiesTestClass {

	public PropertiesTestClass() {
		
	}
	
	public static void propertiesTest() {
		String path = PropertiesTestClass.class.getResource("database.properties").getPath();
//		System.out.println(path);
		
		Properties p = new Properties();
		
		
		try {
			FileReader fr = new FileReader(path);
			p.load(fr);
			
			System.out.println(p.getProperty("driver"));
			System.out.println(p.getProperty("url"));
			System.out.println(p.getProperty("username"));
			System.out.println(p.getProperty("password"));
			
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
		
	}

}

MainClass에서 실행하면 properties 파일에 담겨진 4개의 정보가 콘솔창에 출력된다.