1. 배열과 컬렉션즈 프레임웍
배열은 슬롯에 몇 개의 데이터를 담을 수 있는지 알 때만 사용 가능, 만약에 슬롯의 갯수를 정확하게 모른다면 오류가 발생한다.
배열과는 달리 CF에서 제공하는 ArrayList는 몇 개의 값을 담을 수 있는지 지정할 필요가 없다
사용 시 import java.util.ArrayList를 선언 후 사용
package chapter_14;
import java.util.ArrayList;
public class _01_ArrayList {
public static void main(String[] args) {
// String[] arrayObj = new String[2]; // 일번적인 array
// arrayObj[0] = "one";
// arrayObj[1] = "two";
// //arrayObj[2] = "three"; // 오류 발생
// for (int i = 0; i < arrayObj.length; i++) {
// System.out.println(arrayObj[i]);
// }
// }
// ArrayList a1 = new ArrayList();
// a1.add("one");
// a1.add("two");
// a1.add("three");
// for(int i = 0; i < a1.size(); i++) {
// // String value = a1.get(i); // 오류, "one"은 object 타입임. 근데 이것을 스트링이라는 데이터타입 변수에 저장하려고 해서 오류
// // > 해결방법: 형변환
// String value = (String) a1.get(i); // 이거는 너무 구시대적, 최신 경향은? 제네릭
// System.out.println(value);
// }
ArrayList<String> a1 = new ArrayList<String>(); // 제네릭 적용
a1.add("one");
a1.add("two");
a1.add("three");
for(int i = 0; i < a1.size(); i++) {
String value = a1.get(i);
System.out.println(value);
}
}
}
2. Collections Framework란?
컨테이너라고도 부르며 값을 담는 그릇. 값의 성격에 다라 컨테이너의 성격이 조금씩 다름
Collections Framework = Collection(Set, List, Queue) + Map
요약하자면, 우리가 다루려고 하는 데이터셋을 다룰 수 있는 컨테이너를 선택적으로 골라 사용해야한다는 것
3. List vs. Set
1) Set(집합 / 수학의 집합의 특성을 살린 collections)
- HashSet: ArrayList와 달리 1, 2, 2, 2, 3, 3 의 배열을 저장해도 출력 값은 1, 2, 3 만 나옴 - 고유한 값만 입력되는 것(Set의 특징)
package chapter_14;
import java.util.HashSet;
import java.util.Iterator;
public class _02_HashSet {
public static void main(String[] args) {
HashSet<Integer> A = new HashSet<Integer>();
A.add(1); // HashSet 에서는1, 2, 3의 개수를 수 없이 늘려도 결과는 1, 2, 3만 나옴
A.add(2); // ArrayList 에서는 공통된 숫자를 늘린 만큼 다 추가 됨
A.add(3);
Iterator hi = (Iterator) A.iterator();
while(hi.hasNext()) {
System.out.println(hi.next());
}
}
}
- 기능 예시
package chapter_14;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
public class _02_HashSet {
public static void main(String[] args) {
HashSet<Integer> A = new HashSet<Integer>();
A.add(1);
A.add(2);
A.add(3);
HashSet<Integer> B = new HashSet<Integer>();
B.add(3);
B.add(4);
B.add(5);
HashSet<Integer> C = new HashSet<Integer>();
C.add(1);
C.add(2);
System.out.println(A.containsAll(B)); // false, containsAll 은 HashSet 의 고유 메소드, 부분집합
System.out.println(A.containsAll(C)); // true
//A.addAll(B); // 1, 2, 3, 4, 5 / 합집합 메소드
//A.retainAll(B); // 3 / 교집합
//A.removeAll(B); // 1, 2 / 차집합
Iterator hi = A.iterator();
while(hi.hasNext()){
System.out.println(hi.next());
}
}
}
- 저장된 데이터가 순서대로 저장될 것이라는 보장이 되지 않음 > List 와의 차이2
2) List
- ArrayList: 1, 2, 2, 2, 3, 3을 저장하면 중복되어도 출력값은 1, 2, 2, 2, 3, 3 - 저장된 모든 값이 입력됨(List의 특징)
- 즉, 집합 개념을 도입한 Set과 달리 1차원 행렬 개념을 도입한 Collection
3) Collections interface
- Collection, Set, List, Map은 인터페이스이며 하위에는 추상클래스가 존재한다. 또 그 하위에 존재하는 framework들은 상위의 클래스를 상속받은 하위의 클래스들이다. 후자는 하위에 별도의 메소드들을 가지고 있다.
- 연파랑: 인터페이스, 진파랑: 클래스
- Set 인터페이스는 비어있는데 이 말은 Collection을 그대로 상속받아 사용한다(순서를 보장받지 못함).
- List 인터페이스는 별도의 메소드들(API)이 존재하는데 이는 List만 가지는 index와 관련한 특수한 메소드들이다(즉, 순서와 관련).
- Iterator(반복자): 인터페이스 Collections에 정의되어있는 메소드로 하위의 모든 프레임워크에서 사용 가능함, 메소드 iterator는 인터페이스 iterator를 구현한 객체를 리턴함, 아래 세 가지 메소드를 구현할 것을 강제함
> hasNext: 반복할 데이터가 더 있으면 true, 더 이상 반복할 데이터가 없다면 false를 리턴한다.
> next: hasNext가 true라면 next가 리턴할 데이터가 존재한다는 의미이다.
> remove:
- iterator 메소드에서 인스턴스에 저장된 변수들을 출력한다면 내부에서 출력된 값들이 삭제되면서 반복작업이 종료 된다. 즉, 오리지널 데이터 자체는 삭제되지 않고 가상 저장소를 구현하여 기능하는 API
4) Map
- Key(중복 불가, 정의역) + value(중복 가능, 공역) = Map(치역)
- 수학의 함수와 같은 개념을 구현 (y = f(x))
- entrySet: Map > Set으로 전환 (Set의 메소드 사용 가능, iterator)
- 두 가지 데이터 열을 가지므로 제네릭도 두 가지 정의
package chapter_14;
import java.util.*;
public class _03_HashMap {
public static void main(String[] args) {
HashMap<String, Integer> a = new HashMap<String, Integer>(); // hashmap 은 key 와 value 의 관계를 다루기 때문에 두 개의 제네릭을 가짐
a.put("one", 1); // put 은 Map 인터페이스에만 존재함, (key, value)
a.put("two", 2);
a.put("three", 3);
a.put("four", 4);
System.out.println(a.get("one")); // 1, value 를 불러오기위한 도구로 사용되므로 key 는 중복이 불가하다
System.out.println(a.get("two")); // 2
System.out.println(a.get("three")); // 3
iteratorUsingForEach(a);
iteratorUsingIterator(a);
}
static void iteratorUsingForEach(HashMap map){
Set<Map.Entry<String, Integer>> entries = map.entrySet(); // entrySet: map 안의 정보를 set 형식으로 바꿈
for (Map.Entry<String, Integer> entry : entries) { // entries는 Set의 데이터타입
System.out.println(entry.getKey() + " : " + entry.getValue());
// getKey(): string 데이터타입, 해당하는 데이터를 하나씩 꺼내 씀
// getValue(): Integer 데이터타입, 상동
// four : 4 / one : 1 / two : 2 / three : 3
}
}
static void iteratorUsingIterator(HashMap map){
Set<Map.Entry<String, Integer>> entries = map.entrySet();
Iterator<Map.Entry<String, Integer>> i = entries.iterator(); // set 으로 변환했기 때문에 iterator 사용 가능
while(i.hasNext()){
Map.Entry<String, Integer> entry = i.next();
System.out.println(entry.getKey()+" : "+entry.getValue());
// four : 4 / one : 1 / two : 2 / three : 3
}
}
}
5) 정렬(인터페이스 Comparable)
package chapter_14;
import java.util.*;
class Computer implements Comparable{ // public interface, sort 메소드 사용
int serial;
String owner;
Computer(int serial, String owner){
this.serial = serial;
this.owner = owner;
}
public int compareTo(Object o) { // Comparable 은 compareTo를 정의할 것을 강제하는 인터페이스
return this.serial - ((Computer)o).serial; // 비교 객체가 기준 객체와 같으면 0, 보다 크면 양수, 작으면 음수로 출력
}
public String toString(){
return serial+" "+owner;
}
}
public class _04_collectionsSort {
public static void main(String[] args) {
List<Computer> computers = new ArrayList<Computer>();
computers.add(new Computer(500, "egoing"));
computers.add(new Computer(200, "leezche"));
computers.add(new Computer(3233, "graphittie"));
Iterator i = computers.iterator();
System.out.println("before");
while(i.hasNext()){
System.out.println(i.next()); // 위의 순서대로 출력
}
Collections.sort(computers); // sort는 list 타입만 받음
System.out.println("\nafter");
i = computers.iterator();
while(i.hasNext()){
System.out.println(i.next()); // 숫자 순서대로 나열
}
}
}