Java基础之集合类如ArrayList、LinkedList、HashMap、HashTable的区别


博客出自:http://blog.csdn.net/liuxian13183,转载注明出处! All Rights Reserved ! 


ArrayList是一个动态数组,有下标

LinkedList是一个双向链表,一个指针指向下一个

相同点:都继承自Collections类,放动态数据。

不同点:

后者有指针,增加一个数据,只用断开一个连接,分别将新数据连上

删除一个数据,区别在于如果这个数据位于数组中间,后者只用查到该数据,断开一个连接,将两边的数据连上;

而前者需要将后面所有数据移位

修改,对于后者来说,就是删除+增加;而后者需要移位。

查找,前者通过下标查找方便,后者需要一个指针指向下一个指针来寻找数据,比较慢。

offer==add:添加一个值到尾部,offer是使用add方法实现的。

peek:获得第1个值。

pop:获得第1个值并删除。

poll:获得第1个值并删除,与pop不同的是如果第1个值为null,pop抛出NoSuchElementException,而poll仅返回null。



Vector使用数组实现,其实跟ArrayList一样,区别仅在于实现同步,即不同线程可以共用一个数据。但它不会对遍历如iterator加锁,仅set、get、remove等常用操作加锁,在这一点上HashTable同理。


HashMap底层使用数组+链表实现,同一个键可以放多个值,但取出的是最后一个,非同步,允许放空值空键

HashTable与HashMap一样,唯一不同就是,它是线程安全的,put、get等操作都加锁,且不允许空值空键

查找都根据key的hash来定位数组的下标。

LinkedHashMap与LinkedArrayList原理相似,可以放空值空键,非同步;相比HashMap是个单向链表来讲,它是个双向链表,可以不像单向链表一样从头开始查找数据,是单向链表的升级;缺点:保留原值。

我们能否让HashMap同步?可以通过下面语句同步:

Map map=Collections.sychronizedMap(hashmap);


如果要完全的线程安全可以考虑CopyOnWriteArrayList和ConcurrentHashMap。它们使用volatile和synchronzied来保持同步。

 Collections.unmodifiableList(list);
上面的方法可使当前list无法再添加对象,保持数据传递的安全性。

Android提供一个新的API:SpareArray,来替换ArrayList,特点不存空值,在跟下标有关的操作中,都会执行
一遍回收操作,将空值移除提高查找和增加效率。

Hash:指针对一段数据做的指纹(fingerprint)或者叫摘要(diget),用于快速查找。hash一般保证值不相等,防止暴力碰撞和篡改; 如果值相等,则需要继续当前算法,直到不等为止(再散列法),还有开放寻址法、再建公共溢出区法等等。常见的hash算法有Md5和Sha等。

比如HashMap,查找时不是比较key,而是比较key的hash值,则速度更快。

再比如ArrayMap,使用数组结构,存储hash数组和value数组。put时,根据key和key得到的hash,来设计value的存储位置index,然后把旧值返回,将新的value存入; get时,根据key和key得到的hash,计算出index,从value数组中取得目标value。

最简单的就是String对象里的hashCode算法:

	public static int hashCode(char[] value) {
		int h = hash;
		if (h == 0 && value.length > 0) {
			char val[] = value;

			for (int i = 0; i < value.length; i++) {
				h = 31 * h + val[i];
			}
			hash = h;
		}
		return h;
	}

TreeSet、TreeMap是自动排序的,TreeSet使用TreeMap来实现。

TreeSet:

public class TreeSet extends AbstractSet
    implements NavigableSet, Cloneable, java.io.Serializable
{
    /**
     * The backing map.
     */
    private transient NavigableMap m;
  public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }

   private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        // Read in any hidden stuff
        s.defaultReadObject();

        // Read in Comparator
        @SuppressWarnings("unchecked")
            Comparator c = (Comparator) s.readObject();

        // Create backing TreeMap
        TreeMap tm = new TreeMap<>(c);
        m = tm;

        // Read in size
        int size = s.readInt();

        tm.readTreeSet(size, s, PRESENT);
    }

TreeMap: 通过Comparator接口实现升级排序

    public V put(K key, V value) {
        TreeMapEntry t = root;
        if (t == null) {
            // We could just call compare(key, key) for its side effect of checking the type and
            // nullness of the input key. However, several applications seem to have written comparators
            // that only expect to be called on elements that aren't equal to each other (after
            // making assumptions about the domain of the map). Clearly, such comparators are bogus
            // because get() would never work, but TreeSets are frequently used for sorting a set
            // of distinct elements.
            //
            // As a temporary work around, we perform the null & instanceof checks by hand so that
            // we can guarantee that elements are never compared against themselves.
            //
            // compare(key, key);
            //
            // **** THIS CHANGE WILL BE REVERTED IN A FUTURE ANDROID RELEASE ****
            if (comparator != null) {
                if (key == null) {
                    comparator.compare(key, key);
                }
            } else {
                if (key == null) {
                    throw new NullPointerException("key == null");
                } else if (!(key instanceof Comparable)) {
                    throw new ClassCastException(
                            "Cannot cast" + key.getClass().getName() + " to Comparable.");
                }
            }

            root = new TreeMapEntry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        int cmp;
        TreeMapEntry parent;
        // split comparator and comparable paths
        Comparator cpr = comparator;
        if (cpr != null) {
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                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();
            @SuppressWarnings("unchecked")
                Comparable k = (Comparable) 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);
        }
        TreeMapEntry e = new TreeMapEntry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }

附Java层次关系图:

如图所示:图中,实线边框的是实现类,折线边框的是抽象类,而点线边框的是接口 


Java基础之集合类如ArrayList、LinkedList、HashMap、HashTable的区别_第1张图片


有关集合类的排序和其他介绍请移步:

http://blog.csdn.net/liuxian13183/article/details/7557957

Java集合汇总:https://hacpai.com/article/1523869541981

你可能感兴趣的:(解问答疑,Java高级)