HashSet 에 있 는 대상 에 대한 재 작성 hashcode () 와 equals ()

7734 단어 jdk데이터 구조
제 가 설명 하고 자 하 는 문 제 는 왜 HashSet 에 저 장 된 대상 입 니까? equals () 방법 을 다시 썼 다 면 hashcode () 방법 을 다시 써 야 합 니 다. 즉, equals () 방법 이 같은 대상 을 확보 하 는 이 유 는 hashcode () 방법 반환 값 도 같 아야 합 니 다.
   우선, 제 가 예 를 들 어 보 겠 습 니 다. Person 류 를 쓰 고 equals () 방법 만 덮어 썼 습 니 다.
  

class Person{
	private String name;
	private int age;

	public Person(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}

	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;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return this.name + " :" + this.age;
	}
}


   

   다음은 테스트 클래스 의 코드 를 드 립 니 다.
   

     public class HashSetResearch {
	public static void main(String[] args) {
         Set<Person> s = new HashSet<Person>();
		Person p1 = new Person(22,"zhongyao");
		Person p2 = new Person(22,"zhongyao");
		
		s.add(p1);
		s.add(p2);
		
		for(Person temp : s){
			System.out.println(temp);
		}
	}
}
       :
zhongyao :22
zhongyao :22
    

    HashSet 에서 중 복 된 대상 을 설치 할 수 없습니다. 이것 은 모두 가 알 고 있 는 것 입 니 다. 구체 적 인 설명 은 jdk 의 HashSet 류 와 관련 된 javadoc 설명 을 볼 수 있 습 니 다.
    

     /**
     * Adds the specified element to this set if it is not already present.
     * More formally, adds the specified element <tt>e</tt> to this set if
     * this set contains no element <tt>e2</tt> such that
     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
     * If this set already contains the element, the call leaves the set
     * unchanged and returns <tt>false</tt>.
     *
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     * element
     */
    public boolean add(E e) {
	return map.put(e, PRESENT)==null;
    }
    

    e==null ? e2 = = null: e. equals (e2) 는 HashSet 에서 e 와 같은 element 를 가 질 수 없 음 을 설명 합 니 다. 같은 조건 은 null 또는 equals () 방법 으로 true 를 되 돌려 주 는 것 입 니 다.이 럴 때 당신 은 왜 위의 p2 가 s 에 들 어 갔 느 냐 고 물 을 수 있 습 니 다.
HashSet 을 호출 할 때 많은 일이 발생 했 습 니 다. 대상 의 hashcode () 방법 이 있 습 니 다. 전체 프로 세 스 의 호출 과정 을 상세 하 게 보 여 드 리 겠 습 니 다.

public boolean add(E e) {
	return map.put(e, PRESENT)==null;
}
  HashSet     add  。
map HashSet          :
private transient HashMap<E,Object> map;
PRESENT        ,      :
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
          ”   ”,      ,    map     value。

      HashMap put(K k, V v)  ,          。        ,         。    ,                    
    public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);//        ,     
        //      key   hashcode,        key        
        //     ,   HashMap         ,           
        //          
        int hash = hash(key.hashCode());
        //  i    ,                        table  
        //   ,  table   Entry    ,      ,           
        //   。 indexFor()          ,      i=hash&(talbe.length-1)
        //  hash     。
        int i = indexFor(hash, table.length);
        //  for                      ,   table i      
        //  ,        ,                          ,
        //    hash              hashcode        (    )
        //     for                
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            //         ,             
            //       hashcode,      ,        
            //((k = e.key) == key                    e      
            // ,       。    key.equals(k)     。
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);// do nothing
                //                
                return oldValue;
            }
        }

        modCount++;
        //     for         ,                  ,  
        //         
        addEntry(hash, key, value, i);
        return null;
}
 

HashSet. Entry 의 소스 코드 를 첨부 합 니 다:

 static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;
        final int hash;
        /**
         * Creates new entry.
         */
        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        }
        public final K getKey() {
            return key;
        }
        public final V getValue() {
            return value;
        }
        public final V setValue(V newValue) {
	    V oldValue = value;
            value = newValue;
            return oldValue;
        }
        public final boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry e = (Map.Entry)o;
            Object k1 = getKey();
            Object k2 = e.getKey();
            if (k1 == k2 || (k1 != null && k1.equals(k2))) {
                Object v1 = getValue();
                Object v2 = e.getValue();
                if (v1 == v2 || (v1 != null && v1.equals(v2)))
                    return true;
            }
            return false;
        }
        public final int hashCode() {
            return (key==null   ? 0 : key.hashCode()) ^
                   (value==null ? 0 : value.hashCode());
        }

        public final String toString() {
            return getKey() + "=" + getValue();
        }
        /**
         * This method is invoked whenever the value in an entry is
         * overwritten by an invocation of put(k,v) for a key k that's already
         * in the HashMap.
         */
        void recordAccess(HashMap<K,V> m) {
        }
        /**
         * This method is invoked whenever the entry is
         * removed from the table.
         */
        void recordRemoval(HashMap<K,V> m) {
        }
    }

 

  이것 은 모든 set 에서 거의 차이 가 나 지 않 으 니 여러분 스스로 보 셔 도 됩 니 다.한 가지 더 말씀 드 리 겠 습 니 다. TreeSet 에 서 는 copare To () 에 게 똑 같이 되 돌아 오 라 고 추가 로 요구 합 니 다. 즉, equals () 가 true 로 돌아 갈 때 copare To () 는 0 으로 돌아 가 야 합 니 다.
질문:
    hashset 에 가입 한 후에 수정 대상 의 상 태 는 다른 것 과 마찬가지 로 가능 합 니 다. 자동 으로 끊 어 지지 않 습 니 다. 이것 이 바로 제 가 알 고 싶 은 것 입 니 다. 이것 은 set 의 유일 성 을 파괴 합 니 다.

좋은 웹페이지 즐겨찾기