若想了解底层请参考底层剖析的网址
一、Map
Map集合的特点:
将键映射到值的对象,一个映射不能包含重复的键,每个键只能映射一个值
Map集合的数据结构针对键有效,跟值无关
Collection集合的数据结构针对元素有效
Map和Collection的区别
Map存储的是键值对形式的元素,键唯一,只可以重复
Collection存储的是单独出现的元素,子接口Set元素唯一,子接口List元素可重复。
Map集合的遍历
a:键找值 (map.keySet())
b:键值对对象找键和值 (map.entrySet())
二、HashMap集合的练习
特点:无序、唯一
底层数据结构是哈希表:(数组加单链表)
利用hashCode()和equals()方法保证键的唯一性
利用头插法来加入hash值一样的Map.Entry实体
底层剖析
https://blog.csdn.net/wufaliang003/article/details/79997585
https://blog.csdn.net/P_Doraemon/article/details/80353579
三、LinkedHashMap集合
特点:有序、唯一
底层数据结构是哈希表(数组加单链表)+双向循环链表
使用尾插法来加入hash值一样的Entry实体
recordAccess()决定2种顺序 -- 看源码put
a:按访问进行排序 -- LRU算法 将旧的相同的键的Entry实体删除将get或者put访问的Entry实体添加到双向循环链表尾部(LRU算法)
package day22;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
public class Test {
public static void main(String[] args) {
LinkedHashMap linkedHashMap =new LinkedHashMap(16, 1.2f, true);
linkedHashMap.put("111", "111");
linkedHashMap.put("222", "222");
linkedHashMap.put("333", "333");
linkedHashMap.put("444", "444");
loopLinkedHashMap(linkedHashMap);
linkedHashMap.get("111");
loopLinkedHashMap(linkedHashMap);
linkedHashMap.put("222", "2222");
loopLinkedHashMap(linkedHashMap);
}
public static void loopLinkedHashMap(LinkedHashMap<String, String> linkedHashMap)
{
Set<Map.Entry<String, String>> set = linkedHashMap.entrySet();
Iterator<Map.Entry<String, String>> iterator = set.iterator();
while (iterator.hasNext())
{
System.out.print(iterator.next() + " ");
}
System.out.println();
}
}
结果显示
111=111 222=222 333=333 444=444
222=222 333=333 444=444 111=111
333=333 444=444 111=111 222=2222
b:按照插入顺序排序 -- 就是将相同的键的Entry实体替换或者若双向循环链表中没有相同的键的Entry,则将新的Entry实体添加到尾部(FIFO)
package day22;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
public class Test {
public static void main(String[] args) {
LinkedHashMap linkedHashMap =new LinkedHashMap(16, 1.2f, false);
linkedHashMap.put("111", "111");
linkedHashMap.put("222", "222");
linkedHashMap.put("333", "333");
linkedHashMap.put("444", "444");
loopLinkedHashMap(linkedHashMap);
linkedHashMap.get("111");
loopLinkedHashMap(linkedHashMap);
linkedHashMap.put("222", "2222");
loopLinkedHashMap(linkedHashMap);
}
public static void loopLinkedHashMap(LinkedHashMap<String, String> linkedHashMap)
{
Set<Map.Entry<String, String>> set = linkedHashMap.entrySet();
Iterator<Map.Entry<String, String>> iterator = set.iterator();
while (iterator.hasNext())
{
System.out.print(iterator.next() + " ");
}
System.out.println();
}
}
结果显示
111=111 222=222 333=333 444=444
111=111 222=222 333=333 444=444
111=111 222=2222 333=333 444=444
注意a和b的区别在于
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
if (lm.accessOrder) {
lm.modCount++;
remove();
addBefore(lm.header);
}
}
// 将原来相同键且值换了的Entry实体删除
private void remove() {
before.after = after;
after.before = before;
}
//在双向循环链表末尾添加相同键且值换了的Entry实体
private void addBefore(Entry<K,V> existingEntry) {
after = existingEntry;
before = existingEntry.before;
before.after = this;
after.before = this;
}
当Map的键相同时
若使用a方法lm.accessOrder == true
则会将原来相同键且值换了的Entry实体(也就是说将要删除的Entry和插入的Entry键值对相同)删除
在双向循环链表末尾添加和删除的Entry键值对一样的Entry实体
若使用b方法lm.accessOrder == false
直接在键相同的 Entry实体上替换原来的值
底层剖析
http://www.php.cn/java-article-362041.html (LinkedHashMap的访问顺序)
https://blog.csdn.net/alexdedream/article/details/84955245 (LinkedHashMap的存储顺序)
https://www.cnblogs.com/whgk/p/6169622.html
四、TreeMap集合
特点:排序、唯一
底层数据结构是红黑树(二叉排序树算法)
两种排序方式(看构造方法)
a:自然排序(comparable接口 -- compareto)
b:比较器排序(comparator -- compare ) -- 推荐用内部类
五、HashMap和Hashtable的区别
Hashtable:线程安全,效率低
不允许NULL值或者NULL键
HashMap:线程不安全,效率高
允许NULL值或者NULL键
六、Collections
(1)含义:针对集合进行操作的工具类
(2)面试题:Collection和Collections的区别
A:Collection 是单列集合的顶层接口,有两个子接口List和Set
B:Collections 是针对集合进行操作的工具类,可以对集合进行排序和查找等
(3)常见的几个小方法:
A:public static <T> void sort(List<T> list)
B:public static <T> int binarySearch(List<?> list,T key)
C:public static <T> T max(Collection<?> coll)
D:public static void reverse(List<?> list)
E:public static void shuffle(List<?> list)