java hashedmap,LearningJDK/PreHashedMap.java at master · clouse/LearningJDK · GitHub

/*

* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.

* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.

*

* This code is free software; you can redistribute it and/or modify it

* under the terms of the GNU General Public License version 2 only, as

* published by the Free Software Foundation. Oracle designates this

* particular file as subject to the "Classpath" exception as provided

* by Oracle in the LICENSE file that accompanied this code.

*

* This code is distributed in the hope that it will be useful, but WITHOUT

* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or

* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License

* version 2 for more details (a copy is included in the LICENSE file that

* accompanied this code).

*

* You should have received a copy of the GNU General Public License version

* 2 along with this work; if not, write to the Free Software Foundation,

* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.

*

* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA

* or visit www.oracle.com if you need additional information or have any

* questions.

*/

package sun.util;

import java.util.AbstractMap;

import java.util.AbstractSet;

import java.util.Iterator;

import java.util.Map;

import java.util.NoSuchElementException;

import java.util.Set;

/**

* A precomputed hash map.

*

*

Subclasses of this class are of the following form:

*

*

 
  

* class FooMap

* extends sun.util.PreHashedMap<String>

* {

*

* private FooMap() {

* super(ROWS, SIZE, SHIFT, MASK);

* }

*

* protected void init(Object[] ht) {

* ht[0] = new Object[] { "key-1", value_1 };

* ht[1] = new Object[] { "key-2", value_2, new Object { "key-3", value_3 } };

* ...

* }

*

* }

*

*

The {@codeinit} method is invoked by the {@codePreHashedMap}

* constructor with an object array long enough for the map's rows. The method

* must construct the hash chain for each row and store it in the appropriate

* element of the array.

*

*

Each entry in the map is represented by a unique hash-chain node. The

* final node of a hash chain is a two-element object array whose first element

* is the entry's key and whose second element is the entry's value. A

* non-final node of a hash chain is a three-element object array whose first

* two elements are the entry's key and value and whose third element is the

* next node in the chain.

*

*

Instances of this class are mutable and are not safe for concurrent

* access. They may be made immutable and thread-safe via the appropriate

* methods in the {@link java.util.Collections} utility class.

*

*

In the JDK build, subclasses of this class are typically created via the

* {@codeHasher} program in the {@codemake/tools/Hasher} directory.

*

* @author Mark Reinhold

* @see java.util.AbstractMap

* @since 1.5

*/

/*

* 特制的Map工具类,专为标准字符集类StandardCharsets打造。

*

* 该Map中的数据按行排列,每一行可能包含多个键值对。

* 同一行出现的键的哈希值是相同的,不在同一行的键的哈希值不同。

*

* 例如:

* 1 key1-value1

* 2 key2-value2, key3-value3, key4-value4

* 3 key5-value6, key5-value6

*

* 这6个键值对数据可以存储为:

* Object[] ht = new Object[4];

* ht[1] = new Object{key1, value1};

* ht[2] = new Object{key2, value2, new Object{key3, value3}, new Object{key4, value4}};

* ht[2] = new Object{key5, value5, new Object{key6, value6}};

*/

public abstract class PreHashedMap extends AbstractMap {

private final int rows; // 掩码

private final int size; // 键值对数量

private final int shift;

private final int mask; // 映射到行数的掩码

private final Object[] ht; // 包含了很多行的键值对数据,数组中每个元素是一行,每行可能包含多个键值对

/**

* Creates a new map.

*

*

This constructor invokes the {@link #init init} method, passing it a

* newly-constructed row array that is {@coderows} elements long.

*

* @param rows The number of rows in the map

* @param size The number of entries in the map

* @param shift The value by which hash codes are right-shifted

* @param mask The value with which hash codes are masked after being shifted

*/

protected PreHashedMap(int rows, int size, int shift, int mask) {

this.rows = rows;

this.size = size;

this.shift = shift;

this.mask = mask;

this.ht = new Object[rows];

init(ht);

}

/**

* Initializes this map.

*

*

This method must construct the map's hash chains and store them into

* the appropriate elements of the given hash-table row array.

*

* @param ht The row array to be initialized

*/

// 初始化Map,由子类实现

protected abstract void init(Object[] ht);

// 根据key返回value

public V get(Object k) {

// 先把key按照指定的规则哈希化

int h = (k.hashCode() >> shift) & mask;

// 根据键的哈希值返回整行数据

Object[] a = (Object[]) ht[h];

if(a == null)

return null;

for(; ; ) {

// key匹配,则返回value

if(a[0].equals(k))

return toV(a[1]);

if(a.length < 3)

return null;

// 尝试其他的可能

a = (Object[]) a[2];

}

}

/**

* @throws UnsupportedOperationException If the given key is not part of this map's initial key set

*/

// 设置键值对,并返回成功设置的value

public V put(String k, V v) {

// 先把key按照指定的规则哈希化

int h = (k.hashCode() >> shift) & mask;

Object[] a = (Object[]) ht[h];

if(a == null)

throw new UnsupportedOperationException(k);

for(; ; ) {

if(a[0].equals(k)) {

V ov = toV(a[1]);

a[1] = v;

return ov;

}

if(a.length < 3)

throw new UnsupportedOperationException(k);

a = (Object[]) a[2];

}

}

// 返回key的集合

public Set keySet() {

return new AbstractSet<>() {

public int size() {

return size;

}

public Iterator iterator() {

return new Iterator<>() {

Object[] a = null; // value

String cur = null; // key

private int i = -1;

// 是否还有下一个key

public boolean hasNext() {

if(cur != null)

return true;

return findNext();

}

// 反回下一个key

public String next() {

if(cur == null) {

if(!findNext())

throw new NoSuchElementException();

}

String s = cur;

cur = null;

return s;

}

public void remove() {

throw new UnsupportedOperationException();

}

// 按行遍历查找key

private boolean findNext() {

if(a != null) {

// 如果同一行存在多个键值对

if(a.length == 3) {

a = (Object[]) a[2];

cur = (String) a[0];

return true;

}

// 否则到下一行遍历

i++;

a = null;

}

cur = null;

if(i >= rows)

return false;

if(i < 0 || ht[i] == null) {

do {

if(++i >= rows)

return false;

} while(ht[i] == null);

}

a = (Object[]) ht[i];

cur = (String) a[0];

return true;

}

};

}

};

}

// 返回键值对实体的集合

public Set> entrySet() {

return new AbstractSet<>() {

public int size() {

return size;

}

public Iterator> iterator() {

return new Iterator<>() {

final Iterator i = keySet().iterator();

// 有没有entry取决于有没有key

public boolean hasNext() {

return i.hasNext();

}

public Map.Entry next() {

return new Map.Entry<>() {

String k = i.next();

public String getKey() {

return k;

}

public V getValue() {

return get(k);

}

public int hashCode() {

V v = get(k);

return (k.hashCode() + (v == null ? 0 : v.hashCode()));

}

public boolean equals(Object ob) {

if(ob == this)

return true;

if(!(ob instanceof Map.Entry))

return false;

Map.Entry, ?> that = (Map.Entry, ?>) ob;

return (this.getKey() == null ? that.getKey() == null : this.getKey().equals(that.getKey()))

&& (this.getValue() == null ? that.getValue() == null : this.getValue().equals(that.getValue()));

}

public V setValue(V v) {

throw new UnsupportedOperationException();

}

};

}

public void remove() {

throw new UnsupportedOperationException();

}

};

}

};

}

@SuppressWarnings("unchecked")

private V toV(Object x) {

return (V) x;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值