Map集合和List集合总结

Map集合和List集合哪个效率更高

List接口

List集合是一个元素有序(存储有序)、可重复的集合,集合中的每个元素都有对应的索引,以便于查询和修改,List集合是允许存储null值的。

List集合可重复原因,请看源码:

public boolean add(E e) {
	ensureCapacityInternal(size + 1);  // Increments modCount!!
	elementData[size++] = e;
	return true;
}

结论:无论添加重复还是不重复的元素,结果都是返回true.

ArrayList集合

ArrayList集合是List接口的实现类,有以下特点:

1.有序,有索引
2.元素可以重复
3.可以存储null值
4.随机访问速度快,修改快,增加/插入或者移除/删除的效率慢
5.线程不安全

注意:List集合的实现类想要实现去重复的话:
思想:
  1、首先要创建一个新的集合。
  2、然后使用选择排序思想进行去除重复元素。

Vector集合

  Vector集合也是List接口一个实现类,底层数据结构是数组,插入和移除性能较差,线程安全,效率低。

总结:

ArrayList集合和Vector集合
  ArrayList和Vector都是基于数组实现的list类,所以ArrayList和Vector封装了一个动态的,允许再分配的Object[]数组,不指定的话长度默认为10。ArrayList和Vector对象使用initialCapacity参数来设置该数组的长度,当向集合添加大量元素时,可以使用ensureCapac(int minCapacity)方法一次性的增加initialCapacity。

  ArrayList和Vector在用法上几乎完全相同,但Vector比较古老,方法名比较长,最好是不使用。ArrayList是线程不安全的,Vector是线程安全的,但这个完全可以手动将一个ArrayList变成线程安全的。

ArrayList部分源码分析:

1、首先我们先看一下ArrayList集合的构造器:
  无参构造器:创建一个默认长度为10的集合
  有参构造器:创建一个初始化长度的集合。

/**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

2、分析get方法
  我们调用get方法,获取数据时,底层会调用 rangeCheck(index)方法,然后对传入的索引进行判断,在 rangeCheck(int index)方法中如果传入的索引不存在,那么会抛出异常,如果传入的索引没有问题,那么会调用elementData(index)方法,返回传入该索引的值。

public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}

private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

E elementData(int index) {
    return (E) elementData[index];
}

3、add方法分析:
  我们使用add方法,向集合中添加一个元素时,首先,我们要调用ensureCapacityInternal()方法判断集合的长度是否够用,那么经过层层判断,如果集合长度不够,那么,将会对旧的集合使用集合的工具类的copyOf()方法进行拷贝创建新的集合,如果集合长度够用,那么返回true。

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

4、remove方法分析
  实现的逻辑和add方法大致一样,也是进行集合的拷贝。因此添加和移除的效率低。

    rangeCheck(index);

    modCount++;
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

LinkedList集合

特点:
1.底层数据结构是链表
2.链表的特点有序,查询和修改效率低,增加和删除效率高
3.可以存储null值
4.线程不安全
5.允许重复
6.不可排序

LinkedList与ArrayList集合比较
  LinkedList与ArrayList的实现机制完全不同,ArrayList内部以数组的形式来保存集合中的元素,因此随机访问集合元素时有较好的性能;而LinkedList内部以链表的形式来保存集合中的元素,因此随机访问性能较差,但是插入、删除元素时非常快。

Map接口

  Map 未继承 Collection,而是独立的接口,Map 是一种把键对象和值对象进行映射的集合,它的每一个元素都包含了一对键对象和值对象,Map 中存储的数据是没有顺序的, 其 key 是不能重复的,它的值是可以有重复的。

Map集合的特点:

1.能够存储唯一的列的数据(唯一,不可重复)
2.能够存储可以重复的数据(可重复)
3.值的顺序取决于键的顺序
4.键和值都是可以存储null元素的

Map 接口常见的四个实现类:Hashtable,HashMap,TreeMap,LinkedHashMap;

HashTable集合

内部存储的键值对是无序的是按照哈希算法进行排序,与 HashMap 最大的区别就是线程安全。键或者值不能为 null,为 null 就会抛出空指针异常。

特点:
不允许null键和null值
线程安全,效率低

HashMap集合

基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)
此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap如何运行的:
  HashMap在Map.Entry静态内部类实现中存储key-value对。HashMap使用哈希算法,在put和get方法中,它使用hashCode()和equals()方法。当我们通过传递key-value对调用put方法的时候,HashMap使用Key hashCode()和哈希算法来找出存储key-value对的索引。Entry存储在LinkedList中,所以如果存在entry,它使用equals()方法来检查传递的key是否已经存在,如果存在,它会覆盖value,如果不存在,它会创建一个新的entry然后保存。当我们通过传递key调用get方法时,它再次使用hashCode()来找到数组中的索引,然后使用equals()方法找出正确的Entry,然后返回它的值。

特点:
键无序,唯一,类似于Set集合
值有序,可重复,类似于List
底层数据结构是哈希表,保证键唯一
允许键为null,值为null

HashMap和Hashtable的区别

HashMap是不安全的不同步的效率高的  允许null键和null值
Hashtable是安全的同步的效率低的 不允许null键和null值
底层都是哈希表结构

LinkedHashMap集合

Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序,相当于一个栈,先 put 进去的最后出来,先进后出。

特点:
键有序,唯一,
值有序,可重复,类似于List
底层数据结构是哈希表和链表,哈希表保证键唯一,链表保证键有序

TreeMap集合

基于红黑树 (red-black tree) 数据结构实现,按 key 排序,默认的排序方式是升序。

总结:

  如果List 和Map存储的元素都比较多。那么在取元素方面,List要慢很多。 但是这也不是绝对的,因为List底层基于数组,如果你明确的知道你要取的元素在哪个下标上,那么List也是相当的快。但是如果你不清楚,只能通过迭代内部全部元素然后进行条件判断查找,那么List就要慢的多,因为他要从头到尾一个个的元素去查,直到找到满足你的要求的那个元素,而Map则不需要迭代,因为Map有键,直接取键对应的值。 对于添加元素,List是在数组的结尾追加,当容量不够时,创建一个新的更长的数组然后将旧的全部拷贝过来。Map和他的方式差不多,也是容量不足的时候需要重新创建新的然后拷贝,但是当发生删除元素时,List简直就是灾难。假设你有10000个元素,你删除首个元素,在删除完毕以后 List中的所有元素都必须进行一次移动操作,向前位移。。。而Map则不需要。

  大概就是这样,如果你考虑一个长度比较可预测的保存元素的集合,并且很少有删除操作,大部分是进行全部迭代的操作,那么用List会比较合适。
  如果你的List还要经常增删,那么用LinkedList比较合适。
  如果你要快速查找,取值,用HashMap比较合适。
  如果同时要保证,元素放进去的顺序和取出来的顺序一致用LinkedHashMap。

你可能感兴趣的:(Java基础,List集合,Map集合)