[JAVA] Collection Framework
일반적으로 한번 정해진 배열의 크기를 변경할 수 없다
그래서 배열의 크기를 늘리고 싶다면 새로운 배열을 만들어 복사하는 방식으로만 배열크기를 늘리는 것이 가능하다
public class Array {
String[] list;
int cur = 0;
Array(){
list = new String[10];
}
// 배열 길이를 알고 있다면 해당값을 입력해 효율적으로 해결할 수 있다
Array(int length){
list = new String[length];
}
public void add(String str) {
// 배열을 크기가 넘어가면 더이상 추가가 안됨으로 크기가 더 많은 배열을 만들어서
// 기존 배열을 복사하는 방법으로만 가능하다
if(cur == list.length) {
String[] temp = new String[list.length+10];
System.arraycopy(list, 0, temp, 0, list.length);
list = temp;
}
list[cur++] = str;
}
public String remove(int index) {
String[] temp = new String[list.length];
String remove = list[index];
int add=0;
for(int i =0; i<temp.length; i++) {
if(i==index) add=1;
if(i+add == temp.length-1) break;
temp[i] = list[i+add];
}
list = temp;
return remove;
}
public String get(int index) {
return list[index];
}
public int size() {
return cur;
}
}
public class ArrayListExample {
public static void main(String[] args) {
Array a = new Array();
for(int i=0; i<30; i++) {
a.add("회원"+i);
}
for(int i=0; i<a.size(); i++) {
System.out.println(a.get(i));
}
}
}
ArrayList는 위와같이 동작한다
List
배열과 비슷하게 객체를 인덱스로 관리
배열과의 차이점은 저장 용량이 자동으로 증가하며 객체를 저장할 때 자동 인덱스가 부여
ArrayList
List라는 인터페이스로 선언 (인터페이스를 구현한 LinkedList 삽입/삭제에 유리)
List<Object> list = new ArrayList<Object>();
List<Object> list = new ArrayList<>();
// 후자의 Object를 생략하면 왼쪽 list에 지정된 타입을 따라감
ArrayList 구현체 클래스 (빠른 탐색에 유리)
ArrayList<Object> list = new ArrayList<>(용량);
- 1차원 배열구조
- 중복을 허용하고 순서화 제공
- List 타입의 대표 컬렉션
주요 메소드
- add : 데이터 삽입
- clear : 초기화
- contains : 포함 여부 확인
- get : idx 자료 변환
- remove : idx 자료 반환 후 삭제
- size : 배열 길이
set
isEmpty
public class ArrayListExample {
public static void main(String[] args) {
List list = new ArrayList();
list.add(10);
list.add(10.5);
list.add("test");
list.add(new Test());
for(int i=0; i<list.size(); i++) {
System.out.println(list.get(i));
}
}
}
class Test{
String a = "t";
String b = "e";
String c = "s";
String d = "t";
@Override
public String toString() {
return "Test [a=" + a + ", b=" + b + ", c=" + c + ", d=" + d + "]";
}
}
10
10.5
test
Test [a=t, b=e, c=s, d=t]
랜덤으로 5개 값을 입력하고 출력하시오
5개 값의 총합을 구하시오.
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ArrayListExample02 {
public static void main(String[] args) {
List list = new ArrayList();
for (int i = 0; i < 5; i++) {
int ran = new Random().nextInt(49) + 1;
list.add(ran);
}
int sum = 0;
for (int i = 0; i < list.size(); i++) {
sum += (int) list.get(i);
System.out.print(list.get(i));
if(i!=list.size()-1) System.out.print("+");
}
System.out.println(" = "+sum);
}
}
List<Integer> list = new ArrayList();
만약 list를 Int로 선언을 하면 sum계산 결과에 (int) 강제 타입 변환이 필요하지 않다
여러 타입을 넣을 때는 생략을 한다.
import java.util.ArrayList;
import java.util.List;
public class ArrayListExample03 {
public static void main(String[] args) {
// 회원1 ~ 회원 10까지 입력
List<String> list = new ArrayList();
for(int i=1;i<=10;i++) {
list.add("회원"+i);
}
// 전체 리스트 출력
for(int i=0;i<list.size();i++) {
System.out.println(list.get(i));
}
// index 값을 3입력해서 해당값을 삭제
String remove = list.remove(3);
// 삭제한 값을 출력 => ? 님이 탈퇴하셨습니다.
System.out.println(remove+"님이 탈퇴하셨습니다.");
if(list.contains("회원1")) {
System.out.println("회원1이 있습니다.");
}
if(list.contains("회원4")) {
System.out.println("회원4이 있습니다.");
}
}
}
회원1
회원2
회원3
회원4
회원5
회원6
회원7
회원8
회원9
회원10
회원4님이 탈퇴하셨습니다.
회원1이 있습니다.
remove할 때 값을 리턴하기 때문에 문자열에 저장할 수 있다.
Vector
List<Object> list = new Vector<Object>;
ArrayList와 동일한 내부 구조
ArrayList와 차이점은 Vector는 동기화된 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 실행할 수 없음
하나의 스레드가 메소드를 실행을 완료해야만 다른 스레드가 메소드를 실행하기 때문에
멀티 스레드 환경에서 안전하게 객체를 추가 삭제할 수 있어 이것을 스레드에 안전(thread safe) 하다고 표현
LinkedList
List<Object> list = new LinkedList<>();
ArrayList는 내부 배열에 객체를 저장해서 관리하지만
LinkedList는 인접 참조를 링크해서 체인처럼 관리, 삽입 삭제에 유리하다
객체를 제거할경우 앞 뒤 링크만 변경되고 나머지 링크는 변경되지 않음
(ArrayList는 앞으로 덮어씌워 저장)
Set
List 컬렉션과는 다르게 Set 컬렉션은 저장 순서가 유지되지 않고 객체를 중복해서 저장할 수 없으며 하나의 null만 저장할 수 있다.
인덱스로 객체를 검색해서 가져오는 메소드가 없는 대신에 전체 객체를 대상으로 한번씩 반복해서 가져오는 반복자(Iterator)를 제공 반복자는 Interator 인터페이스를 구현한 객체
Set<Object> set = ...'
Iterator<String> iterator = set.iterator();
리턴 타입 | 메소드 | 설명 | |
boolean | hasNext() | 가져올 객체가 있으면 true 리턴 | iterator.hasNext() |
E | next() | 컬렉션에서 하나의 객체를 가져옴 | iterator.next() |
void | remove() | Iterator의 메소드이지만 실제로 Set 컬렉션에서 객체가 제거 |
iterator.remove() |
Iterator<String> iterator = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
Iterator를 사용하지 않고 향상된 for문을 이용해서 전체 객체를 대상으로 반복할 수 있음
Set<String> set = ;
for(String str : set) {
//저장된 객체 수만큼 루핑
}
HashSet
Set<Object> set = new HashSet();
Set<Object> set = new HashSet<Object>();
- Set 대표 컬렉션
- key로 이루어짐
- key값은 중복을 허용하지 않고 순서가 보장되지 않음
- 동등 객체는 저장하지 않음 - list와 비교할 수 없이 속도가 빠르다
주요 메소드
- add : 값 추가
- remove : 값 삭제
- contains : 포함여부
- iterator : 전체 출력을 위한 메소드
import java.util.HashSet;
import java.util.Set;
public class SetExample {
public static void main(String[] args) {
Set set = new HashSet();
set.add("가");
set.add("a");
set.add("b");
set.add(1);
set.add(10.5);
System.out.println(set);
Iterator it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
[가, a, 1, b, 10.5] // 순서 X
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class SetExample {
public static void main(String[] args) {
Set<Integer> lotto = new HashSet<Integer>();
// 같은 값을 넣으면 아무것도 일어나지 않음
while(lotto.size()<6) {
lotto.add(new Random().nextInt(45)+1);
}
System.out.println(lotto);
}
}
Map
HashMap
Map<Object, Object> map = new HashMap();
- Map 타입의 대표 컬렉션
- key와 value로 이루어짐 (키와 값으로 이루어진 Map.Entry 객체를 저장하는 구조)
Entry는 Map 인터페이스 내부에 선언된 중첩 인터페이스 - key 값은 중복을 허용하지 않고 순서가 보장되지 않음.
- 만약 기존에 저장된 키와 동일한 키로 값을 저장하면 기존의 값은 없어지고 새로운 값으로 대체
(set은 기존의 값 그대로 저장한다는 차이점이 존재)
주요 메소드
- put : 데이터 입력 key 값은 중복되지 않음.
- get : 입력받은 value 값을 key값을 통해 꺼내올 수 있음.
- keySet : key 로 이루어진 hashSet 값을 가져옴
- remove : value 값을 리턴 받고 삭제
- size : 크기 반환
- containsKey : 키값이 존재하는지 확인.
containsValue
import java.util.HashMap;
import java.util.Map;
public class MapExample01 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap();
map.put("홍길동", 95);
map.put("이순신", 85);
map.put("정몽주", 75);
map.put("이성계", 87);
// 홍길동 점수
if(map.containsKey("홍길동2")) {
int hScore = map.get("홍길동2");
System.out.println(hScore);
} else {
System.out.println("해당값이 존재하지 않습니다.");
}
}
}
저장된 전체 객체를 대상으로 하나씩 얻고 싶은 경우
1) keySet()
Map<String, Interger> map = new HashMap<>();
Set<String> keySet = map.keySet(); //모든 키를 set컬렉션으로 추출
Iterator<String> keyIterator = keySet.iterator(); // 반복자 생성
while(keyIterator.hasNext()) { // hasNext() boolean타입
String key = keyIterator.next();
//key 값은 get할 수 없기 때문에 set형태로 바꿈
V value = map.get(key);
}
2) entrySet() 메소드로 모든 Map.Entry를 Set 컬렉션으로 얻은 다음 반복자를 통해 Map.Enrty를 하나씩 얻고
getKey()와 getValue() 메소드를 이용해 키와 값을 얻는 방법
Set<map.Entry<String, Integer>> entrySet = map.entrySet(); //모든 map을 set에 저장
Iterator<map.Entry<String, Integer>> entryIterator = entrySet.iterator();
//반복자를 통해 Map.Entry 하나씩 얻음
while(entryIterator.hasNext()){
Map.Entry<String, Integer> entry = entryIterator.next();
String key = entry.getKey(); //getKey() 이용해 키 출력
Int value = entry.getValue(); //getValue() 이용해 값 출력
}
for(Entry<String, Integer> entrySet : sum.entrySet()) {
System.out.println(entrySet.getKey()+ "\t"+entrySet.getValue());
}
Hashtable
Map<String, String> map = new Hashtable<>();
HashMap과 동일한 내부구조를 가지고 있음 키로 사용할 객체는 hashCode()와 equals()메소드를 재정의해서 동등 책객체가 될 조건을 정함
차이점은 동기화된 메소드로 구성되어있기 때문에 멀티 스레드가 동시에 실행시킬 수 없음 thread safe함