Search

반응형

'Java'에 해당되는 글 52건

  1. 2020.05.12 [자바/java]컬렉션에서 Set 은 어떻게 사용할까요? Collection/Set
  2. 2020.05.10 [자바/java]제너릭과 와일드카드 - <? Extends E> (generic/wildcards) 1
반응형

안녕하세요.

신기한 연구소 개발자 티보이입니다.

컬렉션(Collection) 중 Set에 대해 살펴봅니다.

프로그램을 개발할 때 반드시 알아야 할 인터페이스 중 하나입니다.

제대로 알고 쓰면 더 좋겠지요?

컬렉션인지 모르고 그냥 다른 개발자 선배들이 소스에 사용한 것을 내 생각과 비슷하게 나오니깐 어떤 기능이 있고 성능은 어떤지 고민하지 않고 사용했던 기억이 있네요.

그러다 보면 가끔 난해한 오류가 나는데 이해를 못하고 찾지도 못하고 고생했던 경험들 있을 겁니다.

Vector, ArrayList, HashMap, Hashtable 등 소스에서 자주 만났던 클래스들인데..

잘 이해하고 사용한다면 기능, 성능면에서 많은 도움이 될 거예요.

간단하게 사용하면 되는 것을 굳이 무거운 컬렉션을 사용할 필요가 없잖아요.

쉰나게 만들었는데 막상 필요한 메서드를 해당 클래스가 지원하지 않는다면다른 클래스 찾아서 다시 코딩해야 하고요.

여하튼 카피 앤 페이스트(Copy & Paste)도 잘하면 좋지만 잘 알고 한다면 더 편하게 사용하고

소스 품질도 좋아질 것이며

당연히 우리의 스킬도 업 될 것입니다.

 

이제 같이 컬렉션 Set 인터페이스를 만나러 떠나 봅시다~

렛츠 고!!

 

 

SetCollection(컬렉션)의 특별한 종류이며 SortedSetSet의 특별한 종류입니다.

대표적으로 HashSet, LinkedSet, TreeSet 세가지가 있어요.

그 중 HashSet을 가장 많이 사용합니다.

Set중복된 요소를 저장하지 않는 컬렉션 중 하나입니다.

컬렉션(Collection)의 추상 메서드만 사용합니다.

즉, Set은 따로 메서드를 갖고 있지 않고 Collection것만 사용한다는 의미입니다.

순서(index)가 없어요. , get(int index) 메서드를 사용할 수 없습니다.

toString()으로 전체를 뽑던지, iterator를 사용해서 for문으로 쭉 뽑던지, 아니면 toArray() 배열로 따로 배열에 담아서 사용하면 됩니다.

 

HashSet해시 테이블에 요소들을 저장하며, 최고 성능으로 구현하는 것입니다.

TreeSet은 자료구조의 red-black로 그 요소를 저장하는데 속도는 HashSet보다 느립니다.

 

예제를 통해서 사용법을 익혀봅니다.

#HashSet과 toArray() 활용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
HashSet<Integer> hs = new HashSet<Integer>();
 
Random rm = new Random();
        
        
for(int i=0;i<10;i++) {
    hs.add(rm.nextInt(10));
}
        
        
Integer[] array = hs.toArray(new Integer[hs.size()]);
 
for(Integer itm : array) {
    System.out.println(itm);
}
cs

 Random을 사용해서 10 이하 임의의 수를 10개를 add()를 통해 HashSet hs에 담았습니다.

그리고 Integer [] array 로 배열을 생성하는데,

toArray() 를 사용해서 배열로 받습니다.

for-each문으로 출력문을 만들면 해당 HashSet을 배열로 받은 값들이 술술 나옵니다.

 

#HashSet과 addAll() 활용

1
2
3
4
5
HashSet<Integer> hs = new HashSet<Integer>();
HashSet<Integer> hs3 = new HashSet<Integer>();
 
 
hs3.addAll(hs);
cs

이 예문은 HashSet hs3에 HashSet hs 의 요소들을 추가하는 기능입니다.

중요한 것은 중복 허용이 안되기에 중복하지 않는 요소들만 합쳐집니다.

hs = [3,4]

hs3 = [0.1.2.3] 이면

addAll 후 hs3 = [0,1,2,3,4]가 됩니다. 3은 중복되니 하나만 들어갑니다.

 

#HashSet과 containsAll() 활용

1
2
3
4
5
6
7
8
9
10
11
12
HashSet<Integer> hs = new HashSet<Integer>();
HashSet<Integer> hs3 = new HashSet<Integer>();
 
hs.add(2);
hs.add(3);
 
hs3.add(0);
hs3.add(1);
hs3.add(2);
hs3.add(3);
 
System.out.println(hs3.containsAll(hs));
cs

hs3에 hs 전체가 포함되어 있으면 true 아니면 false를 반환합니다.

일부만 포함되면 false입니다.

#HashSet과 retainAll() 활용

1
2
3
4
5
6
7
8
9
10
11
12
HashSet<Integer> hs = new HashSet<Integer>();
HashSet<Integer> hs3 = new HashSet<Integer>();
 
hs.add(2);
hs.add(3);
 
hs3.add(0);
hs3.add(1);
hs3.add(2);
hs3.add(3);
 
System.out.println(hs3.retainAll(hs));
cs

이 소스를 실행하면 hs가 가지고 있는 [2,3] 이 hs3에도 전부 있습니다.

retainAll을 실행하면 hs3는 hs를 전부 포함하고 있다면 그 부분만 남기게 됩니다.

hs3dl [0.1.2.3]에서 [2,3]으로 바뀌게 됩니다.

 

#HashSet과 removeAll() 활용

1
2
3
4
5
6
7
8
9
10
11
12
HashSet<Integer> hs = new HashSet<Integer>();
HashSet<Integer> hs3 = new HashSet<Integer>();
 
hs.add(2);
hs.add(3);
 
hs3.add(0);
hs3.add(1);
hs3.add(2);
hs3.add(3);
 
System.out.println(hs3.removeAll(hs));
cs

removeAll을 실행하면 hs3의 목록에서 hs 목록이 빠지게 됩니다.

위 결과는 hs3 = [0,1]이 됩니다.

컬렉션(Collection) 중 Set에서 자주 사용하는 HashSet에 대해 살펴봤습니다.

즐 코딩하세요~

반응형
반응형

[자바/java]제너릭과 와일드카드 - <? Extends E> (generic/wildcards)

안녕하세요. 신기한 연구소 개발자 티보이입니다.

자바 개발을 하다 보면 배열, Collection 등을 사용하게 됩니다.

다양한 타입을 지원하기 위해 제너릭(generic)을 사용하는데요.

그중 와일드카드(wildcards)를 사용하는데 처음 사용하거나 또는 확실히 이해가 필요한 개발자를 위해 한 번 포스팅해봅니다.

확실히 이해하고 사용한다면 많은 도움이 될 거예요.

렛츠 고~

제너릭을 사용하는 이유는

타입을 미리 지정해서 캐스팅을 사용하지 않아 좀 더 명확하게 사용할 수 있도록 해줍니다.

제너릭(generic)을 사용한 코드를 확인해보겠습니다.

1
2
3
4
5
6
7
8
9
void printCollection(Collection<Object> c) {
 
    for (Object e : c) {
 
        System.out.println(e);
 
    }
 
}
cs

코드는 <Object>라는 타입을 지정하고 있습니다.

이렇게 <Object>로 타입을 지정하는 것을 제너릭이라고 합니다.

그런데 여기서 문제가 있습니다.

혹시 해당 코드를 모든 Collection 타입을 받기 위해 만든 거라면 오류가 발생합니다.

제너릭(generic)은 지정한 타입만 받기 때문입니다.

Object 최상위 클래스이기에 받을 있다고 잘못 이해한 코드입니다.

Collection<Object>선언하면 모든 Collection 타입 모두를 허용할 수 있다는 것이 아니라 겁니다.

와일드카드 “?” 사용해서 아직 알려지지 않은 혹은 미정의 Collection 타입이라는 의미에서 Collection<?>를 사용하면 해결됩니다.

 

1
2
3
4
5
6
7
8
9
void printCollection(Collection<?> c) {
 
    for (Object e : c) {
 
        System.out.println(e);
 
    }
 
}
cs

이렇게 사용하면 Collection 다양한 타입을 사용할 있게 됩니다.

하지만 코드도 다른 문제가 있습니다.

말했듯이 Collection<?>로 와일드카드를 사용하면 Collection 타입은 안전하게 사용할 있지만 임의의 객체를 받을 수는 없습니다.

아래의 예제를 보세요.

1
2
3
4
5
Collection<?> c = new ArrayList<String>();
 
c.add(new Object()); //임의의 객체
 
 
cs

첫 번째줄은 문제가 없습니다.

아마 객체 c를 Collection<?>로 해서 다양한 타입을 지원하고 싶은 마음에 지정한 보이는데 막상 인스턴스화 하는 부분은 ArrayList<String>으로 지정했습니다.

그래서 ArrayList 아니거나 또는 ArrayList라도 String 타입이 아니면 오류 납니다.

두 번째라인을 보면 c 타입을 Collection<?>로 했기에 new Object() 객체를 add 하면 받을 있어 보이지만 사실은 오류가 발생합니다.

오류는 String 타입으로 캐스팅하라고 나올 겁니다.

 

확실히 타입을 정해서 사용한다면 와일드카드 “?” 사용해도 무방하겠지요?

 

<? extends E>

혹시 이것을 ? 어떻게 사용하는지 궁금하시나요?

제너릭(generic)은 개발의 다양성을 위한 기능이지 않을까 생각해봅니다.

 

와일드카드 “?” 설명 했으니 아시겠죠? 지정되지 않은 객체를 받을 있다는 의미입니다.

그럼 extends E 있을까요?

E elements 약자로 보시면 됩니다. E 그대로 사용하는게 아닙니다.

Extends는 상속 의미 그대로입니다. 지정되지 않은 객체 "?" 가 E를 상속받았다는 의미예요.

 

예를 들어볼께요.

게임 개발을 하는데 유닛 추상클래스(abstract clsss Units) 있습니다.

그리고 인간(class Human extends Units),

요정(class Fairy),

오크(class Oak) 구성된 유닛들이 있습니다.

세개의 클래스는 유닛 추상클래스를 상속받습니다.

유닛들은 게임판에 객체를 생성해서 이미지로 표현해야 합니다.

게임판이라는 클래스가 있고 안에는 객체를 이미지로 만드는 메서드가 있습니다.

유닛들 인간, 요정, 오크를 모두 그려야 하는 경우 각각 메서드를 구성하고 호출하게 되면 소스도 중복되고 비효율적인 소스가 됩니다.

이런 경우 객체들을 List 담은 List 객체로 넘겨주면 되는데

문제는 List 내에 인간, 요정, 오크 다양한 타입이 존재하게 됩니다.

위에서 사용한 제너릭(generic)과 와일드카드(wildcards)로 메서드를 만들어 봤습니다.

 

1
2
3
4
5
6
7
8
9
Public void showAllUnit(List<Units> units){
 
       For (Units u: units) {
 
               u.makeImg(this);
 
          }
 
}
cs

 

이렇게 되면 위에서 말했듯 List내에서 <Units> 타입만 찾게 됩니다.

, Human, Fairy, Oak 찾을 없습니다.

이런 경우 사용할 있는 제너릭(generic)이 <? Extends E> 입니다.

 

1
2
3
4
5
Public void showAllUnit(List<extends Units> units){
 
 
 
}
cs

 

이렇게 되면 List에서 와일드카드(wildcards) ? 의 타입을 찾아야 하는데 바로 Units 클래스를 상속받은 Human, Fairy, Oak를 받을 수 있게 됩니다.

이해가 되셨나요?

이제 제너릭(generic)과 와일드카드(wildcards) 그리고 <? Extends E>사용법을 알게 되었으니 개발에 활용하시길 바랍니다.

즐 코딩하세요~

반응형