JDKソース学習シリーズ一---java.util(1)


はい、私は怠け者だと認めています.しかし、いくつかの学習成果と仕事の経験を記録しないことに気づきました.私はゆっくりとそれらを忘れて、最後に何もありません.お正月に帰ってきて、2011は今日からまた積み重ねましょう.
    市場に出回っている技術書は豊富だが、兄は「コードに真実がある」と信じている.だから、ソースコードこそ最高の学習材料であり、Javaの巨大なオープンソースコミュニティが提供している様々な設計モデルと革新的な考え方に満ちたフレームワークコードは言うまでもなく、JDKソースコード自体は博大で奥深い技術聖書である.jdkソースコードに署名されている@authorを見てみましょう.技術の牛ではなく、彼らのコードを学ぶことができるのは感動的なことかもしれません.これもオープンソースが私たちに与えた楽しみです.よし、freeもオープンもあるのに、どうして見に行かないの.
    まずjava.utilのHashMapとHashTableを見てみましょう.この兄弟はいろいろなjavaの面接問題でよく取り上げられています.以前は面接問題の答えの異同点の羅列しか見たことがありませんが、内部の実現といくつかの特徴は深く研究されていません.個人的には、ソースコードを読むのは小説を読むように目的もなく最初から見ることができないと思います.まず、自分にいくつかの問題を用意して、推測をしてから、実現を見ることができます.これはもっと的確です.はい、兄は今回の勉強にいくつかの自分の問題を用意しました.
    まずはHashMapから始めましょう.
    Personクラスを新規作成:

package com.emsn.crazyjdk.java.util;

/**
 * “ ” ,   equals hashcode  ..., id       ,   ...
 * 
 * @author emsn1026
 *
 */

public class Person {
	
	/**
	 *   id
	 */
	private String id;
	
	/**
	 *   
	 */
	private String name;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@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;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + "]";
	}
	
}


    現在、同じidの人は同じインスタンスとされています…もちろん、異なるidの名前が同じでも異なる人は、このPerson類のインスタンスをHashMapのkeyとすると、keyの一意性はpeopleインスタンスのidを通過します
コントロールします.

package com.emsn.crazyjdk.java.util;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.emsn.crazyjdk.java.util.Person;

/**
 * @author emsn1026
 *
 */
public class MapTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
			Map m = new HashMap();
			Person p1 = new Person();
			Person p2 = new Person();
			
			p1.setId("1");
			p1.setName("name1");
			p2.setId("1");
			p2.setName("name2");
					
			m.put(p1, "person1");
			m.put(p2, "person2");
			
			System.out.println("Map m's size :" + m.size());
			
			for(Object o :m.entrySet()){
				Entry e = (Entry)o;
				System.out.println("key:"+ e.getKey());
				System.out.println("value:"+ e.getValue());
			}
			
		}

}


印刷結果は
Map m's size :1
key:Person [id=1, name=name1]
value:person2
keyはすでに存在し,valueは上書きされ,この結果は予測できることが分かった.次にコードを変更します.

package com.emsn.crazyjdk.java.util;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.emsn.crazyjdk.java.util.Person;

/**
 * @author emsn1026
 *
 */
public class MapTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
			Map m = new HashMap();
			Person p1 = new Person();
			Person p2 = new Person();
			
			p1.setId("1");
			p1.setName("name1");
			p2.setId("2");
			p2.setName("name2");
					
			m.put(p1, "person1");
			m.put(p2, "person2");

                        System.out.println("Map m's size :" + m.size());
			
			p2.setId("1");
			
			System.out.println("Map m's size :" + m.size());
			
			for(Object o :m.entrySet()){
				Entry e = (Entry)o;
				System.out.println("key:"+ e.getKey());
				System.out.println("value:"+ e.getValue());
			}
			
		}

}


    ここでの変化はp 1,p 2のidを異なるように設定し,いずれもkeyとしてmapを挿入することである.2つのkeyが異なるため,我々の予測はいずれも挿入可能であるが,このときmapのsizeは2であるべきであり,挿入後にp 2のidを1,すなわちp 1と同じに修正することで,2つのentryのkeyが同じになると予測し,テストしてmapの構造を確認し,さっき挿入した2つの項目かどうか見てみましょう.
    このとき我々はHashMapの内部実装を知らないので,そのインスタンスがデータ挿入後もkeyの一意性を維持し続けるかどうか分からない.
    私たちが推測できるのは3つの答えです.
    1.異常を放出し、p 2のidをp 1と同じように修正することを許さず、keyの一意性を維持する.
    2.修正は可能であるが、あるアルゴリズムに基づいてp 1またはp 2の1つを削除してもkeyを維持する一意性を果たすことができる.
    3.変更できます.何も起こりません.2つのidの同じpersonインスタンスはmapに共存します.つまり、同じkeyが2つのvalueに対応しています.
    では皆さんは、HashMapのソースコードを試したことがなく、見たことがない場合、どのような選択をしますか?
    はい、プログラムを走りましょう.
    結果は次のように印刷されます.
Map m's size :2
key:Person [id=1, name=name2]
value:person2
key:Person [id=1, name=name1]
value:person1
    では、予測の3つ目の状況です.これはもともと私が一番よく見ている答えではありません.これで疑問があります.同じkeyが2つも異なるvalueに対応できる以上、私がこのkeyを通じて手に入れるべきvalueはどれですか.上記のコードのmainメソッドの最後に、次の2行のコードを追加します.

...

System.out.println("Map m   get   key p1:"+p1+" ,   value:"+m.get(p1));
System.out.println("Map m   get   key p2:"+p2+" ,   value:"+m.get(p2));
...

結果は次のとおりです.
Mapmがgetメソッドでkey p 1:Person[id=1,name=name 1]を用いた場合に取得するvalue:person 1
Mapmがgetメソッドでkey p 2:Person[id=1,name=name 2]を用いた場合に取得するvalue:person 1
p 1を使用してもp 2を使用しても、得られたvalueはperson 1であることがわかります.
では、現象はここまで書きます.次の編では、ソースコードを見ながら、この問題を研究します.
次のJDKソース学習シリーズ1---java.util(2):
http://www.iteye.com/topic/907293