주니어 기초 코딩공부

15장 컬렉션 프레임워크

jju_developer 2022. 12. 1. 21:09
728x90

안녕하세요 JAVA 기초 공부 중인 jju_developer입니다~

 

오늘은 자바의 컬렉션 프레임워크의 기본 개념에 대해 알아보도록 하겠습니다~ :)

 

자료 = 변수, 데이터 공간

 

대표적인 자료의 공간은 배열입니다.

 

하지만, 배열에는 문제점이 있습니다.
• 저장할 수 있는 객체 수가 배열을 생성할 때 결정 -> 불특정 다수의 객체를 저장하기에는 문제가 됩니다.
• 객체 삭제했을 때 해당 인덱스가 비게 됨 -> 

낱알 빠진 옥수수 같은 배열, 객체를 저장하려면 어디가 비어있는지 확인하는 코드도 필요하게 됩니다.

컬렉션 프레임워크란?

 컬렉션이란 사전적 의미로 요소(객체)를 수집해 저장하는 것을 말한다.
 컬렉션 프레임워크는 몇가지 인터페이스를 통해서 다양한 컬렉션 클래스를 이용할 수 있도록 하고 있다.

 

 

대표적인 컬랙션안에 있는 인터페이스 3가지

 

List, Set, Map

 

그 아래에 있는 것들은 구현한 구현 클래스 입니다.

 

주로 자주 쓰는 것은 ArrayList, HashSet, HashMap, Properties 이 네가지 입니다.

 

Set을 기준으로 List, Set, Map 을 구분할 줄 알아야 합니다.

 

Set은 항아리 같은 모양이며, 재비뽑기 하는 방식과 비슷합니다.

 

 


✔List : ArrayList, Vector, LinkedList

단점: 중간에 있는 인덱스를 삭제할 시 뒤에있는 인덱스가 변경됨.

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

배열이 갖고 있는 문제점을 해결하고자 하나의 인덱스가 제거되면 그 뒤의 인덱스가 모두 앞으로 1개씩 당겨집니다.

 


✔ArrayList

 저장 용량(capacity)
• 초기 용량 : 10 (따로 지정 가능)
• 저장 용량을 초과한 객체들이 들어오면 자동적으로 늘어남. 고정도 가능

 

지난시간에 배운 제너릭으로 선언하여 다양하게 구현 가능합니다.

List<String> str_list = new ArrayList<String>();

List<Integer> str_list = new ArrayList<Integer>();

 


예제

 

public class ArrayListExample {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();//인터 페이스에 = 구현객체 ArrayList를 넣은것.
		
		list.add("Java");
		list.add("JDBC");
		list.add("Servlet/JSP");
		list.add(2,"Database");
		list.add("myBatis");
	
		int size = list.size();
		System.out.println("총 객체수:"+size);
		
		String skill = list.get(2);
		System.out.println("2: "+skill);
		System.out.println();

		for (int i = 0; i < list.size(); i++) {
			String str = list.get(i);
			System.out.println(i+": "+str);
		}
	}
}

 

list.remove(2);

 

2번째 인덱스를 지우게 된다면

 

한자리씩 댕겨져서 출력되는 것을 알 수 있습니다~

 

인덱스가 아닌 이름으로 지울 수 있을까요?

 

list.remove("JDBC");

 

동일하게 지울 수 있습니다.

 

여기서..! 향상된 for 문으로 출력하는 법은?

 

for (String str : list) {
			System.out.println(str);
		}

// List list = Arrays.asList(); 으로도 리스트를 만들 수 있습니다.

List<String> list1 = Arrays.asList("홍길동", "신용권", "감자바");

 

	public static void main(String[] args) {
		List<String> list1 = Arrays.asList("홍길동", "신용권", "감자바");
		for(String name: list1) {
			System.out.println(name);
		}
		
		List<Integer> list2 = Arrays.asList(1, 2, 3);

 

List<Integer> list2 = Arrays.asList(1, 2, 3);

int 타입이 Integer로 박싱되어 들어가게 됩니다.


class Article {

  String weiter;

  String title;

  Date regDate;

}

Article a1 = new Article("오근주","15장","확인문제", new Data(22/12/01))

Article a2 = new Article("김진주","15장","확인문제", new Data(22/12/01))

 

List <Article> list = new ArrayList<Article>();

list.add(a1);

list.add(a2);

 

for(Article articles : list) {

    System.out.println(article.getTitle());

}

 

 

✔Vector


 기본형: List<E> list = new Vector<E>();
 ArrayList와 다르게 Vector는 동기화된(synchronized) 메소드로 구성되어 있기 때문에 멀티스레드가 동시에 이 메소드들을 실행할 수 없고, 하나의 스래드가 실행을 완료해야만 다른 스레드를 실행할 수 있다. 그래서 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제할 수 있다(thread safe).

 

예를 들면 add메소드를 쓰려고 할때 Sync 되어있기 때문에 다른 스레드가 쓰지 못하게 lock 이 걸립니다.

 

그 외는 ArrayList와 동일합니다.

 

예제)

 

public class Board {
// 글을 담는 클래스를 먼저 생성해 봅시다.
	
	String subject;
	String content;
	String writer;
	
// 매개변수가 있는 생성자 	
	public Board(String subject, String content, String writer) {
		this.subject = subject;
		this.content = content;
		this.writer = writer;
	}
}

 


✔LinkedList

 기본형: List<E> list = new LinkedList<E>();
 인접 참조를 링크해서 체인처럼 관리
 특정 인덱스에서 객체를 제거하거나 추가하게 되면 바로 앞뒤 링크만 변경

 

빈번하게 중간에 항목을 넣었다 뺏다 하려면 ArrayList보다 Linked list가 더 효율성이 좋습니다.

하지만 단순히 맨뒤에 항목을 추가하는 것은 ArrrayList가 더 효율성이 좋습니다.

List<String> list1 = new ArrayList<String>();
List<String> list2 = new LinkedList<String>();

 

 


✔Set 컬렉션

 특징
• 수학의 집합에 비유
• 저장 순서가 유지되지 않음
• 객체를 중복 저장 불가
• 하나의 null만 저장 가능

 

인덱스가 없고 순서도 없기 때문에 for문을 쓸 수 가 없고

 

Iterator의 객체를 만들어서 하나씩 빼오는 반복자 리턴을 사용해야한다.

 


✔HashSet

 기본형: Set<E> set = new HashSet<E>();
 동일 객체 및 동등 객체는 중복 저장하지 않음
 동등 객체 판단 방법

hashCode() 리턴값이 같은지 판단 후 equals() 리턴값이 같으냐 보고 둘다 같으면 동등객체로 판단!!

 

public class HashSetExample1 {
	public static void main(String[] args) {
		//인터페이스       =  구현객체
		Set<String> set = new HashSet<String>();
		
		set.add("Java");
		set.add("JDBC");
		set.add("Java");	//중복으로 기존 값에 overwrite 한다.
		set.add("myBatis");
		
		
		int size = set.size();
		System.out.println("HashSet의 총 객체수: "+set.size()); 
		//4개를 넣었지만 실제로 중복 값을 빼고 3개 return
	}
}
		//for가 아닌 Iterator를 사용한다.
		Iterator<String> iterator = set.iterator();
		while (iterator.hasNext()) {	//true이면, 다음것을 가져와라
			String element = iterator.next();
			System.out.println(element);
		}

만약 Iterator가 아닌 for문을 활용하여 HashSet을 출력하고 싶을때

 

향상된 for문을 이용하면 됩니다.

for (String element : set) {
			System.out.println(element);
		}

 

hashSet에서 모든 요소를 삭제할때에는 set.clear(); 를 사용하시면 됩니다~

set.clear();
  if(set.isEmpty())
	System.out.println("비어있음");

✔TreeSet

 기본형: TreeSet<E>  set = new TreeSet<E>();
동일 객체 및 동등 객체는 중복 저장하지 않음
 들어갈때에는 순서가 없지만 저장할때 순서에 맞게 저장이 되기 때문에 나올때 정렬이 되어 나옵니당!!

 


✔Collection - Map 컬랙션

 특징
• 키(key)와 값(value)으로 구성된 Map.Entry 객체를 저장하는 구조
• 키와 값은 모두 객체

 

key   :  value

이름 :  오근주

나이 :   27

주소 :  서울

 

여기서 Map은 키는 중복 될 순 없지만, value값은 중복을 허용합니다.

 

 구현 클래스
• HashMap, Hashtable, LinkedHashMap, Properties, TreeMap

위 2개 강조된 클래스는 자주 사용되기 때문에 잘 알아보아야 합니다~!

 

Map에서는 add가 아니라 put을 통해서 저장하게 됩니다!

Key를 Set으로 바꿔서 키의 값을 하나씩 가져오는 구조를 가지게 됩니다.

 

get에다가 key의 객체를 넣으면 return은 value객체를 return 하게 됩니다.

 


HashMap

Map 컬랙션의 HashMap을 먼저 살펴보도록 하겠습니다.

 기본형: Map<K,V> map = new HashMap<K,V>(); // K=키타입, V=값타입
 HashMap의 키로 사용할 객체는 hashCode()와 equals() 메소드를 재정의해서 동등 객체가 될 조건을 정해야 한다. 주로 키 타입은 String을 많이 사용하는데, String은 문자열이 같을 경우 동등 객체가 될 수 있도록 hashCode()와 equals() 메소드가 재정의되어 있다.

 

Map<String, Integer> map = new HashMap<String, Integer>();

=>키는 String, 벨류는 Integer로 받겠다는 말입니다.

뒤에 있는 Map<String, Integer> map = new HashMap<>(); 뒤에는 생략 가능합니다.

앞에 있는 <String, Integer>를 생략하면 <Object, Object>로 되기 때문에 앞은 생략이 불가합니다~!

키는 String 벨류는 Interger인테 박싱되어 int로 들어갑니다.

 

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

public class HashMapExample1 {
	public static void main(String[] args) {
		// Map 컬렉션 생성
		Map<String, Integer> map = new HashMap<String, Integer>();

		// 객체 저장 (put으로 저장)
		map.put("오근주", 85); // 키는 String, 벨류는 int <- Integer
		map.put("이소연", 90); // 키가 중복
		map.put("김동우", 80);
		map.put("이소연", 95); // 키가 중복

		System.out.println("총 Map Entre의 수는?? " + map.size()); // 4가 아닌 3이 return

		// 객체 찾기
		System.out.println("이소연은 90일까요 95일까요?: " + map.get("이소연"));
		// 기존값에 뒤에 들어온 값이 엎어치기함
		System.out.println();

		// 객체를 하나씩 처리 방법 1. keySet()
		Set<String> keySet = map.keySet();
		// for문 말고 Iterator로 만들어서 하나씩 가져올 것임.
//		Iterator에 String이 들어가고 keyIterator만들고 = ketSet.iterator();를 넣을거
//		Iterator에 hasNext가 있느냐? 있으면 하나씩 키에 담아 가져와라 (스트링 타입임)
//		벨류는 Integer 객체이다.

		Iterator<String> keyIterator = keySet.iterator();
		while (keyIterator.hasNext()) {
			String key = keyIterator.next();
			Integer value = map.get(key);
			System.out.println(key + ":" + value);
		}
		System.out.println();

		// 또다른 객체 처리 방법 2. Map.entrySet()
//		map에서 keySet이 아니라 Map.entrySet을 이용하는 방법입니다.
		Set<Map.Entry<String,Integer>> entrySet =map.entrySet();
		Iterator<Map.Entry<String, Integer>> entryIterator = entrySet.iterator();
		while(entryIterator.hasNext()) {
			Map.Entry<String, Integer> entry = entryIterator.next();
			String key = entry.getKey();
			Integer value = entry.getValue();
			System.out.println(key + ":" + value);
		}

*Map에서 삭제하는 방법은

map.remove("키 값"); 으로 해주시면 됩니다.

 

*전체 다 지우는 방법은 map.clear(); 을 해주시면 됩니다.

 


두번째 예제는 Student라는 사용자 정의 클래스를 만들어 보도록 하겠습니다.

// 사용자 정의 클래스
public class Student {
	public int sno;
	public String name;
	
	//생성자
	public Student(int sno, String name) {
		this.sno  = sno;
		this.name = name;
	}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class HashMapExample2 {
	public static void main(String[] args) {
		Map<Student, Integer> map = new HashMap<Student, Integer>();
//		맵의 키는 Student 벨류는 Integer = 
		map.put(new Student(1, "오근주"), 95);
		map.put(new Student(1, "오근주"), 95);
//		이  맵에 값을 저장한다. 아까 정의한 sno,name,값은 95?
//		키는 중복이 되지 않아야 한다고 했는데, Student에 동등비교가 안되어 있기 때문에
//		동일하게 값을 넣더라도 동일하지 않은 객체로 보여집니다.
		
		System.out.println("총 Entry 수: " + map.size());	 //2개로 판별
	}
}

// 이  맵에 값을 저장한다. 아까 정의한 sno,name,값은 95
// 키는 중복이 되지 않아야 한다고 했는데, Student에 동등비교가 안되어 있기 때문에
// 동일하게 값을 넣더라도 동일하지 않은 객체로 보여집니다

총 Entry 수: 2

 

이제 Studnet 클래스에서 동등비교 로직을 넣어보겠습니다!!!

// 사용자 정의 클래스
public class Student {
	public int sno;
	public String name;

	// 생성자
	public Student(int sno, String name) {
		this.sno = sno;
		this.name = name;
	}

	@Override
	public int hashCode() {
		return sno + name.hashCode();
	}

	@Override
	public boolean equals(Object obj) {// 이 object를 student로 변환해야합니다.
		if (obj instanceof Student) {
			Student student = (Student) obj;
			return (sno == student.sno) && (name.equals(student.name));
		} else {
			return false;
		}
	}
}

hashCode와 equals를 재 정의 하게 되면 비로소 Key가 같았던 String이 제거가 되면서

 

총 Entry 수는 1 로 변경됩니다.

 


✔Properties

• 키와 값을 String 타입으로 제한한 Map 컬렉션
• Properties는 프로퍼티(~.properties) 파일을 읽어 들일 때 주로 사용

 

메모장:

driver=oracle.jdbc.OracleDirver
url=jdbc:oracle:thin:@localhost:1521:orcl
username=scott
password=tiger

properties 코드

import java.io.FileReader;
import java.net.URLDecoder;
import java.util.Properties;

public class PropertiesExample {
	public static void main(String[] args) throws Exception {
		// properties 객체 생성 //Map 구조이며 <String, String> 이다
		Properties properties = new Properties();
		// PropertiesExample.클래스에서 database.properties의 path에 담아라!
		String path = PropertiesExample.class.getResource("database.properties").getPath();
		// path를 넣어야지만 FileReader에서 읽을 수가 있습니다.
		path = URLDecoder.decode(path, "utf-8");
		// 중간에 주소 값이 한글이 들어갈 수도 있기때문에 path의 주소를 한글로 인코딩을해라!
		properties.load(new FileReader(path));
		// 파일의 입출력을 담당하는 클래스에 path를 넣어서 파일을 읽어와라!
		// driver=oracle.jdbc.OracleDirver 일 때
		// 키 = 벨류 인 맵 구조로 읽어와라 => 전부 String 타입임.

		String driver = properties.getProperty("driver");
		String url = properties.getProperty("url");
		String username = properties.getProperty("username");
		String password = properties.getProperty("password");
//		각각 설정 정보에 들어 있는 값들을 키에 저장하게 됩니다.
//		아래 처럼 출력하면 잘 저장 되어 있는 것을 볼 수 있습니다.

		System.out.println("driver : " + driver);
		System.out.println("url : " + url);
		System.out.println("username : " + username);
		System.out.println("password : " + password);
	}
}

 

출력:

driver : oracle.jdbc.OracleDirver
url : jdbc:oracle:thin:@localhost:1521:orcl
username : scott
password : tiger

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90