JAVA/JAVA BASIC

[JAVA] Collection Framework

아잠만_ 2024. 3. 28. 11:42

일반적으로 한번 정해진 배열의 크기를 변경할 수 없다

그래서 배열의 크기를 늘리고 싶다면 새로운 배열을 만들어 복사하는 방식으로만 배열크기를 늘리는 것이 가능하다


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함