Vector는 List 인터페이스를 구현한 클래스이며,
내부 메서드들이 synchronized 되어 있어 Thread-safe(쓰레드 안전성)을 제공합니다.
✅ 특징
ArrayList와 비슷하지만, 멀티스레드 환경에서 안전addElement(), elementAt(), size(), remove() 등의 메서드 지원ArrayList를 사용하는 것이 더 효율적import java.util.Vector;
public class VectorExample {
public static void main(String[] args) {
// Vector 생성
Vector<Person> v = new Vector<>();
// 요소 추가
v.addElement(new Person("홍길동", 29));
v.addElement(new Person("이순신", 30));
v.addElement(new Person("강감찬", 65));
System.out.println("Vector 요소: " + v); // 전체 출력
// 특정 요소 가져오기 (인덱스 기반)
Person p = v.elementAt(2);
System.out.println("인덱스 2의 요소: " + p.getName());
// 요소 제거
v.remove(1);
System.out.println("인덱스 1 제거 후: " + v);
// 현재 크기 확인
System.out.println("Vector 크기: " + v.size());
}
}
Stack은 Vector의 하위 클래스로, LIFO(Last-In-First-Out, 후입선출) 방식의 자료구조입니다.
✅ 특징
push(): 요소 추가pop(): 마지막 요소 제거 및 반환peek(): 마지막 요소 조회 (제거 X)empty(): 스택이 비어있는지 확인import java.util.Stack;
public class StackExample {
public static void main(String[] args) {
// Stack 생성
Stack<Person> stack = new Stack<>();
// 요소 추가 (push)
stack.push(new Person("홍길동", 29));
stack.push(new Person("이순신", 30));
stack.push(new Person("강감찬", 65));
System.out.println("Stack 전체: " + stack);
// pop(): 마지막 요소 제거 및 반환
Person p = stack.pop();
System.out.println("pop() 호출: " + p.getName());
System.out.println("Stack 상태: " + stack);
// peek(): 마지막 요소 조회 (제거되지 않음)
Person p2 = stack.peek();
System.out.println("peek() 호출: " + p2.getName());
System.out.println("Stack 상태: " + stack);
// empty(): 스택이 비었는지 확인
System.out.println("Stack이 비었는가? " + stack.empty());
}
}
Hashtable은 Map 인터페이스를 구현한 클래스이며,
HashMap과 유사하지만 Thread-safe합니다.
✅ 특징
Map과 동일하게 Key-Value 저장 구조put(), get(), remove() 메서드를 통해 데이터를 저장/삭제/조회 가능ConcurrentHashMap을 사용하면 보다 높은 성능 제공 가능| 비교 항목 | Hashtable | HashMap |
|---|---|---|
| Thread-safe | O (멀티스레드 환경에서 안전) | X (싱글스레드 환경에서 빠름) |
| null 허용 여부 | X (null key, null value 허용 안됨) | O (null key, null value 허용) |
| 속도 | 느림 (synchronized) | 빠름 |
Enumeration은 Vector, Stack, Hashtable 등에서 요소를 조회하는 클래스입니다.
✅ 특징
nextElement(): 다음 요소를 반환hasMoreElements(): 더 많은 요소가 있는지 확인import java.util.Enumeration;
import java.util.Vector;
public class EnumerationExample {
public static void main(String[] args) {
// Vector 생성
Vector<String> vector = new Vector<>();
vector.add("Apple");
vector.add("Banana");
vector.add("Cherry");
// Enumeration을 사용하여 요소 순회
Enumeration<String> e = vector.elements();
while (e.hasMoreElements()) {
System.out.println("다음 요소: " + e.nextElement());
}
}
}
자바에서는 List.of()와 List.copyOf()를 사용해 수정할 수 없는(immutable) 리스트를 만들 수 있습니다.
이러한 리스트는 생성 후 추가, 삭제, 변경이 불가능하여, 데이터를 안전하게 관리할 수 있습니다.
List.of() 사용UnsupportedOperationException 예외가 발생합니다.import java.util.List;
public class ImmutableListOf {
public static void main(String[] args) {
// 수정할 수 없는 리스트 생성
List<String> immutableList = List.of("apple", "banana", "orange");
// 생성된 리스트는 수정이 불가능 (실행 시 예외 발생)
immutableList.add("grape"); // UnsupportedOperationException 발생
// 리스트 조회는 가능
System.out.println("Immutable List: " + immutableList);
}
}
List.copyOf() 사용import java.util.ArrayList;
import java.util.List;
public class ImmutableListCopyOf {
public static void main(String[] args) {
// 변경 가능한 리스트 생성
List<String> mutableList = new ArrayList<>();
mutableList.add("apple");
mutableList.add("banana");
mutableList.add("orange");
// 기존 리스트를 복사하여 수정할 수 없는 리스트 생성
List<String> immutableList = List.copyOf(mutableList);
// 원본 리스트를 변경해도 immutableList는 영향을 받지 않음
mutableList.add("grape");
// immutableList는 변경되지 않음
System.out.println("Immutable List: " + immutableList);
}
}
자바에서 배열을 다룰 때 유용한 기능을 제공하는 Arrays 클래스의 주요 메서드를 정리합니다.
asList()import java.util.Arrays;
public class ArraysExample {
public static void main(String[] args) {
// 배열을 리스트로 변환
String[] fruitsArray = {"apple", "banana", "orange"};
System.out.println("Array to List: " + Arrays.asList(fruitsArray));
}
}
compare()Java 9부터 사용 가능)int[] array1 = {1, 2, 3};
int[] array2 = {1, 2, 3, 4};
int result = Arrays.compare(array1, array2);
if (result < 0) {
System.out.println("Array 1 is smaller than Array 2");
} else if (result > 0) {
System.out.println("Array 1 is larger than Array 2");
} else {
System.out.println("Both arrays are equal");
}
sort()int[] numbers = {5, 2, 9, 1, 3};
Arrays.sort(numbers);
System.out.println("Sorted Array: " + Arrays.toString(numbers));
toString()char[] charArray = {'a', 'b', 'c', 'd', 'e'};
System.out.println("Array to String: " + Arrays.toString(charArray));
deepToString()toString()을 사용하면 다차원 배열의 주소값이 출력되므로, deepToString()을 사용해야 합니다.int[][] matrix = {{1, 2}, {3, 4}, {5, 6}};
System.out.println("Matrix to String: " + Arrays.deepToString(matrix));
제네릭 클래스는 유형 매개변수(Type Parameter)를 포함하는 클래스입니다.
클래스 선언 시 <T>를 사용하여 유동적인 타입을 적용할 수 있습니다.
package generic;
public class Container<T> { // <T>: 제네릭 타입 매개변수
private T data; // 데이터 타입을 T로 지정 (어떤 타입이든 가능)
public T getData() { // 반환 타입도 T
return data;
}
public void setData(T data) { // 매개변수 타입도 T
this.data = data;
}
}
package generic;
public class GenericExample {
public static void main(String[] args) {
Container<String> cont1 = new Container<>(); // String 타입 지정
cont1.setData("Hello");
// cont1.setData(10); // 오류 발생 (타입 불일치)
String s1 = cont1.getData(); // 형변환 없이 안전한 반환
System.out.println(s1); // 출력: Hello
}
}
💡 Container<String>처럼 타입을 지정하면 컴파일 시 타입 검사가 이루어짐
💡 setData(10); 처럼 잘못된 타입을 입력하면 컴파일 오류 발생
제네릭을 사용할 때 특정 클래스나 인터페이스의 하위 클래스만 허용하도록 제한할 수 있습니다.
T extends SuperClass)T는 반드시 Number의 하위 클래스여야 함 (Integer, Double, Float 등 가능)String 같은 다른 타입은 사용할 수 없음package generic.upperbound;
class Box<T extends Number> { // T는 반드시 Number의 하위 클래스여야 함
private T value;
public Box(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public class UpperBoundExample {
public static void main(String[] args) {
Box<Integer> intBox = new Box<>(10); // 가능
System.out.println("Integer Value: " + intBox.getValue());
// Box<String> strBox = new Box<>("Hello"); // 컴파일 오류 발생
}
}
? super SubClass)? super Integer → Integer의 상위 클래스만 허용 (Number, Object 등 가능)getValue()를 호출하면 반환 타입이 Object가 됨package generic.lowerbound;
class Box<T> {
private T value;
public Box(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public class LowerBoundExample {
public static void main(String[] args) {
Box<? super Integer> intBox = new Box<>(10); // Integer의 상위 타입만 허용
Object value = intBox.getValue(); // Object 타입으로 반환
System.out.println("Value: " + value);
// intBox.setValue("Hello"); // 컴파일 오류 발생 (String은 허용되지 않음)
}
}
제네릭 메서드는 메서드 내부에서만 제네릭 타입을 적용하는 방법입니다.
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess {
public boolean add(E o) { // 요소의 타입을 E로 지정
// ...
return true;
}
}
public <T extends Person> void doSomething(ArrayList<T> list) {
// T는 반드시 Person의 하위 클래스여야 함
}
💡 T extends Person → Person 또는 그 하위 클래스만 허용
?)를 사용한 제네릭 메서드public void doSomething(ArrayList<? extends Person> list) {
// Person의 하위 타입을 포함한 리스트 허용
}
💡 ? extends Person → Person을 포함한 그 하위 클래스도 허용
💡 ? super Person → Person의 상위 클래스만 허용
enum은 고정된 상수들의 집합을 정의하는 자료형으로, 기존 public static final int 방식보다 더 타입 안정성(type-safe)을 갖습니다.
또한, enum은 메서드, 생성자, 필드 등을 포함할 수 있어 클래스처럼 동작합니다.
package enums;
public enum Coin {
PENNY, // 1센트
NICKEL, // 5센트
DIME, // 10센트
QUARTER; // 25센트
}
static final 상수처럼 동작enum은 특정 타입을 명확히 지정하여 형 안정성을 제공int 상수보다 가독성이 좋고 유지보수가 쉬움package enums;
public class EnumBasicExample {
public static void main(String[] args) {
Coin coin = Coin.DIME; // 열거형 값 사용
switch (coin) {
case PENNY:
System.out.println("1센트 동전입니다.");
break;
case NICKEL:
System.out.println("5센트 동전입니다.");
break;
case DIME:
System.out.println("10센트 동전입니다.");
break;
case QUARTER:
System.out.println("25센트 동전입니다.");
break;
default:
break;
}
}
}
✅ switch 문에서 enum을 사용할 수 있음
각 enum 값은 EnumClass.VALUE 형식으로 접근 가능 (Coin.DIME)
전통적인 방식과의 비교
public static final int PENNY = 1;
public static final int NICKEL = 5;
enum에는 자동으로 제공되는 정적 메서드가 있습니다.
values()valueOf(String name)public class EnumHiddenMethodExample {
public static void main(String[] args) {
// 모든 enum 값을 배열로 가져오기
Coin[] coins = Coin.values();
System.out.println("열거형 값 목록:");
for (Coin c : coins) {
System.out.println(c);
}
// 문자열을 이용해 특정 열거형 값 가져오기
Coin c1 = Coin.valueOf("QUARTER"); // "QUARTER"와 완벽히 일치해야 함
System.out.println("c1의 값: " + c1);
System.out.printf("c1의 값: %s\n", c1);
}
}
Coin.values()를 사용하면 열거형의 모든 값을 배열로 가져올 수 있음Coin.valueOf("QUARTER")를 사용하면 해당 enum 값을 반환Coin.valueOf("quarter")처럼 소문자로 입력하면 오류 발생enum은 일반적인 상수 집합을 넘어 메서드를 포함할 수 있는 객체 지향적인 구조입니다.
이를 통해 열거형 값을 특정 값으로 변환하거나 로직을 추가할 수 있습니다.
enum아래 코드에서 getCent() 메서드는 각 열거형 값에 대응하는 센트 값을 반환합니다.
public enum Coin {
PENNY, NICKEL, DIME, QUARTER;
// 각 열거형 값에 대응하는 센트 값을 반환하는 메서드
public int getCent() {
switch (this) {
case PENNY: return 1;
case NICKEL: return 5;
case DIME: return 10;
case QUARTER: return 25;
default: return 0;
}
}
}
this → 현재 열거형 값 (PENNY, NICKEL 등)switch(this) → 현재 객체(열거형 값)에 맞는 값을 반환enum 메서드 활용 예제열거형의 모든 값을 순회하며 getCent()를 호출하여 해당 값을 출력하는 코드입니다.
public class EnumMethodExample {
public static void main(String[] args) {
for (Coin coin : Coin.values()) {
System.out.println(coin + "의 값은 " + coin.getCent());
}
}
}
출력 결과
PENNY의 값은 1
NICKEL의 값은 5
DIME의 값은 10
QUARTER의 값은 25
coin.values() → 모든 열거형 값을 가져옴coin.getCent() → 각 열거형 값에 맞는 센트 값을 반환열거형에서 추상 메서드를 선언하고, 각 열거형 값에서 다르게 구현할 수 있습니다.
각 열거형 항목이 추상 메서드를 개별적으로 정의할 수 있기 때문에 더 유연한 코드 작성이 가능합니다.
enumpublic enum Coin2 {
PENNY {
int getCent() { return 1; }
},
NICKEL {
int getCent() { return 5; }
},
DIME {
int getCent() { return 10; }
},
QUARTER {
int getCent() { return 25; }
};
// 각 열거형이 반드시 구현해야 하는 추상 메서드
abstract int getCent();
}
abstract int getCent(); → 각 열거형에서 반드시 구현해야 하는 추상 메서드getCent()를 각기 다른 방식으로 구현 가능열거형의 모든 값을 순회하며 getCent()를 호출하여 해당 값을 출력하는 코드입니다.
public class EnumAbstractMethodExample {
public static void main(String[] args) {
for (Coin2 coin : Coin2.values()) {
System.out.println(coin + "의 값은 " + coin.getCent());
}
}
}
출력 결과
PENNY의 값은 1
NICKEL의 값은 5
DIME의 값은 10
QUARTER의 값은 25
coin.getCent()를 호출하여 각 열거형 값에 맞는 결과를 반환enum은 일반 클래스처럼 메서드를 포함할 수 있음switch를 활용해 열거형 값을 특정 값으로 변환할 수 있음enum에서 추상 메서드를 선언하고, 각 열거형 값에서 별도로 구현 가능확장이 가능하기 떄문데 센트 값을 필드로 넣고 생성자를 추가할 수 있습니다。
package enums;
2
3 public enum Coin3 {
4 PENNY(1),
5 NICKEL(5),
6 DIME(10),
7 QUARTER(25);
8
9 private final int cent;
10
11 Coin3(int cent) {
12 this.cent = cent;
13 }
14
15 public int getCent() {
16 return cent;
17 }
18 }
package enums;
2
3 public class EnumConstructorExample {
4 public static void main(String[] args) {
5 for(Coin3 coin : Coin3.values()) {
6 System.out.println(coin + "의 값은 " + coin.getCent());
7 }
8 }
9 }