1. List - ArrayList、LinkedList、Vector
- ArrayList
bash
1. 可以有重复元素
2. 超出后自动增加大小,增加一半。会自动重新分配更大的数组,并将元素复制到新数组中
3. 通过索引保存值,访问可以通过索引访问,更加高效。但是添加/删除效率满,
因为操作后需要把其他的全部移动一遍
- LinkedList
bash
1. 通过前后的链表构成一个位置
2. 遍历需要从头开始,效率低
3. 新增/删除 方便,只需要改变链表的链接顺序即可
- Vector
bash
1. 线程安全,使用同步的方式更新数据,性能较差
- 常见使用方法
java
add(E element):向ArrayList的末尾添加元素。
add(int index, E element):在指定位置插入元素。
remove(int index):删除指定位置的元素。
get(int index):获取指定位置的元素。
set(int index, E element):将指定位置的元素替换为新元素。
size():获取ArrayList的大小(元素个数)。
isEmpty():判断ArrayList是否为空。
contains(Object o):判断ArrayList是否包含指定元素。
indexOf(Object o):返回指定元素在ArrayList中第一次出现的位置。
lastIndexOf(Object o):返回指定元素在ArrayList中最后一次出现的位置。
subList(int fromIndex, int toIndex)方法,该方法用于获取LinkedList的子列表
2. Set - HashSet、LinkedHashSet、TreeSet
- HashSet
java
1. 不保留插入顺序,不允许重复元素存在
2. 实现基于哈希表的数据结构
3. 由于哈希表的高效性,查找速度非常快。插入时如果重复,
会覆盖,通过红黑树/链表解决冲突
4. 允许存储null元素
哈希表:
是一种数据模式:维护了一个表,key是hash值,value是统一的值PRESENT。
如果在hashset中存储数据,会把数据转换为hash值,放到对应的hash表中
- LinkedHashSet
java
1. 和hashSet差不多,保留了插入顺序
2. 不允许存在null
3. 不允许重复元素
- TreeSet
java
1. 使用红黑树存储元素
2. 不许存在null
3. 支持按照添加顺序保留/自定义顺序
- 常用方法
java
add(E e):向LinkedHashSet添加元素。
remove(Object o):从LinkedHashSet中移除指定元素。
contains(Object o):判断LinkedHashSet是否包含指定元素。
size():获取LinkedHashSet中元素的个数。
isEmpty():判断LinkedHashSet是否为空。
clear():清空LinkedHashSet中的所有元素。
3. Map - HashMap、TreeMap、LinkedHashMap、Hashtable
- HashMap
java
1. 使用hash表存储map中的key,value映射在对应的桶中。快速查找
2. 允许null
3. 无须,并且不允许存在重复key
- LinkedHashMap
java
1. 保留存储顺序
2. 不允许key为null
3. 双向链表存储
- TreeMap
java
1. 有序,可以按照插入顺序或者自定义
2. 使用红黑树存储键
- Hashtable
java
1. 类似于HashMap,线程安全,都是同步的,性能较差
2. 不允许null存在
3. 是否包含key使用contains();是否包含value使用containsValue()
而在hashMap中使用containsKey();containsValue();
- 使用方法
java
* put(K key, V value):将键值对添加到Map中。
* get(Object key):获取指定键对应的值。
* remove(Object key):从Map中移除指定键的键值对。
* containsKey(Object key):判断Map是否包含指定的键。
* containsValue(Object value):判断Map是否包含指定的值。
* size():获取Map中键值对的数量。
* isEmpty():判断Map是否为空。
* keySet():返回Map中所有键的Set集合。
* values():返回Map中所有值的Collection集合。
* entrySet():返回Map中所有键值对的Set集合。
* replace() : 替换
java
@Test
void testMap(){
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("First", 1);
map.put("Second", 2);
map.put("Third", 3);
map.put("Forth", 4);
System.out.println("获取First指定键对应的值:" + map.get("First"));
System.out.println("判断Map是否包含指定的键:" + map.containsKey("First"));
System.out.println("判断Map是否包含指定的值" + map.containsValue(5));
System.out.println("获取Map中键值对的数量" + map.size());
System.out.println("判断Map是否为空" + map.isEmpty());
Set<String> strings = map.keySet();
String resKeys = strings.toString();
System.out.println("返回Map中所有键的Set集合:" + resKeys);
Collection<Integer> collection = map.values();
String resValues = collection.toString();
System.out.println("返回Map中所有值的Collection集合" + resValues);
Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
for (Map.Entry<String, Integer> entry: entrySet){
System.out.println("返回Map中所有键值对的Set集合Key-->" + entry.getKey() + ", Value-->" + entry.getValue());
}
map.remove("First");
map.replace("Forth", 40);
}
4. 遇到的一些问题及解决方案
- 遍历map的时候不能remove或者replace,一个集合在迭代器遍历的过程中被修改(增加、删除元素),则会抛出
ConcurrentModificationException
。这个异常是为了保护迭代器的一致性,因为迭代器在遍历过程中维护着一个期望的集合状态,如果集合发生了修改,那么迭代器的状态就变得不一致了,因此抛出异常。
解决方案:
java
//把map存储在Entry里面
Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
//把Map.Entry在Set容器,提取转换为迭代器
Iterator<Map.Entry<String,Integer>> iterator = entrySet.iterator();
while (iterator.hasNext()){
Map.Entry<String,Integer> entry = iterator.next();
//使用迭代器删除map的元素
iterator.remove();
System.out.println("返回Map中所有键值对的Set集合Key-->" + entry.getKey() + ", Value-->" + entry.getValue());
}
5. 遍历Map的方法
java
//方法1,使用keySet()遍历
for (String s : map.keySet()){
System.out.println("返回Map中所有键值对的Set集合Key-->" + s + ", Value-->" + map.get(s));
}
//把map存储在Entry里面
Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
//把Map.Entry在Set容器,提取转换为迭代器
Iterator<Map.Entry<String,Integer>> iterator = entrySet.iterator();
//方法2:使用迭代器遍历
while (iterator.hasNext()){
Map.Entry<String,Integer> entry = iterator.next();
iterator.remove();
System.out.println("返回Map中所有键值对的Set集合Key-->" + entry.getKey() + ", Value-->" + entry.getValue());
}
//entrySet 遍历
for (Map.Entry<String, Integer> entry: entrySet){
System.out.println("返回Map中所有键值对的Set集合Key-->" + entry.getKey() + ", Value-->" + entry.getValue());
}
for (Map.Entry<String,Integer> entry : map.entrySet()){
System.out.println("返回Map中所有键值对的Set集合Key-->" + entry.getKey() + ", Value-->" + entry.getValue());
}
另外,toArray()方法就是一坨屎
6. HashMap/HashSet存储原理
java
HashMap
1. 先拿到key,计算出对应的hash值
2. 在hashTable(维护了一个表,key是hash值,value是统一的值PRESENT)
找到对应的索引位置,然后在这个索引位置(桶)放置键值对
3. 如果有冲突,会使用红黑树/链表把value保存起来
HashSet差不多,就是Value存储了默认的PRESENT
7. 哪些集合是线程安全的
1. Vector 比ArrayList多了线程安全
2. HashTable 比HashMap多了线程安全
3. Stack
4. enumeration:枚举,相当于迭代器。