안녕하세요 JAVA 기초 공부 중인 jju_developer입니다~
오늘은 자바의 컬렉션 프레임워크의 기본 개념에 대해 알아보도록 하겠습니다~ :)
자료 = 변수, 데이터 공간
대표적인 자료의 공간은 배열입니다.
하지만, 배열에는 문제점이 있습니다.
• 저장할 수 있는 객체 수가 배열을 생성할 때 결정 -> 불특정 다수의 객체를 저장하기에는 문제가 됩니다.
• 객체 삭제했을 때 해당 인덱스가 비게 됨 ->
낱알 빠진 옥수수 같은 배열, 객체를 저장하려면 어디가 비어있는지 확인하는 코드도 필요하게 됩니다.
컬렉션 프레임워크란?
컬렉션이란 사전적 의미로 요소(객체)를 수집해 저장하는 것을 말한다.
컬렉션 프레임워크는 몇가지 인터페이스를 통해서 다양한 컬렉션 클래스를 이용할 수 있도록 하고 있다.
대표적인 컬랙션안에 있는 인터페이스 3가지
List, Set, Map
그 아래에 있는 것들은 구현한 구현 클래스 입니다.
주로 자주 쓰는 것은 ArrayList, HashSet, HashMap, Properties 이 네가지 입니다.
Set을 기준으로 List, Set, Map 을 구분할 줄 알아야 합니다.
Set은 항아리 같은 모양이며, 재비뽑기 하는 방식과 비슷합니다.
✔List : 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
'주니어 기초 코딩공부' 카테고리의 다른 글
Java 입출력 (In/Out), Scanner 클래스 설명 (4) | 2022.12.06 |
---|---|
JAVA 게시판 만들기_비밀번호가 같으면 삭제할 수 있도록 코드 작성 (0) | 2022.12.02 |
JA14장 람다식 (0) | 2022.12.01 |
13장 제네릭 (0) | 2022.12.01 |
12장 JAVA Thread의 개념 및 자바의 스레드 구현과 실행 (0) | 2022.11.30 |