순서가 없는 배열. 방번호(index)가 없음. 중복값을 가질 수 없음. HashSet, TreeSet.
HashSet<String> set=new HashSet<String>();
// 요소 추가하기
System.out.println(set.add("사과"));
set.add("딸기");
set.add("바나나");
System.out.println(set.add("사과")); // 사과는 이미 들어가있기 때문에 false 반환.
set.add("바나나");
// 요소 개수
System.out.println(set.size());
// toString()
System.out.println(set);
// 개별 요소 탐색 -> 불가능! (******) 방번호가 없기 때문에!
// System.out.println(set.get(0));
// 그래서 요소 탐색을 사용하려면 iterator를 사용할 것!
Iterator<String> iter=set.iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}
// 로또 번호 6개(1~45)
Random rnd=new Random();
ArrayList<Integer> lotto=new ArrayList<Integer>();
for (int i=0; i<6;i++) {
int n=rnd.nextInt(45)+1;
// 검증
boolean flag=false;
for(int j=0;j<i;j++) {
if (n==lotto.get(j)) {
flag=true;
break;
}else {
flag=false;
}
}
if (flag) {
i--;
}else {
lotto.add(n);
}
}
Collections.sort(lotto);
System.out.println(lotto);
// Set 구현
HashSet<Integer> lotto2=new HashSet<Integer>();
while(lotto2.size()<6) {
lotto2.add(rnd.nextInt(45)+1);
}
System.out.println(lotto2);
//행사 -> 경품
//1. 중복 당첨 가능 > List
//2. 중복 당첨 불가능 > Set
ArrayList<String> box = new ArrayList<String>(); //응모권 상자
box.add("홍길동");
box.add("아무개");
box.add("유재석");
box.add("강호동");
box.add("박명수");
box.add("정준하");
box.add("하하");
box.add("김영철");
//추첨 명단(3명)
ArrayList<String> result1 = new ArrayList<String>();
HashSet<String> result2 = new HashSet<String>();
while (result1.size() < 3) {
result1.add(box.get(rnd.nextInt(box.size())));
}
while (result2.size() < 3) {
result2.add(box.get(rnd.nextInt(box.size())));
}
System.out.println();
System.out.println(result1);
System.out.println(result2);
// 단일값 집합(값형, 문자열)
HashSet<Integer> set1=new HashSet<Integer>();
set1.add(100);
set1.add(200);
set1.add(300);
set1.add(100);
System.out.println(set1);
// 복합값 집합(객체)
// Set이 객체를 저장하는 용도로 사용될 때는
// 동일 객체 비교를 hashCode()를 사용해서 비교
// 객체가 들어가는 Set에서 객체의 상태가 동일하면 같은 객체로 취급하고 싶다.
// -> 해당 객체의 클래스에서 hashCode()를 재정의한다.
HashSet<Person> set2=new HashSet<Person>();
set2.add(new Person("홍길동", 20));
set2.add(new Person("아무개", 22));
set2.add(new Person("하하하", 25));
set2.add(new Person("홍길동", 20));
// HashSet은 단일값일 경우 중복을 제외하지만,
// 객체인 경우 주소값 비교를 하기 때문에 중복값을 넣을 수 있다. 동명이인으로 처리.
// 실제 출력결과 : [{name=아무개, age=22}, {name=홍길동, age=20}, {name=홍길동, age=20}, {name=하하하, age=25}]
System.out.println(set2);
// 같은 객체를 찾아내기! -> 해시코드로!
Person p1=new Person("홍길동", 20);
Person p2=new Person("아무개", 22);
// com.test.collection2.Person@3039 -> 3039는 해시코드(12345, 10진수)의 return값(16진수)
// 자료형@해시코드(메모리주소값)
// p1 주소값 : com.test.collection2.Person@5c647e05 // 실제 존재하는 곳
// p2 주소값 : com.test.collection2.Person@33909752
// 실제 존재하는 곳은 5c647e05와 33909752.
// 주소값을 적절히 조절하면 다른 값을 같다고 할 수도 있고,
// 같은 값을 다르다고 할 수도 있다.
// 객체 비교할 때 HashCode 이용.
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p1==p2);
System.out.println(p1.equals(p2));
// 사실 문자열은 재사용! 메모리 낭비를 막기 위해.
// "홍길동"이라는 공간이 s1, s2에 재사용되는 것
// 문자열은 불변이다. (Immutable) -> 고칠 수 없다
// "홍길동"+"님" -> "홍길동님"으로 보이지만
// 사실 메모리를 늘리거나 줄일 수 없다.
// Stack : 질서정연 <-> Heap : 자유분방
// 이렇게 생각할 것.
// 크기가 가변이면 Heap영역에 생긴다.
String s1="홍길동";
String s2="홍길동";
String s3="홍";
s3=s3+"길동";
System.out.println(s1==s2);
System.out.println(s1.equals(s2));
System.out.println(s1==s3);
System.out.println(s1.equals(s3));
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
// 둘다 54150062
Person p3=new Person("호호호", 28);
Person p4=new Person("호호호", 28);
// 해시코드를 재정의하고, equals도 오버라이딩하면
// 아래의 결과는 true가 나온다.
System.out.println(p3.equals(p4));
class Person{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "{name=" + name + ", age=" + age + "}";
}
@Override
public int hashCode() {
// "홍길동20" -> 12345
// "아무개22" -> 23423
// "홍길동20" -> 12345
return (this.name+this.age).hashCode();
}
@Override
public boolean equals(Object obj) {
// 참조 주소값의 비교 -> 상태값 비교
Person p=(Person)obj;
return this.name.equals(p.name) && this.age==p.age;
}
}
Tree구조를 가지는 Set. 중복값X, 순서X, 정렬X. 이진트리구조를 기반으로 자동 정렬이 되는 Set. 정렬된 상태에서의 Set이 필요할 때 사용. 검색에 장점!
TreeSet<Integer> set=new TreeSet<Integer>();
set.add(5);
set.add(3);
set.add(1);
set.add(2);
set.add(7);
set.add(9);
set.add(6);
set.add(4);
set.add(8);
System.out.println(set.size());
System.out.println(set);
Iterator iter=set.iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}
// TreeSet 목적
// 1. 정렬(중복값 없는)
// 2. 부분 검색 능함(*****)
System.out.println(set.first());
System.out.println(set.last());
System.out.println(set.headSet(5)); // 5는 방번호 아님!!! "5"를 만날 때까지 가져오는 것.
System.out.println(set.tailSet(5));
System.out.println(set.subSet(3, 7)); // "3" 등장에서부터 "7" 등장까지.("7"은 미포함)
// 중복값 없는 집합 -> Set -> HashSet vs TreeSet?
// 1. 뭐가 뭔지 잘 모름 -> HashSet
// 2. 범위 검색 필요 -> TreeSet
// 3. 나머지 -> HashSet
// 중복값 있는 집합 -> List vs Map?
// 1. 뭐가 뭔지 잘 모름 -> ArrayList
// 2. 첨자(index) O -> List
// 2-1. 조작이 심하다 -> LinkedList
// 2-2. 조작이 덜하다 -> ArrayList
// 2-3. 선입선출 -> Queue(LinkedList)
// 2-4. 후입선출 -> Stack
// 3. 키 사용 -> HashMap
// 3-1. 범위 검색 -> TreeMap
// 3-2. 나머지 -> HashMap
// List -> ArrayList
// Map -> HashMap
// Set -> HashSet