大家好,又见面了,我是你们的朋友全栈君。
Map集合和List集合哪个效率更高
List接口
List集合是一个元素有序(存储有序)、可重复的集合,集合中的每个元素都有对应的索引,以便于查询和修改,List集合是允许存储null值的。
List集合可重复原因,请看源码:
代码语言:javascript复制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的集合 有参构造器:创建一个初始化长度的集合。
代码语言:javascript复制/** * 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)方法,返回传入该索引的值。
代码语言:javascript复制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。
代码语言:javascript复制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方法大致一样,也是进行集合的拷贝。因此添加和移除的效率低。
代码语言:javascript复制 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的区别
代码语言:javascript复制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。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/142801.html原文链接:https://javaforall.cn