


List 구현체로는 ArrayList, LinkedList 등이 있다.List<String> names = new ArrayList<>(); 코드는 문자열을 저장하는 ArrayList를 생성한다.Set 인터페이스는 중복을 허용하지 않는 컬렉션을 나타낸다. 즉, 같은 요소를 두 번 이상 포함할 수 없다.Set은 저장된 요소 간의 순서를 보장하지 않는다.HashSet, LinkedHashSet, TreeSet 등이 대표적인 Set 구현체이다.Set<String> uniqueNames = new HashSet<>(); 코드는 중복되지 않는 문자열을 저장할 수 있는 HashSet을 생성한다.
Map<K, V> 인터페이스는 키-값 쌍을 저장하는 구조이다. 여기서 K는 키, V는 값이다.HashMap, LinkedHashMap, TreeMap 등이 있다.Map<String, Integer> ageMap = new HashMap<>(); 코드는 문자열 키와 정수 값을 가진 HashMap을 생성한다.ArrayList는 Java의 Collection 프레임워크 내에서 매우 유용하고 자주 사용되는 클래스이다. 이 클래스는 List 인터페이스를 구현하며, 다음과 같은 특징을 가지고 있다.
동적 배열 구현체: ArrayList는 내부적으로 배열을 사용하여 요소들을 저장한다. 배열과 달리, ArrayList는 자동으로 크기를 조절한다. 즉, 요소들이 추가되거나 제거될 때 내부 배열의 크기가 동적으로 변한다.
순서 유지: ArrayList에 요소를 추가하면, 각 요소는 추가된 순서대로 저장된다. 따라서, 요소를 순서대로 검색하거나 반복할 수 있다.
중복 허용: ArrayList는 중복된 요소의 저장을 허용한다. 같은 값이나 객체를 여러 번 리스트에 추가할 수 있다.
랜덤 액세스: 내부적으로 배열을 사용하기 때문에, ArrayList는 인덱스를 통한 빠른 요소 접근을 제공한다. get(int index) 메소드를 사용하여 특정 인덱스의 요소에 빠르게 접근할 수 있다.
확장성: ArrayList는 초기 용량(capacity)이 있으며, 이 용량이 초과될 때마다 자동으로 용량이 늘어난다. 이 과정은 '리사이징'이라고 하며, 새로운 더 큰 배열을 생성하고 기존의 요소들을 이 새 배열로 복사하는 방식으로 이루어진다.
다양한 작업 지원: ArrayList는 요소를 추가, 제거, 검색하는 등의 다양한 작업을 지원한다. 예를 들어 add(E e), remove(int index), indexOf(Object o) 같은 메소드들이 있다.
import java.util.ArrayList;
public class Example {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
// 요소 추가
list.add("Java");
list.add("Python");
list.add("C++");
// 특정 인덱스의 요소 얻기
String firstItem = list.get(0); // "Java"
// 리스트의 크기
int size = list.size(); // 3
}
}
import java.util.ArrayList;
import java.util.Collections;
public class ArrayListExam {
public static void main(String[] args) {
// ArrayList 초기화: Integer 타입을 저장할 수 있는 ArrayList 생성
ArrayList<Integer> list1 = new ArrayList<Integer>();
// 현재 리스트 크기 출력 (초기 크기는 0)
System.out.println("list1.size() : " + list1.size());
// 요소 추가: Integer 객체 및 int 값 추가 (오토 박싱 활용)
list1.add(new Integer(5)); // Integer 객체 저장
list1.add(1); // int가 Integer로 자동 변환되어 저장됨
list1.add(5);
list1.add(6);
list1.add(7);
// 리스트 내용 출력
System.out.println("list1 : " + list1.toString());
// 지정된 위치에 요소 추가: 0번 인덱스에 100 추가
list1.add(0, 100);
// 추가 후 리스트 내용 출력
System.out.println("0번 인덱스에 100 add 후 : " + list1.toString());
// 요소 수정: 0번 인덱스의 요소를 999로 변경
list1.set(0, 999);
// 수정 후 리스트 크기 및 내용 출력
System.out.println("list1.size() : " + list1.size());
System.out.println("0번 인덱스에 999 set 후 : " + list1.toString());
// 특정 위치의 요소 조회 및 출력
Integer firstData = list1.get(0);
System.out.println("list1.get(0) : " + firstData);
System.out.println(list1);
// 특정 위치의 요소 삭제 및 삭제된 요소 반환
int returnValue = list1.remove(0);
// 삭제 후 리스트와 삭제된 요소 출력
System.out.println("0번 인덱스 remove 후 : " + list1);
System.out.println(returnValue);
// 특정 값의 요소 삭제: 값 5를 가진 요소 삭제
boolean removeSuccess = list1.remove(new Integer(5));
// 삭제 성공 여부 및 리스트 내용 출력
System.out.println(removeSuccess); // true
System.out.println(list1);
System.out.println("--------------------");
// 0번 인덱스에 999를 다시 추가
list1.add(0, 999);
System.out.println(list1);
// 특정 데이터의 존재 여부 확인
boolean contains999 = list1.contains(999);
System.out.println("list1.contains(999) : " + contains999);
// 리스트의 순서를 역순으로 변경
System.out.println("--- Collections.reverse() 사용 ---");
Collections.reverse(list1);
System.out.println("reverse 후 : " + list1);
// 리스트의 일부분을 부분 리스트로 생성
System.out.println("subList : " + list1.subList(1, 4));
// 생성된 부분 리스트를 새 ArrayList에 저장
ArrayList<Integer> list2 = new ArrayList<Integer>(list1.subList(1, 4));
System.out.println("list2 : " + list2);
// 리스트 정렬
System.out.println("--- Collections.sort() ---");
Collections.sort(list2);
System.out.println("Collections.sort(list2) 후 : " + list2);
System.out.println("=============================");
System.out.println("list2 : " + list2);
// list2의 모든 요소를 순회하여 출력
for (int i = 0; i < list2.size(); i++) {
System.out.println(i + " : " + list2.get(i));
}
}
}
list1.size() : 0
list1 : [5, 1, 5, 6, 7]
0번 인덱스에 100 add 후 : [100, 5, 1, 5, 6, 7]
list1.size() : 6
0번 인덱스에 999 set 후 : [999, 5, 1, 5, 6, 7]
list1.get(0) : 999
[999, 5, 1, 5, 6, 7]
0번 인덱스 remove 후 : [5, 1, 5, 6, 7]
999
true
[1, 5, 6, 7]
--------------------
[999, 1, 5, 6, 7]
list1.contains(999) : true
--- Collections.reverse() 사용 ---
reverse 후 : [7, 6, 5, 1, 999]
subList : [6, 5, 1]
list2 : [6, 5, 1]
--- Collections.sort() ---
Collections.sort(list2) 후 : [1, 5, 6]
=============================
list2 : [1, 5, 6]
0 : 1
1 : 5
2 : 6
java.util.Vector 클래스는 Java의 컬렉션 프레임워크의 일부로, 동적 배열을 구현한다. ArrayList와 유사하지만 몇 가지 중요한 차이점이 있다.
동기화(Synchronization): Vector는 메소드들이 동기화되어 있어 멀티스레드 환경에서 안전하다(thread-safe). 즉, 여러 스레드가 동시에 Vector 객체를 수정하더라도 안전하게 작동한다. 반면, ArrayList는 동기화되어 있지 않다.
크기 증가: Vector의 기본 생성자는 기본 크기가 10인 배열을 생성한다. 배열이 가득 차면, Vector는 자동으로 크기를 늘린다. 이 크기 확장 비율은 생성자에서 설정할 수 있다.
레거시 클래스(Legacy Class): Vector는 Java 1.0부터 있었던 클래스로, 컬렉션 프레임워크가 도입되기 전부터 사용되어 왔다. 이후 Java 1.2에서 ArrayList와 함께 컬렉션 프레임워크가 도입되었고, Vector도 이 프레임워크의 일부가 되었다.
성능: Vector의 동기화 특성 때문에 ArrayList보다 성능이 조금 떨어질 수 있다. 대부분의 단일 스레드 애플리케이션에서는 ArrayList가 더 효율적이다.
API: Vector는 List 인터페이스를 구현하므로, List 인터페이스의 모든 메소드를 사용할 수 있다. 또한, Vector는 자체적인 메소드들도 가지고 있다(예: addElement, removeElement 등).
import java.util.Vector;
public class VectorExample {
public static void main(String[] args) {
Vector<Integer> v = new Vector<Integer>();
v.add(1); // 요소 추가
v.add(2);
v.add(3);
System.out.println("Vector: " + v);
}
}
이 예시에서는 Vector에 정수 요소를 추가하고, 이를 출력한다. Vector는 다양한 상황에서 유용할 수 있지만, 동기화가 필요 없는 상황에서는 ArrayList를 사용하는 것이 일반적으로 더 좋다.
맞다
Vector도 내부적으로 배열을 사용하여 데이터를 저장한다. 이 점에서 ArrayList와 유사하다. 두 클래스 모두 내부적으로는 배열을 사용하여 요소들을 관리하는 동적 배열(dynamic array) 구현이다. 그러나 Vector와 ArrayList 사이에는 몇 가지 차이점이 있다.
동기화: 가장 큰 차이점은 Vector의 메소드들이 동기화되어 있다는 것이다. 이는 Vector가 멀티스레드 환경에서 안전하게 사용될 수 있음을 의미한다. 반면, ArrayList는 동기화되지 않는다.
성능: Vector의 동기화로 인해 ArrayList에 비해 성능상의 오버헤드가 있다. 단일 스레드 애플리케이션에서는 ArrayList가 Vector보다 더 빠른 성능을 제공한다.
용량 증가 방식: 두 클래스 모두 필요에 따라 자동으로 용량을 증가시킨다. 그러나 Vector는 기본적으로 용량이 100% 증가하는 반면, ArrayList는 기본적으로 용량이 50% 증가한다.
이러한 차이점에도 불구하고, Vector와 ArrayList는 둘 다 내부적으로 배열을 사용하여 요소들을 저장하고 관리하는 것은 동일하다. 요소들의 추가, 삭제, 접근 등의 작업이 배열을 기반으로 이루어지며, 배열의 크기를 동적으로 조정하여 컬렉션의 크기가 변경될 때마다 내부 배열의 크기도 조절한다.
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
public class Vector_Exam {
public static void main(String[] args) {
// Vector 클래스 초기화 및 요소 추가
Vector<String> v = new Vector<String>();
v.add("1"); // 요소 "1" 추가
v.add("2"); // 요소 "2" 추가
v.add("3"); // 요소 "3" 추가
// Vector의 현재 상태 출력
System.out.println("v : " + v);
System.out.println("v.size() : " + v.size()); // Vector의 현재 크기 출력
System.out.println("v.capacity() : " + v.capacity()); // Vector의 현재 용량 출력
// Vector의 문자열 표현 저장 및 출력
String temp = v.toString();
System.out.println(temp);
// Vector에서 요소 제거
v.remove(2); // 인덱스 2의 요소(세 번째 요소) 제거
// 요소 제거 후 Vector의 상태 출력
System.out.println("v : " + v);
System.out.println("v.size() : " + v.size());
System.out.println("v.capacity() : " + v.capacity());
// Vector의 용량을 현재 크기에 맞게 조정
v.trimToSize();
// 용량 조정 후 Vector의 상태 출력
System.out.println("v : " + v);
System.out.println("v.size() : " + v.size());
System.out.println("v.capacity() : " + v.capacity());
// 요소 추가
v.addElement("4문자열"); // "4문자열" 추가
System.out.println("v : " + v);
// 특정 위치에 요소 추가
v.add(2, "BBB"); // 인덱스 2 위치에 "BBB" 추가
System.out.println("v : " + v);
// Vector 복제
Vector<String> v2 = (Vector) v.clone();
// 원본 Vector와 복제본 Vector의 상태 출력
System.out.println("v : " + v);
System.out.println("v2 : " + v2);
// 원본 Vector와 복제본 Vector의 동일성 비교
System.out.println("v == v2 : " + (v == v2));
// Enumeration을 이용한 요소 순회
System.out.println("========================");
Enumeration<String> enu = v.elements();
while (enu.hasMoreElements()) {
System.out.println("enu.nextElement() : " + enu.nextElement());
}
// Iterator를 이용한 요소 순회
System.out.println("----------------------");
System.out.println("=== Iterator 사용 데이터 조회 ===");
Iterator<String> ite = v.iterator();
System.out.println("ite.hasNext() : " + ite.hasNext());
while (ite.hasNext()) {
System.out.println("ite.next() : " + ite.next());
}
System.out.println("ite.hasNext() : " + ite.hasNext());
// 개선된 for문을 이용한 요소 순회
System.out.println("=== 개선된 for 문 사용 ===");
for (String str : v) {
System.out.println(str);
}
}
}

LinkedList는 Java의 Collection 프레임워크에 속하는 List 인터페이스의 구현 클래스 중 하나이다. 이 클래스는 연결 리스트를 기반으로 하며, 다음과 같은 특징들을 가진다.
연결 리스트 구조: 각 요소(노드)는 자신의 데이터와 다음 요소에 대한 참조(링크)를 포함한다. 이 구조 덕분에 요소의 추가, 삭제가 빠르게 이루어진다.
동적 크기 조정: LinkedList는 요소가 추가되거나 제거될 때 자동으로 크기를 조정한다. 이 때문에 크기 변경에 대한 고민 없이 원하는 만큼 요소를 추가하거나 제거할 수 있다.
양방향 순회 가능: LinkedList는 각 노드가 이전 노드와 다음 노드를 가리키는 양방향 연결 리스트이다. 이를 통해 리스트를 앞에서 또는 뒤에서부터 순회할 수 있다.
인덱스를 통한 접근: LinkedList는 인덱스를 통해 특정 위치의 요소에 접근할 수 있지만, 내부적으로는 처음 또는 끝에서부터 해당 위치까지 순회해야 하므로, 이러한 접근은 ArrayList보다 느리다.
List 및 Deque 인터페이스 구현: LinkedList는 List 인터페이스 외에도 Deque(덱) 인터페이스를 구현한다. 따라서 스택이나 큐처럼 사용할 수 있으며, 요소를 리스트의 앞이나 뒤에 추가하거나 제거하는 메소드들을 제공한다.
중복 요소 허용: LinkedList는 중복 요소를 허용한다. 같은 값을 여러 번 추가할 수 있으며, 순서가 유지된다.
import java.util.LinkedList;
public class LinkedListExample {
public static void main(String[] args) {
// LinkedList 생성
LinkedList<String> animals = new LinkedList<>();
// 요소 추가
animals.add("Dog");
animals.add("Cat");
animals.add("Horse");
// 맨 앞과 맨 뒤에 요소 추가
animals.addFirst("Bird");
animals.addLast("Elephant");
// LinkedList 출력
System.out.println("LinkedList: " + animals);
// 특정 위치의 요소 조회
String firstAnimal = animals.get(0); // 첫 번째 요소
String lastAnimal = animals.getLast(); // 마지막 요소
System.out.println("First Animal: " + firstAnimal);
System.out.println("Last Animal: " + lastAnimal);
// 특정 요소 삭제
animals.remove("Horse");
animals.removeFirst(); // 첫 번째 요소 삭제
animals.removeLast(); // 마지막 요소 삭제
// 수정된 LinkedList 출력
System.out.println("Updated LinkedList: " + animals);
}
}
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class LinkedListExam {
public static void main(String[] args) {
// LinkedList 초기화: String 타입을 저장할 수 있는 LinkedList 생성
LinkedList<String> list = new LinkedList<String>();
// 요소 추가: "홍길동", "홍길동", "김유신" 순서대로 추가
list.add("홍길동"); // 0번 인덱스
list.add("홍길동"); // 1번 인덱스
list.add("김유신"); // 2번 인덱스
// 리스트 내용 출력
System.out.println("list : " + list);
// 첫 번째 요소 조회 및 출력
System.out.println(list.get(0));
// "홍길동" 문자열을 가진 첫 번째 요소 삭제
list.remove("홍길동");
// 삭제 후 리스트 내용 출력
System.out.println("list : " + list);
System.out.println("---------------");
// 문자열에서 배열로 변환하여 요소 추가
String str = "홍길동,홍길동,김유신,강감찬,을지문덕,홍경래,김유신,홍길동";
String[] names = str.split(",");
// 배열 내용 출력
System.out.println("names : " + Arrays.toString(names));
// 배열에 있는 데이터를 리스트에 추가
for (int i = 0; i < names.length; i++) {
list.add(names[i]);
}
// 추가 후 리스트 내용 출력
System.out.println("list : " + list);
//--------------------
// 리스트 내 "홍길동" 모두 삭제
while(list.contains("홍길동")) {
list.remove("홍길동");
}
// 삭제 후 리스트 내용 출력
System.out.println(list);
// 리스트 내 "김유신"을 "김유신2"로 변경
list.replaceAll(s -> !s.equals("김유신")? s : "김유신2");
// 변경 후 리스트 내용 출력
System.out.println(list);
}
}
Iterator는 Java의 컬렉션 프레임워크에서 컬렉션의 요소에 접근하고 순회하기 위한 표준 방법을 제공하는 인터페이스이다. 주로 List, Set과 같은 컬렉션 클래스들과 함께 사용된다. Iterator를 사용하면 컬렉션의 내용을 변경하지 않고 각 요소에 순차적으로 접근할 수 있다.
hasNext(): Iterator가 다음 요소를 가지고 있는지 여부를 반환한다. 컬렉션의 요소를 순회할 때, hasNext() 메소드는 더 이상 순회할 요소가 없을 때까지 true를 반환한다.
next(): Iterator의 다음 요소를 반환한다. hasNext() 메소드가 true를 반환하는 경우에만 next() 메소드를 호출해야 한다. 만약 더 이상 순회할 요소가 없는데 next() 메소드를 호출하면 NoSuchElementException이 발생한다.
remove(): Iterator를 사용하여 순회 중인 요소를 제거한다. 이 메소드는 next() 메소드를 호출한 다음에만 사용할 수 있으며, 한 번의 next() 호출에 대해 한 번만 사용할 수 있다.
import java.util.ArrayList;
import java.util.Iterator;
public class IteratorExample {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
Iterator<Integer> it = numbers.iterator();
while (it.hasNext()) {
int value = it.next();
System.out.println(value);
if (value == 2) {
it.remove(); // 요소 '2'를 제거
}
}
System.out.println(numbers); // [1, 3] 출력
}
}
이 예시에서 Iterator는 ArrayList의 모든 요소를 순회한다. hasNext() 메소드를 사용하여 더 이상 순회할 요소가 없을 때까지 반복하고, next() 메소드로 각 요소를 가져온다. 필요한 경우 remove() 메소드를 사용하여 현재 요소를 제거할 수도 있다.
Enumeration은 Java에서 컬렉션의 요소들을 순회하기 위한 또 다른 방법이다. Iterator와 유사하게, Enumeration은 컬렉션의 요소에 순차적으로 접근할 수 있게 해준다. 주로 오래된 코드나 레거시 API에서 사용되며, 주로 Vector나 Hashtable과 같은 구식 클래스들과 함께 사용된다.
Enumeration 인터페이스의 주요 메소드는 다음과 같다.
hasMoreElements(): Enumeration에 더 이상 순회할 요소가 있는지 여부를 반환한다. 이 메소드는 Iterator의 hasNext()와 유사한 역할을 한다.
nextElement(): Enumeration에서 다음 요소를 반환한다. 이 메소드는 Iterator의 next()와 유사하다.
Enumeration은 Iterator와 비교했을 때 몇 가지 제한 사항이 있다. 가장 주목할 만한 것은 remove() 메소드가 없다는 점이다. 즉, Enumeration을 사용하는 동안 컬렉션의 요소를 제거할 수 없다. 이러한 이유로, Enumeration은 주로 읽기 전용으로 데이터를 순회할 때 사용된다.
import java.util.Enumeration;
import java.util.Vector;
public class EnumerationExample {
public static void main(String[] args) {
Vector<Integer> numbers = new Vector<Integer>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
Enumeration<Integer> en = numbers.elements();
while (en.hasMoreElements()) {
int value = en.nextElement();
System.out.println(value);
}
}
}
이 예시에서 Enumeration은 Vector의 모든 요소를 순회한다. hasMoreElements() 메소드를 사용하여 더 이상 순회할 요소가 없을 때까지 반복하고, nextElement() 메소드로 각 요소를 가져온다.
요약하자면, Enumeration은 Java의 초기 버전에서 컬렉션의 요소들을 순회하는 기본적인 방법이었다. 현대의 Java 코드에서는 Iterator나 개선된 for문(for-each 루프)이 더 널리 사용되며, Enumeration은 주로 레거시 코드나 오래된 API에서만 볼 수 있다.