- 제네릭
- Hash map/hash set
- auto boxing/unboxing
1. 제네릭
제네릭의 장점 :
- 제네릭을 사용하면 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지
- 클래스 외부에서 타입을 지정해주기 때문에 따로 타입을 체크하고 변환해줄 필요 없음 => 관리 용이
- 비슷한 기능 지원 => 코드의 재사용성이 높아짐
| 타입 | 설명 |
| <T> | Type |
| <E> | Element |
| <K> | Key |
| <V> | Value |
| <N> | Number |
[와일드 카드]
<?> :와일드 카드 = '알 수 없는 타입'
정해지지 않은 unknown 타입으로, 모든 타입을 대신할 수 있다.
<?> // 모든 타입 가능. <? extends Object>랑 같은 의미
<K extends T> // T와 T의 자손 타입만 가능 (K는 들어오는 타입으로 지정 됨)
<K super T> // T와 T의 부모(조상) 타입만 가능 (K는 들어오는 타입으로 지정 됨)
<? extends T> // T와 T의 자손 타입만 가능
<? super T> // T와 T의 부모(조상) 타입만 가능
- ? extends T : 상한 경계
- ? super T : 하한 경계
*주의 : 경계가 지정되고 K는 특정 타입으로 지정이 되지만, ?는 타입이 지정되지 않는다는 의미다.
1)상한 경계 : <? extends T>
extends를 사용해서 와일드카드 타입의 최상위 타입을 정의함으로써 상한 경계를 설정함.
void printCollection(Collection<? extends MyParent> c) {
// 컴파일 에러
for (MyChild e : c) {
System.out.println(e);
}
for (MyParent e : c) {
System.out.println(e);
}
for (MyGrandParent e : c) {
System.out.println(e);
}
for (Object e : c) {
System.out.println(e);
}
}
//<? extends MyParent>으로 가능한 타입은 MyParent와 미지(unknown)의 모든 MyParent 자식 클래스들이다.
//미지의 MyParent 자식 클래스라는 것은 자식이 어떤 타입인지 알 수 없다는 것
2) 하한 경계 : <? super T>
super를 사용해 와일드카드의 최하위 타입을 정의하여 하한 경계를 설정
void printCollection(Collection<? super MyParent> c) {
// 불가능(컴파일 에러)
for (MyChild e : c) {
System.out.println(e);
}
// 불가능(컴파일 에러)
for (MyParent e : c) {
System.out.println(e);
}
// 불가능(컴파일 에러)
for (MyGrandParent e : c) {
System.out.println(e);
}
for (Object e : c) {
System.out.println(e);
}
}
//하위 타입인 경우에도 문제가 되는데, <? super MyParent>으로 가능한 타입은 MyParent와
//미지의 MyParent 부모 타입들이므로 MyChild와 같이 경계 아래의 하위 타입들은 당연히 추가될 수 없기 때문이다.
<참고>
https://mangkyu.tistory.com/241
https://st-lab.tistory.com/153
2. Hash map
map : key + value 두 쌍으로 데이터를 보관하는 자료 구조
키는 맵에 유일하게 있음. (value 중복 상관 x)
<HashTable과 HashMap차이점 >
| HashTable | HashMap |
| Thread 관점에서 안전한가? | 안전하지 않은 대신 속도가 빠른가? |
[사용법]
- put : 저장
- get : 읽기
- containsKey : 이미 HashMap에 키가 있으면 값을 덮어 쓰지 않음
//키가 들어있는지 확인 -> 있으면 덮어쓰지 않음.
if(map.containsKey('key'){
map.put('key',100);
map.putIfAbsent('key',100);
}
- containsValue : 값이 존재하는지 알아보는 메소드(true/false)
- putAll : Map에 다른 Map을 전부 포함
public static void main(String[] org){
Map<String,Integer> m1 = new HashMap();
java.util.Map<String,Integer> m2 = new HashMap();
m1.put("A", 100);
m1.put("B", 200);
m2.put("C", 300);
m2.put("D", 400);
//m2에 m1 전부 포함하기.
m2.putAll(m1);
System.out.println(m2);
}
//결과값
//putAll 대신 생성자 이용하여 데이터 넘기기.
Map<String,Integer> m2 = new HashMap(m1);
- keySet : 키롤 set으로 넘겨주어 존재하는 키를 모두 순회함.
- ForEach : 메소드 순회
- equals : 같은 객체인지 판별
- hashCode() : 각 개체가 갖는 유일한 값(Code)를 의미
Hash Set
[특징]
- 중복된 값 허용X (자동으로 제거)
- 순서 보장 X
- null값 허용
- 생성
- 요소 값 추가
- 입력되는 값이 내부에 존재하지 않는다면 값을 HashSet에 추가하고 true를 반환
- 입력되는 값에 내부에 존재한다면 false 반환
- size : HashSet 크기 구하기
- 요소 값 삭제
- remove(value) : value 값 제거
- clear() : 모든 값 제거
- HashSet 요소 값 검색
- contains(valuse)
- Hash 내부에 존재하는지 확인
- contains(valuse)
- 요소 값 출력
- print : [Set의 전체값]이 출력
- 반복자(iterator) : 전체 객체를 한번씩 반복해서 가져옴
HashSet<Integer> set = new HashSet<Integer>(Arrays.asList(1,3,5));
Iterator iter = set.iterator();
//hasNext() : 가져올 객체가 있다면 true 리턴, 없다면 false 리턴
// next() : Iterator에서 하나의 객체를 가져올 수 있는 메소드
while(iter.hasNext()) {
System.out.println(iter.next());
}
3.auto boxing / auto-unboxing
autoBoxing
- primitive data에서 Wrapper Class로 자동으로 변환되는 것
- 가벼운 데이터를 무거운 데이터에 넣기
- 컴파일러가 Pirmitive에서 Object Data로 자동변환 함
- Wrapper 클래스에 기본 자료형의 데이터 대입

auto unboxing
- Wrapper 클래스 -> primitivie type으로 자동 형변환 되는것
- 컴파일러가 Object Data를 Primitive type으로 자동변환
- 무거운 데이터를 가벼운 데이터에 넣기
- 기본자료형에 wrapper 객체 대입

'Backend' 카테고리의 다른 글
| MSA에 대해 알고가기 (0) | 2025.02.13 |
|---|---|
| AJAX(Asynchronous JavaScript and XML) (0) | 2024.11.29 |
| [RBF] 2주차 (2) | 2024.11.07 |