Java Map.entry案例详解

网友投稿 386 2022-10-05


Java Map.entry案例详解

Map.entrySet(MJpNT) 这个方法返回的是一个Set>,Map.Entry 是Map中的一个接口,他的用途是表示一个映射项(里面有Key和Value),而Set>表示一个映射项的Set。Map.Entry里有相应的getKey和getValue方法,即javaBean,让我们能够从一个项中取出Key和Value。

下面是遍历Map的四种方法:

public static void main(String[] args) {

Map map = new HashMap();

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> it = map.entrySet().iterator();

while (it.hasNext()) {

Map.Entry entry = it.next();

System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());

}

//第三种:推荐,尤其是容量大时

System.out.println("通过Map.entrySet遍历key和value");

for (Map.Entry 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);

}

}

下面是HashMap的源代码:

首先HashMap的底层实现用的时候一个Entry数组

/**

* The table, resized as necessary. Length MUST Always be a power of two.

*/

transient Entry[] table; //声明了一个数组

........

public HashMap() {

this.loadFactor = DEFAULT_LOAD_FACTOR;

threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);

table = new Entry[DEFAULT_INITIAL_CAPACITY];//初始化数组的大小为DEFAULT_INITIAL_CAPACITY(这里是16)

init();

}

static class Entry implements Map.Entry {

final K key;

V value;

Entry next;

final int hash;

/**

* Creates new entry.

*/

Entry(int h, K k, V v, Entry 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 m) {

}

/**

* This method is invoked whenever the entry is

* removed from the table.

*/

void recordRemoval(HashMap m) {

}

}

既然这样那我们再看一下Map.Entry这个接口是怎么定义的,原来他是Map的一个内部接口并且定义了一些方法

interface Entry {

/**

* 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

* remove 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 remove operation).

*

* @param value new value to be stored in this entry

* @return old value corresponding to the entry

* @throws UnsupportedOperationException if the put 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 true if the given object is also a map entry and

* the two entries represent the same mapping. More formally, two

* entries e1 and represent the same mapping

* if

* (e1.getKey()==null ?

* e2.getKey()==null : e1.getKey().equals(e2.getKey())) &&

* (e1.getValue()==null ?

* e2.getValue()==null : e1.getValue().equals(e2.getValue()))

*

MJpNT * This ensures that the equals method works properly across

* different implementations of the Map.Entry interface.

*

* @param o object to be compared for equality with this map entry

* @return true 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 e is defined to be:

* (e.getKey()==null ? 0 : e.getKey().hashCode()) ^

* (e.getValue()==null ? 0 : e.getValue().hashCode())

*

* This ensures that e1.equals(e2) implies that

* e1.hashCode()==e2.hashCode() for any two Entries

* e1 and e2, as required by the general

* contract of Object.hashCode.

*

* @return the hash code value for this map entry

* @see Object#hashCode()

* @see Object#equals(Object)

* @see #equals(Object)

*/

int hashCode();

}

看到这里的时候大伙儿估计都明白得差不多了为什么HashMap为什么要选择Entry数组来存放key-value对了吧,因为Entry实现的Map.Entry接口里面定义了getKey(),getValue(),setKey(),setValue()等方法相当于一个javaBean,对键值对进行了一个封装便于后面的操作,从这里我们其实也可以联想到不光是HashMap,譬如LinkedHashMap,TreeMap 等继承自map的容器存储key-value对都应该使用的是Entry只不过组织Entry的形式不一样,HashMap用的是数组加链表的形式,LinkedHashMap用的是链表的形式,TreeMap应该使用的二叉树的形式,不信的话上源码

LinkedHashMap:

/**

* The head of the doubly linked list.

*/

/定义了链头

private transient Entry header;

初始化链表的方法:

void init() {

header = new Entry(-1, null, null, null);

header.before = header.after = header;

}

TreeMap:

//定义根节点

private transient Entry root = null;

再看他的put方法,是不是很面熟(二叉排序树的插入操作)

public V put(K key, V value) {

Entry 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(key, value, null);

size = 1;

modCount++;

return null;

}

int cmp;

Entry 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 e = new Entry(key, value, parent);

if (cmp < 0)

parent.left = e;

else

parent.right = e;

fixAfterInsertion(e);

size++;

modCount++;

return null;

}

ok,明白了各种Map的底层存储key-value对的方式后,再来看看如何遍历map吧,这里用HashMap来演示吧

Map提供了一些常用方法,如keySet()、entrySet()等方法,keySet()方法返回值是Map中key值的集合;entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。

so,很容易写出如下的遍历代码

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有一个values方法,返回的是value的Collection集合。通过遍历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();


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:游戏行业频繁遭到DDoS攻击,游戏公司该如何立足?(ddos攻击游戏服务器)
下一篇:被 DDoS 漏洞 ping 的 HTTP/2
相关文章

 发表评论

暂时没有评论,来抢沙发吧~