数组和集合的区别
长度定义:
数组长度固定,声明时需要指定长度,长度不可变
list集合动态长度,可自动调节长度,无需预先指定
数据类型:数组可保存任何类型,包括基本类型,list只能保存对象引用,不支持基本数据类型
集合
有序可重复:List (存入什么顺序,就是什么顺序)
无序不重复:HashSet (存入的数据无规则排列)
自动排序切不重复集合:TreeSet (存入的数据会自动排序)
ArrayList和LinkedList:
ArrayList : 基于动态数组,连续内存存储,适合下标访问(随机访问),扩容机制:因为数组长度固定,超出长度存数据时需要新建数组,然后将老数组的数据拷贝到新数组,如果不是尾部插入数据还会涉及到元素的移动(挨个元素往后复制一份,再插入新元素),使用尾插法并指定初始容量可以极大提高性能、甚至超过linkedList(需要创建大量的node对象)。
LinkedList : 基于链表,可以存储在分散内存中,适合做数据插入及删除操作,不适合查询:需要逐一遍历。遍历LinkedList必须使用iterator不能使用for循环,因为每次for循环体内通过get(i)获取某一元素时都需要对list重新进行遍历,性能消耗极大。
Map
Map的key都不可重复
无序map:HashMap(存入的数据无规则排列)
有序map:LinkedHashMap(存入什么顺序,就是什么顺序)
自动排序map:TreeMap(存入的数据会根据key值自动排序)
HashMap和HashTable:
1、HashTable每个方法都加了synchronized修饰,是线程安全的,HashMap非线程安全的;
2、HashMap允许key和value为null,HashTable的key和value都不允许为null。
多线程
常见并发异常:
java.util.ConcurrentModificationException
List
数组复制底层实现:循环旧数组一个个set进新数组。
// 在多线程并发下,ArrayList是不安全的
// 解决办法
// 1.通过Vector实现
List<String> list = new Vector(); // 通过在add方法上加synchronized关键字实现
// 2.通过Collrctions工具类实现
List<String> list2 = Collections.synchronizedList(new ArrayList());
// 3.通过juc实现
List<String> list3 = new CopyOnWriteArrayList();
// CopyOnWrite 写入时复制,读写分离,写入的时候先copy原来的集合,然后加入新元素,通过lock实现线程安全
Set
// 非安全的
Set<String> set = new HashSet<>();
// 解决方法
// 1.Collections工具类
Set<String> set1 = Collections.synchronizedSet<>();
// 2.juc
Set<String> set2 = new CopyOnWriteArraySet<>();
// HashSet底层原理
public HashSet() {
map = new HashMap<>();
}
// add set本质就是map的key无法重复
public boolean add(E e) {
return map.put(e,"常量");
}
Map
// 非线程安全的
Map<String,Object> map = new HashMap<>();
// 解决办法
// 1.Collections工具类
Map<Stding,Object> map1 = Collections.synchronizedMap(new HashMap<>());
// 2.juc
Map<Stding,Object> map2 = new ConcurrentHashMap<>();