基于有时候想存储一对多的数据结构的需求,自己写了个类来存储。
package javax.util.collection.collections;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 此类是用来存储键值对数据的,但一个键可以映射多个值。
*
* @author Administrator
*/
public class O2NMap<K, V> implements Map<K, V> {
private Map<Key<K>, V> myMap;
public O2NMap() {
myMap = new Hashtable<Key<K>, V>();
}
public O2NMap(int initialCapacity) {
myMap = new Hashtable<Key<K>, V>(initialCapacity);
}
public O2NMap(int initialCapacity, float loadFactor) {
myMap = new Hashtable<Key<K>, V>(initialCapacity, loadFactor);
}
public O2NMap(Map<? extends Key<K>, ? extends V> t) {
myMap = new Hashtable<Key<K>, V>(t);
}
@Override
public synchronized void clear() {
myMap.clear();
}
@Override
public synchronized boolean containsKey(Object key) {
for (K k : keySet()) {
if (k == key || k.equals(key)) {
return true;
}
}
return false;
}
@Override
public boolean containsValue(Object value) {
if (value == null)
throw new NullPointerException();
for (V v : values()) {
if (v == value || v.equals(value)) {
return true;
}
}
return false;
}
@Override
public synchronized Set<java.util.Map.Entry<K, V>> entrySet() {
Set<Entry<K, V>> entrySets = new HashSet<Entry<K, V>>();
Set<Entry<Key<K>, V>> entrySet = myMap.entrySet();
for (Iterator<Entry<Key<K>, V>> it = entrySet.iterator(); it.hasNext();) {
Entry<Key<K>, V> entry = it.next();
Key<K> key = entry.getKey();
V value = entry.getValue();
entrySets.add(new MyEntry(key.value(), value));
}
return entrySets;
}
@Deprecated
@Override
public synchronized V get(Object key) {
List<V> vList = new ArrayList<V>();
Set<Entry<K, V>> entrySet = entrySet();
for (Entry<K, V> entry : entrySet) {
K k = entry.getKey();
if (k == key || k.equals(key)) {
vList.add(entry.getValue());
}
}
return vList.size() == 1 ? vList.get(0) : vList.get(vList.size() - 1);
}
public synchronized List<V> getAll(Object key) {
List<V> vList = new ArrayList<V>();
Set<Entry<K, V>> entrySet = entrySet();
for (Entry<K, V> entry : entrySet) {
K k = entry.getKey();
if (k == key || k.equals(key)) {
vList.add(entry.getValue());
}
}
return vList;
}
@Override
public synchronized boolean isEmpty() {
return size() == 0;
}
@Override
public synchronized Set<K> keySet() {
Set<K> kSet = new HashSet<K>();
Set<Key<K>> keySet = myMap.keySet();
for (Iterator<Key<K>> it = keySet.iterator(); it.hasNext();) {
Key<K> key = it.next();
kSet.add(key.value());
}
return kSet;
}
@Override
public synchronized V put(K key, V value) {
if (value == null)
throw new NullPointerException();
Set<Entry<K, V>> set = entrySet();
if (set.size() == 0) {
myMap.put(new Key<K>(key), value);
} else {
boolean isExisted = false;
for (Entry<K, V> entry : set) {
K k = entry.getKey();
V v = entry.getValue();
if ((k == key || k.equals(key))
&& (v == value || v.equals(value)))
isExisted = true;
}
if (!isExisted)
myMap.put(new Key<K>(key), value);
}
return value;
}
@Override
public synchronized void putAll(Map<? extends K, ? extends V> m) {
for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override
public synchronized V remove(Object key) {
Map<Key<K>, V> temp = new Hashtable<Key<K>, V>();
V v = null;
Set<Entry<K, V>> set = entrySet();
for (Entry<K, V> entry : set) {
if (entry != null) {
K k = entry.getKey();
if ((k == key) || (k.equals(key))) {
v = entry.getValue();
} else {
temp.put(new Key<K>(k), entry.getValue());
}
}
}
myMap = temp;
return v;
}
@Override
public synchronized int size() {
return myMap.size();
}
@Override
public synchronized Collection<V> values() {
Collection<V> collection = new ArrayList<V>();
for (Entry<K, V> entry : entrySet()) {
collection.add(entry.getValue());
}
return collection;
}
/**
* Map.Entry接口的实现类
*
* @author Administrator
*
*/
private class MyEntry implements Map.Entry<K, V> {
private K k;
private V v;
public MyEntry(K k, V v) {
this.k = k;
this.v = v;
}
@Override
public K getKey() {
return k;
}
@Override
public V getValue() {
return v;
}
@Override
public V setValue(V value) {
if (value == null)
throw new NullPointerException();
V oldValue = this.v;
this.v = value;
return oldValue;
}
}
/**
* 用Key类代替泛型中的K
*
* @author Administrator
*
* @param <K>
*/
private class Key<K> implements Serializable {
private static final long serialVersionUID = 1753979936226694189L;
private K value;
public K value() {
return value;
}
public Key(K value) {
this.value = value;
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
if (obj instanceof Key) {
Key<K> k = (Key<K>) obj;
if (value.equals(k.value())) {
return true;
}
}
return false;
}
@Override
public String toString() {
return value.toString();
}
}
}
分享到:
相关推荐
- hashtable构造函数初始化时定义了多个方法,如`clear`、`containsKey`、`containsValue`、`get`、`isEmpty`、`keys`、`put`、`remove`、`size`、`toString`、`values`、`set`、`valueOf`、`clone`等,这些方法...
在C语言中,哈希表通常由两部分组成:一个数组和一个指向链表的指针数组。数组的大小是根据负载因子(已存元素数量与总容量的比例)动态调整的。链表用于存储哈希冲突的元素,每个链表节点包含键、值以及指向下一个...
首先,理解Hashtable是Java中的一个同步容器类,它继承自Dictionary类,实现了Map接口。Hashtable存储键值对,不允许存储null键和null值,且具有线程安全的特性。在Web应用中,开发者可以利用Hashtable存储和管理...
当一个`HashMap`的键为null时,其对应的值可以通过`get(null)`方法获取,如果`HashMap`中不存在该键,则返回null。 #### 4. 方法差异 `Hashtable`提供了`contains()`、`containsValue()`和`containsKey()`等方法,...
哈希节点(hashnode)包含了指向下一个节点的指针`next`,键`key`和值`val`。当键冲突时,这些节点将链接成链表。哈希表(hashtable)结构包括内存池`p`,用于管理内存分配,大小`size`,表示哈希表的节点数量,...
在处理大量数据或者需要通过键来访问数据时,`Hashtable`是一个很好的选择。现在我们来详细探讨`Hashtable`的遍历方法以及在给定的描述中提供的代码段。 首先,`Hashtable`中的元素没有特定的顺序,但我们可以使用...
当多个变量共享同一个`zval`时,其`refcount`值会相应增加。当不再需要某个`zval`时,其`refcount`值会被递减,直到为零,此时`zval`将被释放。 ##### 1.1.3 zval状态 `zval`的状态主要由`is_ref`字段控制。在PHP...
键是唯一的,每个键对应一个值,但一个值可以对应多个键。 构造函数和常用方法包括: - `public Hashtable()`:创建一个空的Hashtable。 - `public Hashtable(int initialCapacity)`:创建一个初始容量为...
这种设计允许存储多个值与一个键相关联,而标准的`Hashtable`只允许存储一个值。如果需要存储更多的值,可以通过增加更多的字段和相应的属性来扩展`typeFiles`类。 `WEHash`类是自定义`Hashtable`的主体,它继承自`...
`HashTable`由一系列的`Bucket`组成,每个`Bucket`包含一个键和一个`zval`指针,指向存储的实际数据。为了提高查找效率,`HashTable`使用了链地址法来处理哈希冲突。 **1.2.2 PHP数组** PHP数组本质上是一个`...
HashTable 结构由多个组件组成,包括 Bucket(桶)结构和 HashTable 结构。Bucket 是实际存储键值对的单元,包含以下几个关键字段: 1. `ulong h`:存储计算出的哈希值,用于快速查找。 2. `uint nKeyLength`:键的...
哈希表的关键在于通过哈希函数将key映射到一个索引,然后在bucket数组中找到对应的bucket来存储或检索值。PHP使用链地址法解决哈希冲突,即一个索引位置可以存储多个bucket。当进行哈希计算时,会考虑nTableMask来...
哈希表通过哈希函数将元素的键(key)转换为数组的下标,使得数据存储在一个数组中,但下标不是直接由元素的位置决定,而是由键的哈希值决定。这种方法允许我们快速查找、插入和删除元素,理想情况下,其时间复杂度...
- `HashMap` 允许一个键为 `null` 和一个值为 `null`,而 `Hashtable` 不允许键或值为 `null`。 - `Hashtable` 的实现更老,而 `HashMap` 在 `Java 1.2` 版本中引入,提供了更多的灵活性。 #### 4. forward和...
一个类可以实现多个接口,但只能继承一个抽象类。接口强调“是什么”,抽象类强调“怎么做”。 7. 异常处理:Java 通过 try-catch-finally 结构处理异常,try 块内捕获异常,catch 块处理异常,finally 块确保资源...
HashTable 由多个 bucket 组成,每个 bucket 包含一个链表,链表中的元素是 `Bucket` 结构,包含了键和对应的 `zval`。 #### PHP 数组 PHP 数组实际上是一个 HashTable,可以存储不同类型的元素。数组的键可以是...
16. 完整计算机系统:一个完整的计算机系统由硬件系统(包括CPU、内存、硬盘等)和软件系统(操作系统、应用程序等)两部分组成。 17. JSP 导入包:在 JSP 中,使用 *" %> 指令可以导入 java.io 包下的所有类。 18...
一个好的哈希函数应该尽可能使得不同键的哈希值分布均匀,以减少冲突的可能性。例如,对于字符串键,可以采用取模运算或者基于字符的ASCII码进行计算。 2. **数组**:哈希表的基础数据结构,用于存储键值对。数组的...
- 链地址法是为每个数组元素创建一个链表,当新键映射到已有的键的位置时,将新键添加到对应链表的末尾。查找时,先计算键的哈希值,然后遍历对应链表找到目标键。 4. **C语言实现**: - 使用结构体定义哈希表,...