-
list set map区别
- List,Set都是继承自Collection接口,Map则不是
- List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)
- Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。Map:适合储存键值对的数据 List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
- LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;HashMap是非线程安全的,HashTable是线程安全的;StringBuilder是非线程安全的,StringBuffer是线程安全的。
-
先来理清这几个爹的常见儿子:
Collection
|--------List
|----------LinkedList
|----------ArrayList
|----------Vector
|-----Stack
|--------Set
|----------HashSet
|----------TreeSet
Map
|---------HashMap
|---------TreeMap
-
list的子类介绍
ArrayList | Vector | LinkedList | |
底层结构 | 数组结构 | 数组结构 | 链表结 构 |
空间占用 | 存储区间连续 占用空间大,空间复杂度大 | 存储区间连续 占用空间大,空间复杂度大 | 存储区间离散 占用宽松,空间复杂度小 |
特点 | 查询快,增删慢 | 查询快,增删慢 | 查询慢,增删快 |
安全性 | 不安全,不同步,效率高 | 安全的,同步的,效率低 | 不安全,不同步,效率高 |
-
ArrayList,Vector,LinkedList
需求:模拟的数据的增删改查测试
// 计算添加所需的时间
static long readList_add(List<Integer> list) {
long start = System.currentTimeMillis();
for (int i = 0; i < 300000; i++) {
list.add(0, i);
}
return System.currentTimeMillis() - start;
}
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<Integer>();
System.out.println("ArrayList添加消耗的时间:" + readList_add(arrayList) + "毫秒");
LinkedList<Integer> linkedList = new LinkedList<Integer>();
System.out.println("LinkedList添加消耗的时间:" + readList_add(linkedList) + "毫秒");
Vector<Integer> vector = new Vector<Integer>();
System.out.println("Vector添加消耗的时间:" + readList_add(vector) + "毫秒");
}
结果:
ArrayList添加消耗的时间:10514毫秒
LinkedList添加消耗的时间:13毫秒
Vector添加消耗的时间:10558毫秒
这里使用的是add(int index,e elemen)方法,在指定的下标下插入数据,list.add(0, i);在插入的数据始终放入第一位,新插入的元素就会把前一位插入的元素向后挤。所以结果就是list.get(0)就是获取的29999,也就是最新插入的数据,这样会产生一种幻觉就是倒序,其实不是的。
插入位置的选取对LinkedList有很大的影响,一直往数据中间部分插入删除的时候,ArrayList比LinkedList更快
原因大概就是当数据量大的时候,system.arraycopy的效率要比每次插入LinkedList都需要从端查找index和分配节点node来的更快。
下面测试删除
// 计算删除所需的时间
static long readList_delete(List list) {
long start = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++) {
list.remove(i);//从头删
}
return System.currentTimeMillis() - start;
}
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<Integer>();
for (int i = 0; i < 100000; i++) {
arrayList.add(i);// 插入的时候始终在下标为0的位置插入,插入的新元素会向后移动
}
System.out.println("ArrayList删除消耗的时间:" + readList_delete(arrayList) + "毫秒");
LinkedList<Integer> linkedList = new LinkedList<Integer>();
for (int i = 0; i < 100000; i++) {
linkedList.add(i);// 插入的时候始终在下标为0的位置插入,插入的新元素会向后移动
}
System.out.println("linkedList删除消耗的时间:" + readList_delete(linkedList) + "毫秒");
Vector<Integer> vector = new Vector<Integer>();
for (int i = 0; i < 100000; i++) {
vector.add(i);// 插入的时候始终在下标为0的位置插入,插入的新元素会向后移动
}
System.out.println("Vector删除消耗的时间:" + readList_delete(vector) + "毫秒");
}
结果:
ArrayList删除消耗的时间:530毫秒
linkedList删除消耗的时间:2767毫秒
Vector删除消耗的时间:533毫秒
我曹,为什么???为什么linkedlist增删有时候都会落败?
因为:
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
1.对于随机访问,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
2.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
但测试结果与理论不相符。ArrayList在添加、查找、删除的性能都优于LinkedList。
细细想一下,当顺序添加数据时,ArrayList的容量足够大,就不把时间浪费在扩容上,如果对象是很简单对象,在删除操作时移动数组也是足够快的。LinkedList是链表结构相对数组来说比较复杂,在添加数据操作上比较消耗时间,而在删除操作时,因为大部分时间都花费在查找上,所以删除操作时间变长。而vector效率很低,但是线程安全,多用于银行等操作。
下面在测试查询:
// 计算查询所需的时间
static long readList_query(List<Integer> list) {
long start = System.currentTimeMillis();
for (int i = 0; i <= 10000; i++) {
list.add(i);
}
for (int i = 0; i <= 10000; i++) {
list.get(i);
}
return System.currentTimeMillis() - start;
}
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<Integer>();
System.out.println("ArrayList查询消耗的时间:" + readList_query(arrayList) + "毫秒");
LinkedList<Integer> linkedList = new LinkedList<Integer>();
System.out.println("linkedList查询消耗的时间:" + readList_query(linkedList) + "毫秒");
Vector<Integer> vector = new Vector<Integer>();
System.out.println("Vector查询消耗的时间:" + readList_query(vector) + "毫秒");
}
结果:
ArrayList查询消耗的时间:3毫秒
linkedList查询消耗的时间:59毫秒
Vector查询消耗的时间:2毫秒
三个list的使用场景:
- ArrayList使用场景:因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销
- Vector使用场景: 如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。
- LinkedList使用场景:经常有删除/插入操作而顺序遍历列表