se集合篇之--List,Set,Map接口之间

List与set都是单列元素的集合,它们有共同的父接口Collection。
List允许有重复的元素插入,set集合不允许。
对于set的实现类是怎么样区分插入的对象是否是同一个这里有可以长篇大论了。
首先以hashset为例子吧,hashset的底层应用了hashmap,follow me watch the code(写博客很枯燥)

public boolean add(E e) {
        return map.put(e, PRESENT)==null;//hashset的add方法源码,PRESENT其实只是一个静态的final的object空对象实例
    }

private transient HashMap<E,Object> map;//map其实就是一个hashmap

从上面的源码可以很明显就看出,hashset其实就是沾了hashmap的光,也就是利用了hashmap中key的唯一性。

那么下面让我们看瞧瞧hashmap中put方法是怎么保证key的唯一性的,下面老规矩,贴源码:

public V put(K key, V value) {
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);
        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;
    }

 private V putForNullKey(V value) {
     //e.next,Entry<K,V>静态内部类中有一个next成员变量,这个变量是链表集合的核心,
     //它指向了下一个元素的地址
     //这里是将整个Entry链表遍历了一遍,只要next所指向的引用对象不是null
     //找到key==null的Entry
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {
            if (e.key == null) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);//关于这个方法的调用我不知道是几个意思,有知道的可以留言咱们理论一下。
                return oldValue;//返回原来的元素的value
            }
        }
        modCount++;
        addEntry(0, null, value, 0);
        return null;
    }

根据代码中key.equals(k)就知道为什么要重写元素对象的equals方法了
判断同一个元素是用到equals方法,int hash = hash(key)中,hash方法用到了hashCode()方法。
下满是hash()的源码:

final int hash(Object k) {
        int h = hashSeed;
        if (0 != h && k instanceof String) {
            return sun.misc.Hashing.stringHash32((String) k);
        }

        h ^= k.hashCode();

        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }

下面的一大片无符号右移位运算我没有研究,表示有点蛋疼。
所以,问题来了,到底要如何重写equals和hashcode方法呢?
请移步我的另一篇博客http://blog.csdn.net/sj13823420859/article/details/50404451

set集合框架的add方法有一个boolean类型返回值,代表插入是否成功。当然List的add方法也有。
set集合只能用迭代器迭代取出所有的结合,list可以用get根据下标获取元素。

关于Map集合,以HashMap为例子,HashMap底层每一个元素是一个HashMap的静态内部类Entry,它实现了Map的内部接口Entry。map集合的key是唯一的,一个集合里面不可能存在两个相同的key,上面已经有说明map集合key唯一性的原理了,Map集合的遍历如下

//遍历键,通过键取值

Set set = map.keySet();

for (Object key : set) {

System.out.println("键:"+key+"  值:"+map.get(key));

}

//遍历键集合

Iterator it=map.keySet().iterator();

while(it.hasNext()){

System.out.println("键:"+it.next());

}

List 以特定次序来持有元素,可有重复元素。Set无法拥有重复元素,内部排序,也就是顺序是随机的。Map 保存 key-value 值,value 可多值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值