<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    于吉吉的技術(shù)博客

    建造高性能門戶網(wǎng)

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      65 隨筆 :: 6 文章 :: 149 評論 :: 0 Trackbacks
    看一段set的簡單應(yīng)用代碼

            Set<String> set = new HashSet<String>();
            String a 
    = "1",b = "2",c = "1",d = "3",e = "2";
            set.add(a);
            set.add(b);
            set.add(c);
            set.add(d);
            set.add(e);
            
            Iterator it 
    = set.iterator();
            
    while(it.hasNext()){
                String s 
    = (String)it.next();
                System.out.print(s
    +",");
            }
            System.out.println(
    "一共有對象:"+set.size()+""); //打印結(jié)果是:3,2,1,一共有對象:3個

    我們都知道Set是一種最簡單的集合,對象的排序無特定的規(guī)則,集合里面存放的是對象的引用,所以沒有重復(fù)的對象,在上面的代碼中,程序創(chuàng)建了a、b、c、d、e五個變量,其中a和c,b和e所引用的字符串是一致的,然后向set添加了這5個變量。打印出來的size()只有3個,實際上向集合加入的只有3個對象,在執(zhí)行Set的add()方法時已經(jīng)進行了判斷這個對象是否存在于集合,如果對象已經(jīng)存在則不繼續(xù)執(zhí)行。


    Set的接口有兩個實現(xiàn)類,HashSet和TreeSet,HashSet是按照哈希算法來進行存取集合中的對象,存取速度比較快,TreeSet類顯示了SortedSet接口,具有排序功能

    HashSet
    HashSet是按照哈希算法來存取集合中的對象,具有很好的存取和查找性能,當向集合中加入一個對象時,HashSet會調(diào)用對象的hashCode()方法來獲取哈希碼,然后根據(jù)這個哈希嗎來計算對象在集合中的存放位置。
    在Object類中定義了hashCode()和equal(),equal()是按照內(nèi)存地址比較對象是否相同,如果object1.equal(object1)w為true時,則表明了object1和object2變量實際上引用了同一個對象,那么object1和object2的哈希碼也是肯定相同。
    稍微的看看HashSet的源碼

    public class HashSet<E>
        
    extends AbstractSet<E>
        
    implements Set<E>, Cloneable, java.io.Serializable
    {

        
    private transient HashMap<E,Object> map;
        
    private static final Object PRESENT = new Object();
            
    public HashSet() {
            map 
    = new HashMap<E,Object>();
        }

       
    public boolean add(E e) {
            
    return map.put(e, PRESENT)==null;
        }
    }

    public class HashMap<K,V>
        
    extends AbstractMap<K,V>
        
    implements Map<K,V>, Cloneable, Serializable
    {

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

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

    }

    我們會發(fā)現(xiàn)我們調(diào)用Set的add()方法其實是返回一個transient HashMap.put(e, PRESENT),再跟進HashMap的put(K key, V value)方法進行查看,可以看到int hash = hash(key.hashCode());使用了set.add(key)的key做了一個哈希處理得到一個哈希碼,然后再將Entry做了一個遍歷,使用equal()方法對講原有的對象和新添加的對象進行了一個比較,如果出現(xiàn)了true的情況,就直接返回一個oldValue,如果在遍歷對比的過程中沒有出現(xiàn)ture的情況,則繼續(xù)一下的步驟modCount++,將對象總數(shù)自加,并且繼續(xù)執(zhí)行addEntry()的操作,下面涉及HashMap的操作就不繼續(xù)。

    實際上HashSet的底層實現(xiàn)是基于HashMap,所以在此處涉及到Hash算法不展開,詳細可以見另一篇《java數(shù)據(jù)結(jié)構(gòu)-HashMap

    TreeSet
    TreeSet類是實現(xiàn)了SortedSet接口,所以能夠?qū)现械膶ο筮M行排序

            Set iset = new TreeSet();
            iset.add(
    new Integer(1));
            iset.add(
    new Integer(10));
            iset.add(
    new Integer(5));
            iset.add(
    new Integer(8));
            iset.add(
    "2");
            Iterator it2 
    = iset.iterator();
            
    while(it2.hasNext()){
                Integer s 
    = (Integer)it2.next();
                System.out.print(s
    +",");
            }
            System.out.println(
    "一共有對象:"+iset.size()+"");//打印出來的結(jié)果:1,2,5,8,10,一共有對象:5個

    當TreeSet向集合加入一個對象時,會把它插入到有序的對象序列中,TreeSet包括了兩種排序方式,自然排序和客戶化排序,在默認的情況下使用自然排序。

    自然排序
    在jdk類庫中,有部分類實現(xiàn)了Comparable接口,如Integer,Double等等,Comparable接口有一個compareTo()方法可以進行比較,TreeSet調(diào)用對象的compareTo()方法比較集合中對象的大小,然后進行升序排序。如Integer:

    public final class Integer extends Number implements Comparable<Integer> {

        
    public int compareTo(Integer anotherInteger) {
        
    int thisVal = this.value;
        
    int anotherVal = anotherInteger.value;
        
    return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
        }

    }

    基于Comparable的屬性,使用自然排序時,只能向TreeSet集合中加入同類型的對象,并且這些對象的類必須實現(xiàn)了Comparable的接口,以下我們嘗試向TreeSet集合加入兩個不同類型的對象,會發(fā)現(xiàn)拋出ClassCastException

    Set iset = new TreeSet();
    iset.add(
    new Integer(1));
    iset.add(
    new Integer(8));
    iset.add(
    "2");
    Exception in thread "main" java.lang.ClassCastException: java.lang.Integer

    我們再打開TreeSet的源碼進行查看

    public class TreeSet<E> extends AbstractSet<E>
        
    implements NavigableSet<E>, Cloneable, java.io.Serializable
    {
        
    private transient NavigableMap<E,Object> m;

        
    private static final Object PRESENT = new Object();

        
    public boolean add(E e) {
        
    return m.put(e, PRESENT)==null;
        }

    }

    NavigableMap為接口,實現(xiàn)類為TreeMap

    public class TreeMap<K,V>
        
    extends AbstractMap<K,V>
        
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
    {
        
    private final Comparator<? super K> comparator;

        
    private transient Entry<K,V> root = null;

        
    public V put(K key, V value) {
            Entry
    <K,V> t = root;
            
    if (t == null) {
            
    // TBD:
            
    // 5045147: (coll) Adding null to an empty TreeSet should
            
    // throw NullPointerException
            
    //
            
    // compare(key, key); // type check
                root = new Entry<K,V>(key, value, null);
                size 
    = 1;
                modCount
    ++;
                
    return null;
            }
            
    int cmp;
            Entry
    <K,V> parent;
            
    // split comparator and comparable paths
            Comparator<? super K> cpr = comparator;
            
    if (cpr != null) {
                
    do {
                    parent 
    = t;
                    cmp 
    = cpr.compare(key, t.key); //此處如果類別不相同可能拋出ClassCastException
                    if (cmp < 0)
                        t 
    = t.left;
                    
    else if (cmp > 0)
                        t 
    = t.right;
                    
    else
                        
    return t.setValue(value);
                } 
    while (t != null);
            }
            
    else {
                
    if (key == null)
                    
    throw new NullPointerException();
                Comparable
    <? super K> k = (Comparable<? super K>) key;
                
    do {
                    parent 
    = t;
                    cmp 
    = k.compareTo(t.key);
                    
    if (cmp < 0)
                        t 
    = t.left;
                    
    else if (cmp > 0)
                        t 
    = t.right;
                    
    else
                        
    return t.setValue(value);
                } 
    while (t != null);
            }
            Entry
    <K,V> e = new Entry<K,V>(key, value, parent);
            
    if (cmp < 0)
                parent.left 
    = e;
            
    else
                parent.right 
    = e;
            fixAfterInsertion(e);
            size
    ++;
            modCount
    ++;
            
    return null;
        }

    }

    首先判斷原始集合是否存在,如果不存在則直接創(chuàng)建,無需比較。
    如果原始集合存在的話,先去取出Comparator對象,然后遍歷原始集合t,使用parent為臨時比較值,逐個使用compare(key, t.key)方法與添加對象key進行比較,決定元素排在集合的left或right。

    客戶端排序
    客戶端排序時因為java.util.Comparator<Type>接口提供了具體的排序方式,<Type>指定了被比較對象的類型,Comparator有個compare(Type x,Type y)的方法,用于比較兩個對象的大小。

    public class NameComparator implements Comparator<Name>{
        
        
    public int compare(Name n1,Name n2){
            
    if(n1.getName().compareTo(n2.getName())>0return -1;
            
    if(n1.getName().compareTo(n2.getName())<0return 1;
            
            
    return 0;
        }
        
        
    public static void main(String[] args) {
            Set
    <Name> set = new TreeSet<Name>(new NameComparator());
            
            Name n1 
    = new Name("ray");
            Name n2 
    = new Name("tom");
            Name n3 
    = new Name("jame");
            set.add(n1);
            set.add(n2);
            set.add(n3);
            
            Iterator it 
    = set.iterator();
            
    while(it.hasNext()){
                Name s 
    = (Name)it.next();
                System.out.print(s.getName()
    +",");
            }
            System.out.println(
    "一共有對象:"+set.size()+"");
        }
    }
    //打印結(jié)果是:tom,ray,jame,一共有對象:3個

    道理與自然排序其實相同,都是通過實現(xiàn)Comparator接口,就不細說了,可能有些說得不對的地方,歡迎指正

    ----------------------------------------

    by 陳于喆
    QQ:34174409
    Mail: dongbule@163.com



    posted on 2011-01-06 18:07 陳于喆 閱讀(8611) 評論(0)  編輯  收藏 所屬分類: java數(shù)據(jù)結(jié)構(gòu)
    主站蜘蛛池模板: 三年片在线观看免费观看高清电影| 亚洲v国产v天堂a无码久久| 亚洲AV无码国产精品色| 在线观看免费精品国产| 国产无遮挡又黄又爽免费视频| 亚洲精品私拍国产福利在线| 成人一级免费视频| 免费人成视频在线| 一级做受视频免费是看美女| 久久久久亚洲AV成人片| 精品国产麻豆免费人成网站| 亚洲成AV人片一区二区| 四虎影院免费在线播放| 羞羞视频免费网站含羞草| 亚洲av永久无码精品古装片| 全部免费国产潢色一级| 无码AV片在线观看免费| 亚洲高清日韩精品第一区| 中文字幕无码播放免费| 免费人人潮人人爽一区二区| 亚洲人成人网站在线观看| 一级毛片免费播放男男| 亚洲乱码一区av春药高潮| 性做久久久久久久免费看| 美女被免费网站91色| 亚洲成AV人片在线观看ww| 日本牲交大片免费观看| 亚洲精品在线免费看| 亚洲一区二区三区精品视频| 亚洲人成网亚洲欧洲无码久久| 成人毛片免费视频| a级毛片免费观看在线| 在线a亚洲老鸭窝天堂av高清| 久久久影院亚洲精品| 亚洲男人第一无码aⅴ网站 | 好吊妞在线新免费视频| 国产成人一区二区三区视频免费 | 噼里啪啦电影在线观看免费高清| 国产无遮挡又黄又爽免费网站 | 永久免费AV无码国产网站| 日韩精品免费视频|