Information Security Study

240123 자바 API(제네릭, collection, List, ArrayList, LinkedList, Set, Iterator, HashSet, Map, HashMap) 본문

네트워크 캠퍼스/JAVA

240123 자바 API(제네릭, collection, List, ArrayList, LinkedList, Set, Iterator, HashSet, Map, HashMap)

gayeon_ 2024. 1. 23. 15:49

제네릭(generic)

  • 제네릭이란 클래스나 인터페이스 선언에 유형 매개변수가 들어있는 클래스를 뜻한다.
  • 제네릭 타입은 클래스 또는 인터페이스 이름 뒤에 "<>"부호가 붙고, 그 사이에 파라미터가 위치한다.
  • 자바 5 버전부터 제네릭이 도입된 이후에는 제네릭 기능으로 인해 클래스에 원하지 않는 데이터형이 들어가는 것을 방지할 수 있고, 반대로 값을 가져올 때도 형 변환을 하지 않게 되었다.
  • 제네릭은 형 안정성(type safety)을 위해 사용한다.
  • 제네릭 내부에서 주소값만 받아올 수 있도록 설계가 되어있기 때문에 <>안에 기본 타입을 사용할 수 없다. 참조 타입만 가능하다.

 

 

Collection

  • 자바 프로그램에서 객체를 객체들의 모음 형식으로 관리할 수 있는 방법을 제공하는 클래스들을 컬렉션이라고 부른다.
  • 컬렉션은 배열과 유사하지만 데이터를 저장/조회/수정/삭제하는 작업을 쉽게 처리할 수 있으며, 동적인 크기를 갖는다는 장점이 있다.
  • 컬렉션 계열은 Set/List/Map 등의 인터페이스가 있으며 이를 구현한 클래스를 이용하면 객체들을 모음저장할 수 있다.

 

 

List 컬렉션

  • List 컬렉션은 객체를 인덱스로 관리하기 때문에 객체를 저장하면 자동으로 인덱스 번호가 부여되고 인덱스를 통해 객체를 검색, 삭제할 수 있는 기능을 제공한다.
  • List 는 객체를 순서대로 저장하며 동일한 객체를 중복 저장할 수 있다.

 

List 계열 주요 메서드

  • 객체 추가 기능
  1. add(E e): 주어진 객체를 List의 맨 끝부분에 추가
  2. add(int index, E e): 주어진 인덱스에 객체를 추가
  3. set(int index, E e): 주어진 인덱스에 저장된 객체를 주어진 객체로 바꿈
  • 객체 검색 기능
  1. contains(Object o): 주어진 객체가 저장되어있는지의 여부를 판단
  2. get(int index): 주어진 인덱스에 저장되어 있는 객체를 리턴
  3. isEmpty(): 컬렉션이 비어있는지의 여부를 판단
  4. size(): 저장되어 있는 전체 객체 수를 리턴
  • 객체 삭제 기능
  1. clear(): 저장된 모든 객체를 삭제
  2. remove(int index): 주어진 인덱스에 저장된 객체를 삭제
  3. remove(Object o): 주어진 객체를 삭제

 

 

ArrayList

  • ArrayList 클래스는 List 인터페이스의 구현 클래스로 ArrayList에 객체를 추가하면 객체가 인덱스로 관리된다.
  • 일반 배열과 ArrayList는 인덱스로 객체를 관리한다는 점에서는 유사하지만 배열은 생성될 때 크기가 고정되고, 사용 중에 크기를 변경할 수 없지만 ArrayList는 저장 용량을 초과한 객체들이 들어오면 자동으로 저장 용량을 증가시킨다.
  • 기본 생성자로 ArrayList 객체를 생성하면 내부에 10개의 객체를 저장할 수 있는 초기 용량을 가지게 되며 저장되는 객체 수가 증가하면 용량이 자동적으로 증가한다.
  • ArrayList에 특정 인덱스의 객체를 제거하면 자동으로 바로 뒤 인덱스부터 마지막 인덱스까지 모두 앞으로 1칸씩 당겨진다.

 

 

LinkedList

  • LinkedList는 List 인터페이스를 구현한 클래스이며 ArrayList와 사용 방법은 같지만 내부 구조는 완전히 다르다.
  • ArrayList는 내부 배열에 객체를 저장하여 인덱스로 관리하지만 LinkedList는 인접 참조를 링크하여 체인처럼 관리한다.
  • ArrayList는 특정 인덱스의 객체를 제거하면 뒤의 모든 객체가 앞으로 한칸씩 당겨지지만, LinkedList는 특정 인덱스의 객체를 제거하면 앞 뒤 링크만 변경되고 나머지 링크는 변경되지 않아 빈번한 객체의 삭제와 삽입이 일어나는 로직에서는 ArrayList보다 좋은 성능을 발휘한다.

 

예제

package collection.list;

import java.util.ArrayList;
import java.util.List;

public class ListExample {

	public static void main(String[] args) {
		// ArrayList와 LinkedList는 사용 양식은 전부 List 인터페이스를 따른다.
		// 따라서 교환이 가능하다.
		// 인터페이스가 같은 구현체들은 사용법이 모두 같다.
		// 제네릭: 타입 안정화를 위해 객체 내부에 저장되는 타입을 일치시키는 방법
		// String만 저장할 수 있는 컬렉션
		
		// 다형성이 적용되는 특정 인터페이스 타입에 구현체를 선택적으로 대입하는 패턴을 전략패턴이라고 한다.
		List<String> list = new ArrayList<>(); // 1.8버전부터는 생성자에 제네릭 표시 X
//		List<String> list = new LinkedList<>(); 위와 동일하게 사용 가능
		
		String str1 = "Java";
		String str2 = "SpringBoot";
		System.out.println(list); // 컬렉션들은 toString()이 자동으로 오버라이딩되어
								  // 주소값이 아닌 내부 저장 요소가 바로 콘솔에 찍힘
		// list에 객체를 저장하는 메서드 add(): 데이터를 마지막 지점에 추가
		list.add(str1);
		list.add(str2);
		list.add("infra");
		list.add("docker");
		list.add("linux");
		list.add("linux"); // 중복 저장 허용
		System.out.println(list);
		
		// list에 저장된 총 객체 수 얻기 .size()
		int size = list.size();
		System.out.println("list에 저장된 총 객체의 수: " + size);

		// list에 객체 삽입 add(index, 객체): 데이터를 해당 인덱스 번호에 넣고
		// 해당 인덱스 이후 자료는 전부 한 칸씩 뒤로 밀어내기
		list.add(2, "Network");
		System.out.println(list);
		
		// list 데이터 수정 set(index, 객체)
		// list[5] = "ubuntu"; // 일반 인덱싱으로 수정하기 사용 불가
		list.set(5, "ubuntu");
		System.out.println(list);
		
		// list 내부 객체 가져오기 get(index)
		String s = list.get(2);
		System.out.println(s);
		
		// list 내부에 저장된 객체의 번호가 몇 번인지 확인하기
		int idx = list.indexOf("docker");
		System.out.println(idx);
		
		// list에서 객체데이터 삭제 remove(index), remove(객체)
		list.remove(5);
		System.out.println(list);
		list.remove(str1);
		System.out.println(list);
		
		// list 내부에 저장된 객체의 유무확인 contains() -> 있으면 true, 없으면 false
		System.out.println(list.contains(str2));
		
		// list의 반복문 처리
		// 인덱스로 조회
		for(int i = 0; i < list.size(); i++) {
			System.out.println("내부요소: " + list.get(i));
		}
		System.out.println("-----------------");
		
		// 향상된 for문도 사용 가능(List<String>으로 선언했으므로 String으로 받기)
		for(String str : list) {
			System.out.println("내부요소 " + str);
			
		}
		
		// list 내부의 전체 자료 삭제 clear()
		list.clear();
		
		// list 내부 데이터가 전부 비었는지 확인하는 메서드 isEmpty()
		System.out.println(list.isEmpty());
	}
	


}

 

다형성이 적용되는 특정 인터페이스 타입에 구현체를 선택적으로 대입하는 패턴을 전략패턴이라고 한다.

 

ArrayList는 조회가 빈번한 경우 사용하고

추가, 삭제가 빈번한 경우에는 LinkedList를 사용하는 게 좋다.

 

 

Set 계열 컬렉션

  • Set 컬렉션은 저장 순서를 보장하지 않으며 객체의 중복 저장을 허용하지 않는다.
  • Set 컬렉션은 인덱스로 관리하지 않으며 들어갈 때의 순서와 나올 때의 순서가 다를 수도 있다.
  • Set 컬렉션은 인덱스로 객체를 검색하는 기능이 없고 전체 객체를 대상으로 한번씩 반복해서 객체의 값을 가져오는 반복자(Iterator)를 제공한다.
  • 반복자는 Iterator 인터페이스를 구현한 객체를 의미하며 이 객체는 Set 인터페이스의 iterator() 메서드를 호출하여 객체를 얻을 수 있다.

 

 

Iterator 인터페이스의 주요 메서드

  1. hasNext(): 가져올 객체가 있으면 true를 리턴하고 없으면 false를 리턴.
  2. next(): 컬렉션에서 하나의 객체를 가져옴.
  3. remove(): Set 컬렉션에서 객체를 제거함.

 

 

Set 계열 컬렉션 주요 메서드

  • 객체 추가 기능
  1. add(E e): 주어진 객체를 저장, 성공적으로 저장되면 true를 리턴, 중복 객체를 저장하면 false를 리턴.

 

  • 객체 검색 기능
  1. contains(Object o): 주어진 객체가 저장되어 있는지의 여부를 판단.
  2. isEmpty(): 컬렉션이 비어있는지를 조사.
  3. iterator(): 저장된 객체를 한번씩 가져오는 반복자 객체를 리턴.
  4. size(): 저장되어 있는 전체 객체 수를 리턴.

 

  • 객체 삭제 기능
  1. clear(): 저장된 모든 객체를 삭제.
  2. remove(Object o): 주어진 객체를 삭제.

 

 

HashSet

  • HashSet 클래스는 Set 인터페이스를 구현한 컬렉션이므로 저장된 객체의 순서를 보장하지 않고 중복을 허용하지 않는다.
  • HashSet을 사용하면 많은 양의 데이터를 관리할 때 추가/삭제/검색 등에 있어서 순차적으로 데이터를 관리하는 것에 비하여 속도가 향상된다.

 

 

Map 계열 컬렉션

  • Map 컬렉션은 키(key)와 값(value)으로 구성된 Entry객체를 저장하는 구조를 가지고 있다.
  • 키는 중복저장 될 수 없지만 값은 중복저장 될 수 있다.

 

Map 계열 주요 메서드

  • 객체 추가 기능
  1. put(K key, V value): 주어진 키와 값을 추가, 정상적으로 저장되면 그 값(value)를 리턴.

 

  • 객체 검색 기능
  1. containsKey(Object Key): 주어진 키가 있는지의 여부를 확인.
  2. containsValue(Object value): 주어진 값이 있는지의 여부를 확인.
  3. get(Object key): 주어진 키에 들어있는 값을 리턴.
  4. isEmpty(): 컬렉션이 비어있는지의 여부를 확인.
  5. size(): 저장된 키의 총 수를 리턴.
  6. values(): 저장된 모든 값을 컬렉션에 담아서 리턴.
  7. keySet(): 저장된 모든 키를 Set객체에 담아서 리턴.
  8. entrySet(): 키와 값의 쌍으로 구성된 모든 Entry객체를 Set에 담아서 리턴.

 

  • 객체 삭제 기능
  1. clear(): 모든 Entry를 삭제
  2. remove(Object key): 주어진 키와 일치하는 Entry객체를 삭제.

 

 

HashMap

  • HashMap은 Map 인터페이스를 구현한 대표적인 Map 컬렉션이다.
  • 키와 값의 타입은 기본 타입을 사용할 수 없고, 클래스 및 인터페이스 타입만 사용이 가능하다.

 

예제

package collection.map;

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

public class HashMapExample {
	public static void main(String[] args) {
		// Map<key, value>
		Map<String, Integer> map = new HashMap<>();
		
		// Map에 객체를 저장 put(key, value)
		map.put("치킨", 30000);
		map.put("양꼬치", 50000);
		map.put("랍스터", 120000);
		
		// 중복된 key로 입력 시, 가장 마지막에 넣은 하나만 적용된다.
		map.put("치킨", 25000);
		
		System.out.println(map);
		
		// Map에 저장된 key, value쌍(entry)의 개수 측정: size()
		System.out.println(map.size());
		
		// Map에 저장된 value값을 key값으로 얻기: getkey
		int price = map.get("랍스터"); // Integer price = map.get("랍스터");도 가능
		System.out.println("랍스터의 가격: " + price + "원");
		
		// Map에서 Key만 전부 추출하기
		// 앞서 배운 Set 형식으로 추출된다.
		Set<String> kSet = map.keySet();
		System.out.println(kSet);
		System.out.println(map.keySet());
		
		// Iterator로 변경해서 저장
		Iterator<String> kIter = kSet.iterator(); // Set에서 배운거 복습
		System.out.println("------------------");
		
		// Iterator를 while문으로 반복시켜서 모든 매뉴의 값을 출력하기
		// XX 메뉴의 가격은 YY원입니다.
		while(kIter.hasNext()) {
			String menu = kIter.next();
			price = map.get(menu);
			
			System.out.println(menu + "메뉴의 가격은 " + price + "입니다.");
		}
		
		// Map 내부에 있는 key값의 유무 확인 containsKey()
		String food = "라멘";
		
		if(map.containsKey(food)) {
			System.out.println("우리 식당 " + food + " 팝니다.");
		} else {
			System.out.println("우리 식당 " + food + " 안 팝니다.");
		}
		
		// Map 내부 데이터 단일데이터 삭제 remove(key)
		// 일치하는 key값에 매칭된 entry 한 쌍을 삭제
		map.remove("랍스터");
		System.out.println(map);
		
		// Map 내부 전체 데이터 일괄삭제 clear()
		map.clear();
		
		System.out.println(map);
		
		if(map.isEmpty()) {
			System.out.println("빈 Map입니다.");
		} else {
			System.out.println("비어있지 않은 Map입니다.");
		}
	}
}