`
Lyishuai
  • 浏览: 33593 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

HashTable扩展:一个键对应多个值

阅读更多
基于有时候想存储一对多的数据结构的需求,自己写了个类来存储。

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();
		}
	}

}
0
0
分享到:
评论

相关推荐

    javascript hashtable 修正版 下载

    - hashtable构造函数初始化时定义了多个方法,如`clear`、`containsKey`、`containsValue`、`get`、`isEmpty`、`keys`、`put`、`remove`、`size`、`toString`、`values`、`set`、`valueOf`、`clone`等,这些方法...

    HashTable:C语言哈希表

    在C语言中,哈希表通常由两部分组成:一个数组和一个指向链表的指针数组。数组的大小是根据负载因子(已存元素数量与总容量的比例)动态调整的。链表用于存储哈希冲突的元素,每个链表节点包含键、值以及指向下一个...

    浅谈Java web中基于Hashtable的数据库操作.zip

    首先,理解Hashtable是Java中的一个同步容器类,它继承自Dictionary类,实现了Map接口。Hashtable存储键值对,不允许存储null键和null值,且具有线程安全的特性。在Web应用中,开发者可以利用Hashtable存储和管理...

    Hashtable和HashMap区别

    当一个`HashMap`的键为null时,其对应的值可以通过`get(null)`方法获取,如果`HashMap`中不存在该键,则返回null。 #### 4. 方法差异 `Hashtable`提供了`contains()`、`containsValue()`和`containsKey()`等方法,...

    利用C语言实现HashTable

    哈希节点(hashnode)包含了指向下一个节点的指针`next`,键`key`和值`val`。当键冲突时,这些节点将链接成链表。哈希表(hashtable)结构包括内存池`p`,用于管理内存分配,大小`size`,表示哈希表的节点数量,...

    asp.net Hashtable 遍历写法

    在处理大量数据或者需要通过键来访问数据时,`Hashtable`是一个很好的选择。现在我们来详细探讨`Hashtable`的遍历方法以及在给定的描述中提供的代码段。 首先,`Hashtable`中的元素没有特定的顺序,但我们可以使用...

    PHP内核介绍及扩展开发指南.pdf

    当多个变量共享同一个`zval`时,其`refcount`值会相应增加。当不再需要某个`zval`时,其`refcount`值会被递减,直到为零,此时`zval`将被释放。 ##### 1.1.3 zval状态 `zval`的状态主要由`is_ref`字段控制。在PHP...

    Java常用数据结构及类.docx

    键是唯一的,每个键对应一个值,但一个值可以对应多个键。 构造函数和常用方法包括: - `public Hashtable()`:创建一个空的Hashtable。 - `public Hashtable(int initialCapacity)`:创建一个初始容量为...

    asp.net 实现自定义Hashtable (.net)

    这种设计允许存储多个值与一个键相关联,而标准的`Hashtable`只允许存储一个值。如果需要存储更多的值,可以通过增加更多的字段和相应的属性来扩展`typeFiles`类。 `WEHash`类是自定义`Hashtable`的主体,它继承自`...

    PHP内核介绍及扩展开发指南

    `HashTable`由一系列的`Bucket`组成,每个`Bucket`包含一个键和一个`zval`指针,指向存储的实际数据。为了提高查找效率,`HashTable`使用了链地址法来处理哈希冲突。 **1.2.2 PHP数组** PHP数组本质上是一个`...

    深入PHP中的HashTable结构详解

    HashTable 结构由多个组件组成,包括 Bucket(桶)结构和 HashTable 结构。Bucket 是实际存储键值对的单元,包含以下几个关键字段: 1. `ulong h`:存储计算出的哈希值,用于快速查找。 2. `uint nKeyLength`:键的...

    PHP内核介绍及扩展开发指南—基础知识.pdf

    哈希表的关键在于通过哈希函数将key映射到一个索引,然后在bucket数组中找到对应的bucket来存储或检索值。PHP使用链地址法解决哈希冲突,即一个索引位置可以存储多个bucket。当进行哈希计算时,会考虑nTableMask来...

    数组,链表和哈希表(Hashtable)1

    哈希表通过哈希函数将元素的键(key)转换为数组的下标,使得数据存储在一个数组中,但下标不是直接由元素的位置决定,而是由键的哈希值决定。这种方法允许我们快速查找、插入和删除元素,理想情况下,其时间复杂度...

    2012年9月份上海地区J2EE面试题集(附答案)

    - `HashMap` 允许一个键为 `null` 和一个值为 `null`,而 `Hashtable` 不允许键或值为 `null`。 - `Hashtable` 的实现更老,而 `HashMap` 在 `Java 1.2` 版本中引入,提供了更多的灵活性。 #### 4. forward和...

    20道常见的 Java 面试题目以及对应的解析

    一个类可以实现多个接口,但只能继承一个抽象类。接口强调“是什么”,抽象类强调“怎么做”。 7. 异常处理:Java 通过 try-catch-finally 结构处理异常,try 块内捕获异常,catch 块处理异常,finally 块确保资源...

    编写 PHP Extension.doc

    HashTable 由多个 bucket 组成,每个 bucket 包含一个链表,链表中的元素是 `Bucket` 结构,包含了键和对应的 `zval`。 #### PHP 数组 PHP 数组实际上是一个 HashTable,可以存储不同类型的元素。数组的键可以是...

    2021-2022计算机二级等级考试试题及答案No.923.docx

    16. 完整计算机系统:一个完整的计算机系统由硬件系统(包括CPU、内存、硬盘等)和软件系统(操作系统、应用程序等)两部分组成。 17. JSP 导入包:在 JSP 中,使用 *" %&gt; 指令可以导入 java.io 包下的所有类。 18...

    哈希表的实现

    一个好的哈希函数应该尽可能使得不同键的哈希值分布均匀,以减少冲突的可能性。例如,对于字符串键,可以采用取模运算或者基于字符的ASCII码进行计算。 2. **数组**:哈希表的基础数据结构,用于存储键值对。数组的...

    用C语言实现一个简单的哈希表(hash table)

    - 链地址法是为每个数组元素创建一个链表,当新键映射到已有的键的位置时,将新键添加到对应链表的末尾。查找时,先计算键的哈希值,然后遍历对应链表找到目标键。 4. **C语言实现**: - 使用结构体定义哈希表,...

Global site tag (gtag.js) - Google Analytics