quilt code
[고급자바] 컬렉션 프레임워크 (3) 본문
1. EqualsHashCodeTest
해시함수(hash function)는 임의의 길이의 데이터를 고정된 길이의 데이터로 매핑하는 함수이다. 해시함수에 의해 얻어지는 해시값은 해시코드, 해시 체크섬 또는 간단하게 해시라고 부른다. |
HashSet, HashTable, HashMap과 같은 객체들을 사용할 경우 객체가 서로 같은지를 비교하기 위해 equals()메소드와 hashCode()메소드를 이용한다. 그래서 객체가 서로 동일한지 결정하려면 두 메소드를 재정의해야 한다. HashSet, HashTable, HashMap에서는 객체 동일 여부를 데이터 추가 시에 검사한다. |
equals() 메소드는 두 객체의 내용(값)이 같은지 비교하는 메소드이고, hashCode() 메소드는 객체에 대한 해시코드값을 반환하는 메소드이다. => 해시테이블 작성시 사용됨. |
equals()와 hashCode() 메소드에 관련된 규칙 1. 두 객체가 같으면 반드시 같은 hashCode를 가져야 한다. 2. 두 객체가 같으면 equals()메소드를 호출했을 때 true값을 반환해야한다. 즉, 객체 a, b가 같다면 a.equals(b)와 b.equals(a) 둘다 true값을 반환해야 한다. 3. 두 객체의 hashCode가 같다고 해서 두 객체가 반드시 같은 객체는 아니다. 하지만, 두 객체가 같으면 반드시 hashCode가 같아야 한다. 4. equals() 메소드를 override하려면 반드시 hashCode() 메소드도 override 해야 한다. 5. hashCode()는 기본적으로 힙메모리에 존재하는 각 객체에 대한 메모리 주소값을 기반으로한 정수값을 반환한다. 그러므로, hashCode()를 재정의하지 않고서는 절대로 두 객체가 같은 해시코드가 반환될 수 없다. |
hashCode()에서 사용하는 '해싱 알고리즘'에서 서로다른 객체에 대하여 같은 hashCode를 만들어낼 수 있다. 그래서 객체가 같지 않더라도 hashCode가 같을 수 있다. |
|
public static void main(String[] args) { Person p1 = new Person(1,"정재현"); Person p2 = new Person(1,"정재현"); Person p3 = new Person(1,"홍길동"); System.out.println("p1.equals(p2) : " + p1.equals(p2)); System.out.println("p1 == p2 : " + (p1 == p2)); Set<Person> hs = new HashSet<>(); //다이아몬드 문법 java8부터 사용가능 <Person>생략 System.out.println("add(p1) 성공여부 : " + hs.add(p1)); System.out.println("add(p2) 성공여부 : " + hs.add(p2)); System.out.println("p1, p2 등록 후 데이터"); for(Person p : hs) { System.out.println(p.getId() + " : " + p.getName()); } System.out.println("add(p3) 성공여부 : " + hs.add(p3)); System.out.println("p3 등록 후 데이터"); for(Person p : hs) { System.out.println(p.getId() + " : " + p.getName()); } System.out.println("remove(p2) 성공여부 : " + hs.remove(p2)); System.out.println("remove(p2) 후 데이터"); for(Person p : hs) { System.out.println(p.getId() + " : " + p.getName()); } } |
|
p1.equals(p2) : true p1 == p2 : false add(p1) 성공여부 : true add(p2) 성공여부 : false p1, p2 등록 후 데이터 1 : 정재현 add(p3) 성공여부 : true p3 등록 후 데이터 1 : 홍길동 1 : 정재현 remove(p2) 성공여부 : true remove(p2) 후 데이터 1 : 홍길동 |
class Person {
private int id; private String name; public Person(int id, String name) { super(); this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override
public String toString() { return "Person [id=" + id + ", name=" + name + "]"; } @Override public int hashCode() { return Objects.hash(id, name); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; return id == other.id && Objects.equals(name, other.name); } |
2. HashMap
Map 1. key값과 value값을 한쌍으로 관리하는 객체 2. key값은 중복을 허용하지 않고 순서가 없다. (Set의 특징) 3. value값은 중복을 허용한다. |
|
public static void main(String[] args) {
Map<String, String> map = new HashMap<>(); |
자료 추가 : put(key값, value값); |
|
map.put("name", "정재현"); map.put("addr", "대전"); map.put("tel", "010-1234-5678"); System.out.println("map => " + map);
|
|
map => {name=정재현, tel=010-1234-5678, addr=대전} |
자료 수정 : 데이터를 저장할 때 key값이 같으면 나중에 입력한 값이 저장된다. put(수정할 key값, 새로운 value값); |
map.put("addr", "서울");
System.out.println("map => " + map); |
map => {name=정재현, tel=010-1234-5678, addr=서울}
|
자료 삭제: remove(삭제할 값); |
map.remove("name");
System.out.println("map => " + map); |
map => {tel=010-1234-5678, addr=서울}
|
자료 읽기 : get(key값); |
System.out.println("addr = " + map.get("addr"));
|
addr = 서울
|
**key값들을 읽어와 자료를 출력하는 방법**
| 방법1. keySet() 메소드 이용하기 Map의 key값들을 Set타입의 객체를 반환한다. |
|
Set<String> keySet = map.keySet(); System.out.println("Iterator를 이용한 방법"); Iterator<String> it = keySet.iterator(); while(it.hasNext()) { String key = it.next(); System.out.println(key + " : " + map.get(key)); } |
Iterator를 이용한 방법
tel : 010-1234-5678 addr : 서울 |
| 방법2. Set형의 데이터를 '향상된 for문'으로 처리하면 Iterator를 사용하지 않아도 된다. |
System.out.println("향상된 for문을 이용한 방법");
for(String key : keySet) { System.out.println(key + " : " + map.get(key)); } |
향상된 for문을 이용한 방법
tel : 010-1234-5678 addr : 서울 |
| 방법3. value값만 읽어와 출력하기 |
System.out.println("values()메소드 이용한 방법");
for(String value : map.values()) { System.out.println(value); } |
values()메소드 이용한 방법
010-1234-5678 서울 |
| 방법4. Map관련 클래스는 Map.Entry타입의 내부 class가 만들어져 있다. 이 내부 클래스는 key와 value라는 멤버변수로 구성되어 있다. Map에서 이 Map.Entry 타입의 객체들을 Set 타입의 데이터로 저장하여 관리한다 Map.Entry타입의 객체 모두 가져오기 => entrySet() 메소드 이용함. |
Set<Map.Entry<String,String>> entrySet = map.entrySet();
|
| 가져온 Entry 객체들을 순서대로 처리하기 위해 Iterator 객체 사용하기 |
Iterator<Map.Entry<String, String>> entryIt = entrySet.iterator();
while(entryIt.hasNext()) { Map.Entry<String, String> entry = entryIt.next(); System.out.println("key값 : " + entry.getKey()); System.out.println("value값 : " + entry.getValue()); System.out.println(); } |
key값 : tel
value값 : 010-1234-5678 key값 : addr value값 : 서울 |
'daily > 고급자바' 카테고리의 다른 글
| [고급자바] 컬렉션 프레임워크(4) (0) | 2023.02.02 |
|---|---|
| [고급자바] Student 과제 (0) | 2023.02.02 |
| [고급자바] Lotto 과제 (0) | 2023.02.02 |
| [고급자바] 컬렉션 프레임워크 (2) (0) | 2023.01.31 |
| [고급자바] 컬렉션 프레임워크 (1) (0) | 2023.01.30 |