目录
集合详细图
单例集合(Collection)
-
概念:java不提供直接集成Collection类的接口,只能继承其子接口List和Set,存储一组不唯一,无序的对象。
1:List接口
-
List:是一个有序的接口,有索引,可以存储重复的值。
-
Set:唯一,无序的接口,不可以保存重复的值。
-
区别:存储有序无序,重复不重复,Set删除和插入效率高,元素位置不会发生变化,List有索引,查询快。
1-1:ArrayList
继承AbstractList和实现List(增删改查)。RandomAccess(随机访问),Cloneable(克隆),java.io.Serializable(序列化)这些接口。线程不安全,建议单线程使用。
-
ArrayList:包含elementDate和size对象。允许空,重复,有序,线程不安全。
transient Object[] elementData; 保存添加的数组。初始容量10,扩容是原始大小的1.5倍。
删除数据是elementDate的大小是不会改变。理解:扩容的改变需要重新建一个集合。
transient修饰不会序列化。elementDate有扩容。
加快速度,序列化文件变小。
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size);
// Write out all elements in the proper order. 遍历elementDate
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
private int size; 元素的个数,null是一个元素
-
ArrayList删除:System.arraycopy方法整体向前移动一个位置,最后一个位置的元素指定为null,这样让GC可以去回收它。
-
优点:实现了RandomAccess(随机访问)接口,查找get很快,末尾添加数据非常快。
-
缺点:插入和删除是需要涉及一次元素的复制,元素多很耗性能。
1-2:LinkedList
-
双向链表,每一个节点里存到上下一个节点的地址。
-
插入和删除快,查找和修改比较慢
-
LinkedList 继承了 AbstractSequentialList 类。
-
LinkedList 实现了 Queue 接口,可作为队列使用。
-
LinkedList 实现了 List 接口,可进行列表的相关操作。
-
LinkedList 实现了 Deque 接口,可作为队列使用。
-
LinkedList 实现了 Cloneable 接口,可实现克隆。
-
LinkedList 实现了 java.io.Serializable 接口,即可支持序列化,能通过序列化去传输。
1-3:Vector
-
同步,执行效率不高,所以线程安全,容器扩容为2倍,
2:Set接口
2-1:HashSet
-
HashSet是基于HashMap来实现的,没有重复数据的接口,允许null,线程不安全,无序。
-
HashSet在存入一个值时,会调用该对象的hashCode()方法来获取其hashCode值。根据hashCode的值来决定该对象在HashSet中储存的位置。判断两个值是否相同需要用equals()来比较。
---封装成同步
SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));
2-2:TreeSet
-
有序,可排序(equles),不可重复,红黑树。
-
TreeSet是二叉树(红黑树)是实现的,自动排序的,不允许又NULL。
TreeSet<Object> objects = new TreeSet<>();
objects.add(32);
objects.add(31);
objects.add(34);
System.out.println(objects);
[31, 32, 34]
2-3:LinkedHashSet
-
会保存添加数据的顺序,非同步,允许空,继承HashSet,底层使用LinkedHashMap。
LinkedHashSet<String> lhset = new LinkedHashSet<String>();
// Adding elements to the LinkedHashSet
lhset.add("Z");
lhset.add("PQ");
lhset.add("N");
lhset.add("O");
lhset.add("KK");
lhset.add("FGH");
System.out.println(lhset);
[Z, PQ, N, O, KK, FGH]
-
HashSet:
-
不能保证元素的排列顺序,顺序有可能发生变化
-
集合元素可以是null,但只能放入一个null
-
HashSet底层是采用HashMap实现的
-
HashSet底层是哈希表实现的
-
-
TreeSet:
-
Treeset中的数据是排好序的,不允许放入null值。
-
TreeSet是通过TreeMap实现的,只不过Set用的只是Map的key。
-
TreeSet的底层实现是采用二叉树(红-黑树)的数据结构。
-
双列集合(Map)
异常:
-
NoSuchElementException-----当调用的映射中没有元素存在时
-
ClassCastException-------对象与映射中的元素不兼容时
-
NullPointerException-------如果试图使用映射不允许使用的null对象时
-
UnsupportedOperationException-----当试图改变一个不允许修改的映射时
1-1:HashMap
-
是一个散列表,键(键:HashSet)值对形式,无序的,线程不安全,键允许又一个空,非同步。
-
初始容量为16,加载因子是0.75。
1-2:TreeMap
键排序,非同步,线程不安全,
1-3:LinkedHastMap
-
LinkedHashMap继承自HashMap,它的多种操作都是建立在HashMap操作的基础上的。同HashMap不同的是,LinkedHashMap维护了一个Entry的双向链表,保证了插入的Entry中的顺序。
public class Test{
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("1", "value1");
map.put("2", "value2");
map.put("3", "value3");
//第一种:普遍使用,二次取值
System.out.println("通过Map.keySet遍历key和value:");
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
//第二种
System.out.println("通过Map.entrySet使用iterator遍历key和value:");
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第三种:推荐,尤其是容量大时
System.out.println("通过Map.entrySet遍历key和value");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第四种
System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
for (String v : map.values()) {
System.out.println("value= " + v);
}
}
}
1-4:HashTable
-
默认容量11,加载因子0.75,同步,不允许键值null,扩容为2倍-1,不会转换红黑树。