原创转载请注明出处:http://agilestyle.iteye.com/blog/1562357
Map的底层实现
数组+链表
Note:
HashSet底层也是用HashMap实现的
Map
映射(map)是一个存储关键字和值的关联或者说是关键字/值对的对象。给定一个关键字,可以得到它的值。关键字和值都是对象。关键字必须是唯一的。但值是可以重复的。有些映射可以接收null关键字和null值。而有的则不行。
Map接口映射唯一关键字到值。关键字(key)是以后用于检索值的对象。给定一个关键字和一个值,可以存储这个值到一个Map对象中。当这个值被存储以后,就可以使用它的关键字来检索它。当调用的映射中没有项存在时,其中的几种方法
会引发一个NoSuchElementException异常。而当对象与映射中的元素不兼容时,引发一个ClassCastException异常。如果试图使用映射不允许使用的null对象时,则引发一个NullPointerException异常。当试图改变一个不允许修改的映射时,则引发一个UnsupportedOperationException异常。
映射循环使用两个基本操作:get( )和put( )。使用put( )方法可以将一个指定了关键字和值的值加入映射。为了得到值,可以通过将关键字作为参数来调用get( )方法。调用返回该值。
MapTest01
package com.fairy.test;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapTest01 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("a", "aa");
map.put("b", "bb");
map.put("c", "cc");
map.put("d", "dd");
Set<String> set = map.keySet();
for (Iterator<String> iter = set.iterator(); iter.hasNext();) {
String key = iter.next();
String value = map.get(key);
System.out.println(key + "=" + value);
}
}
}
映射不是类集,但可以获得映射的类集“视图”。为了实现这种功能,可以使用entrySet( )方法,它返回一个包含了映射中元素的集合(Set)。为了得到关键字的类集“视图”,可以使用keySet( )方法。为了得到值的类集“视图”,可以使用
values( )方法。类集“视图”是将映射集成到类集框架内的手段。
Map.Entry接口使得可以操作映射的输入。回想由Map接口说明的entrySet( )方法,调用该方法返回一个包含映射输入的集合(Set)。这些集合元素的每一个都是一个Map.Entry对象。
MapTest02
package com.fairy.test;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MapTest02 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("a", "aa");
map.put("b", "bb");
map.put("c", "cc");
map.put("d", "dd");
Set<Entry<String, String>> set = map.entrySet();
System.out.println(set);
for (Iterator<Entry<String, String>> iter = set.iterator(); iter.hasNext();) {
Map.Entry<String, String> entry = iter.next();
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + ":" + value);
}
}
}
Hashtable和HashMap的区别
主要是两点,还有一些琐碎的细节自行查看src
- Hashtable线程安全;HashMap线程不安全
- Hashtable的key、value都不可以为null;HashMap的key、value都可以为null
HashMap、LinkedHashMap、TreeMap和PriorityQueue的区别
HashMap
HashMap里面存入的键值对在取出的时候是随机的,也是我们最常用的一个Map.它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。在Map 中插入、删除和定位元素,HashMap 是最好的选择。
LinkedHashMap
LinkedHashMap 是HashMap的一个子类,如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现. (应用场景:购物车等需要顺序的)
TreeMap
TreeMap是基于红黑二叉树的NavigableMap的实现,取出来的是排序后的键值对。但如果要按自然顺序或自定义顺序遍历键,那么TreeMap会更好
PriorityQueue
PriorityQueue只保证最高或者最低优先级的元素在头部,并且是无序
package org.fool.java.test;
import java.util.*;
public class Test {
public static void main(String[] args) {
Map<String, String> linkedMap = new LinkedHashMap<>();
linkedMap.put("e", "0");
linkedMap.put("d", "1");
linkedMap.put("c", "2");
linkedMap.put("b", "3");
linkedMap.put("a", "4");
Map<String, String> hashMap = new HashMap<>();
hashMap.put("e", "0");
hashMap.put("d", "1");
hashMap.put("c", "2");
hashMap.put("b", "3");
hashMap.put("a", "4");
Queue<Integer> queue = new PriorityQueue<>();
queue.add(6);
queue.add(7);
queue.add(8);
queue.add(9);
queue.add(1);
queue.add(2);
queue.add(3);
queue.add(4);
queue.add(5);
System.out.println("LinkedHashMap: " + linkedMap);
System.out.println("HashMap: " + hashMap);
System.out.println("PriorityQueue: " + queue);
}
}
Console Output
TreeMap排序
TreeMapTest.java
package org.fool.java.collections;
import java.util.*;
public class TreeMapTest {
public static void main(String[] args) {
// sort by key
Map<String, Integer> keyMap = new TreeMap<>(
(o1, o2) -> o2.compareTo(o1) // sort by key desc
);
keyMap.put("a", 22);
keyMap.put("b", 32);
keyMap.put("c", 12);
keyMap.put("d", 42);
System.out.println(keyMap); // {d=42, c=12, b=32, a=22}
// sort by value
Map<String, Integer> valueMap = new TreeMap<>();
valueMap.put("a", 22);
valueMap.put("b", 32);
valueMap.put("c", 12);
valueMap.put("d", 42);
List<Map.Entry<String, Integer>> list = new ArrayList<>(valueMap.entrySet());
Collections.sort(list, (o1, o2) -> o1.getValue().compareTo(o2.getValue())); // sort by value asc
Map<String, Integer> sortedMap = new LinkedHashMap<>();
for (Map.Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
System.out.println(sortedMap); // {c=12, a=22, b=32, d=42}
}
}
Note:
这个类加入了JDK8的Lambda特性来简化Comparator接口的编写
Console Output
使用JDK8的Stream特性重写TreeMap排序
package org.fool.java.collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Stream;
public class MapSortByGenericExample {
public static void main(String[] args) {
Map<String, Integer> unsortedMap = new HashMap<>();
unsortedMap.put("z", 10);
unsortedMap.put("b", 5);
unsortedMap.put("a", 6);
unsortedMap.put("c", 20);
unsortedMap.put("d", 1);
unsortedMap.put("e", 7);
unsortedMap.put("y", 8);
unsortedMap.put("n", 99);
unsortedMap.put("j", 50);
unsortedMap.put("m", 2);
unsortedMap.put("f", 9);
System.out.println("Original...");
System.out.println(unsortedMap);
System.out.println("Sort By Key...");
Map<String, Integer> resultKey = compareByKey(unsortedMap);
System.out.println(resultKey);
System.out.println("Sort By Value...");
Map<String, Integer> resultValue = compareByValue(unsortedMap);
System.out.println(resultValue);
}
public static <K, V extends Comparable<? super V>> Map<K, V> compareByValue(Map<K, V> map) {
Map<K, V> result = new LinkedHashMap<>();
Stream<Map.Entry<K, V>> mapInStream = map.entrySet().stream();
mapInStream.sorted(Map.Entry.comparingByValue())
.forEachOrdered(x -> result.put(x.getKey(), x.getValue()));
return result;
}
public static <K extends Comparable<? super K>, V> Map<K, V> compareByKey(Map<K, V> map) {
Map<K, V> result = new LinkedHashMap<>();
Stream<Map.Entry<K, V>> mapInStream = map.entrySet().stream();
mapInStream.sorted(Map.Entry.comparingByKey())
.forEachOrdered(x -> result.put(x.getKey(), x.getValue()));
return result;
}
}
Console Output
Reference
http://www.mkyong.com/java/how-to-sort-a-map-in-java/
http://www.mkyong.com/java8/java-8-how-to-sort-a-map/