Java Map.entry案例詳解
Map.entrySet() 這個(gè)方法返回的是一個(gè)Set<Map.Entry<K,V>>,Map.Entry 是Map中的一個(gè)接口,他的用途是表示一個(gè)映射項(xiàng)(里面有Key和Value),而Set<Map.Entry<K,V>>表示一個(gè)映射項(xiàng)的Set。Map.Entry里有相應(yīng)的getKey和getValue方法,即JavaBean,讓我們能夠從一個(gè)項(xiàng)中取出Key和Value。
下面是遍歷Map的四種方法:
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("通過(guò)Map.keySet遍歷key和value:");
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
//第二種
System.out.println("通過(guò)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());
}
//第三種:推薦,尤其是容量大時(shí)
System.out.println("通過(guò)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("通過(guò)Map.values()遍歷所有的value,但不能遍歷key");
for (String v : map.values()) {
System.out.println("value= " + v);
}
}
下面是HashMap的源代碼:
首先HashMap的底層實(shí)現(xiàn)用的時(shí)候一個(gè)Entry數(shù)組
/**
* The table, resized as necessary. Length MUST Always be a power of two.
*/
transient Entry[] table; //聲明了一個(gè)數(shù)組
........
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
table = new Entry[DEFAULT_INITIAL_CAPACITY];//初始化數(shù)組的大小為DEFAULT_INITIAL_CAPACITY(這里是16)
init();
}
再來(lái)看一下Entry是在什么地方定義的,繼續(xù)上源碼,我們?cè)贖ashMap的源碼的674行發(fā)現(xiàn)了它的定義,原來(lái)他是HashMap的一個(gè)內(nèi)部類(lèi),并且實(shí)現(xiàn)了Map.Entry接口,以下有些地方是轉(zhuǎn)載
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
Entry<K,V> next;
final int hash;
/**
* Creates new entry.
*/
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
public final K getKey() {
return key;
}
public final V getValue() {
return value;
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry)o;
Object k1 = getKey();
Object k2 = e.getKey();
if (k1 == k2 || (k1 != null && k1.equals(k2))) {
Object v1 = getValue();
Object v2 = e.getValue();
if (v1 == v2 || (v1 != null && v1.equals(v2)))
return true;
}
return false;
}
public final int hashCode() {
return (key==null ? 0 : key.hashCode()) ^
(value==null ? 0 : value.hashCode());
}
public final String toString() {
return getKey() + "=" + getValue();
}
/**
* This method is invoked whenever the value in an entry is
* overwritten by an invocation of put(k,v) for a key k that's already
* in the HashMap.
*/
void recordAccess(HashMap<K,V> m) {
}
/**
* This method is invoked whenever the entry is
* removed from the table.
*/
void recordRemoval(HashMap<K,V> m) {
}
}
既然這樣那我們?cè)倏匆幌翸ap.Entry這個(gè)接口是怎么定義的,原來(lái)他是Map的一個(gè)內(nèi)部接口并且定義了一些方法
interface Entry<K,V> {
/**
* Returns the key corresponding to this entry.
*
* @return the key corresponding to this entry
* @throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
K getKey();
/**
* Returns the value corresponding to this entry. If the mapping
* has been removed from the backing map (by the iterator's
* <tt>remove</tt> operation), the results of this call are undefined.
*
* @return the value corresponding to this entry
* @throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
V getValue();
/**
* Replaces the value corresponding to this entry with the specified
* value (optional operation). (Writes through to the map.) The
* behavior of this call is undefined if the mapping has already been
* removed from the map (by the iterator's <tt>remove</tt> operation).
*
* @param value new value to be stored in this entry
* @return old value corresponding to the entry
* @throws UnsupportedOperationException if the <tt>put</tt> operation
* is not supported by the backing map
* @throws ClassCastException if the class of the specified value
* prevents it from being stored in the backing map
* @throws NullPointerException if the backing map does not permit
* null values, and the specified value is null
* @throws IllegalArgumentException if some property of this value
* prevents it from being stored in the backing map
* @throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
V setValue(V value);
/**
* Compares the specified object with this entry for equality.
* Returns <tt>true</tt> if the given object is also a map entry and
* the two entries represent the same mapping. More formally, two
* entries <tt>e1</tt> and <tt>e2</tt> represent the same mapping
* if<pre>
* (e1.getKey()==null ?
* e2.getKey()==null : e1.getKey().equals(e2.getKey())) &&
* (e1.getValue()==null ?
* e2.getValue()==null : e1.getValue().equals(e2.getValue()))
* </pre>
* This ensures that the <tt>equals</tt> method works properly across
* different implementations of the <tt>Map.Entry</tt> interface.
*
* @param o object to be compared for equality with this map entry
* @return <tt>true</tt> if the specified object is equal to this map
* entry
*/
boolean equals(Object o);
/**
* Returns the hash code value for this map entry. The hash code
* of a map entry <tt>e</tt> is defined to be: <pre>
* (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
* (e.getValue()==null ? 0 : e.getValue().hashCode())
* </pre>
* This ensures that <tt>e1.equals(e2)</tt> implies that
* <tt>e1.hashCode()==e2.hashCode()</tt> for any two Entries
* <tt>e1</tt> and <tt>e2</tt>, as required by the general
* contract of <tt>Object.hashCode</tt>.
*
* @return the hash code value for this map entry
* @see Object#hashCode()
* @see Object#equals(Object)
* @see #equals(Object)
*/
int hashCode();
}
看到這里的時(shí)候大伙兒估計(jì)都明白得差不多了為什么HashMap為什么要選擇Entry數(shù)組來(lái)存放key-value對(duì)了吧,因?yàn)镋ntry實(shí)現(xiàn)的Map.Entry接口里面定義了getKey(),getValue(),setKey(),setValue()等方法相當(dāng)于一個(gè)javaBean,對(duì)鍵值對(duì)進(jìn)行了一個(gè)封裝便于后面的操作,從這里我們其實(shí)也可以聯(lián)想到不光是HashMap,譬如LinkedHashMap,TreeMap 等繼承自map的容器存儲(chǔ)key-value對(duì)都應(yīng)該使用的是Entry只不過(guò)組織Entry的形式不一樣,HashMap用的是數(shù)組加鏈表的形式,LinkedHashMap用的是鏈表的形式,TreeMap應(yīng)該使用的二叉樹(shù)的形式,不信的話上源碼
LinkedHashMap:
/**
* The head of the doubly linked list.
*/
/定義了鏈頭
private transient Entry<K,V> header;
初始化鏈表的方法:
void init() {
header = new Entry<K,V>(-1, null, null, null);
header.before = header.after = header;
}
TreeMap:
//定義根節(jié)點(diǎn) private transient Entry<K,V> root = null;
再看他的put方法,是不是很面熟(二叉排序樹(shù)的插入操作)
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
// TBD:
// 5045147: (coll) Adding null to an empty TreeSet should
// throw NullPointerException
//
// compare(key, key); // type check
root = new Entry<K,V>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<K,V>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
ok,明白了各種Map的底層存儲(chǔ)key-value對(duì)的方式后,再來(lái)看看如何遍歷map吧,這里用HashMap來(lái)演示吧
Map提供了一些常用方法,如keySet()、entrySet()等方法,keySet()方法返回值是Map中key值的集合;entrySet()的返回值也是返回一個(gè)Set集合,此集合的類(lèi)型為Map.Entry。
so,很容易寫(xiě)出如下的遍歷代碼
1. Map map = new HashMap();
Irerator iterator = map.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry entry = iterator.next();
Object key = entry.getKey();
//
}
2.Map map = new HashMap();
Set keySet= map.keySet();
Irerator iterator = keySet.iterator;
while(iterator.hasNext()) {
Object key = iterator.next();
Object value = map.get(key);
//
}
另外,還有一種遍歷方法是,單純的遍歷value值,Map有一個(gè)values方法,返回的是value的Collection集合。通過(guò)遍歷collection也可以遍歷value,如
[java] view plain copy
Map map = new HashMap();
Collection c = map.values();
Iterator iterator = c.iterator();
while(iterator.hasNext()) {
Object value = iterator.next();
到此這篇關(guān)于Java Map.entry案例詳解的文章就介紹到這了,更多相關(guān)Java Map.entry內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java web實(shí)現(xiàn)郵箱激活與忘記密碼
這篇文章主要為大家詳細(xì)介紹了java web實(shí)現(xiàn)郵箱激活與忘記密碼、重置密碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02
Java Guava排序器Ordering原理及代碼實(shí)例
這篇文章主要介紹了Java Guava排序器Ordering原理及代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
Java實(shí)戰(zhàn)花店商城系統(tǒng)的實(shí)現(xiàn)流程
只學(xué)書(shū)上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+Springboot+Maven+mybatis+Vue+Mysql實(shí)現(xiàn)一個(gè)花店商城系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2022-01-01
Java實(shí)現(xiàn)一個(gè)小說(shuō)采集程序的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇Java實(shí)現(xiàn)一個(gè)小說(shuō)采集程序的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的, 現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06
簡(jiǎn)單實(shí)現(xiàn)Java版學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了簡(jiǎn)單實(shí)現(xiàn)Java版學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06
Java二維數(shù)組查找功能代碼實(shí)現(xiàn)
這篇文章主要介紹了Java二維數(shù)組查找功能代碼實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06

