Java框架 Map简单实现

简述:

LinkedMap<K, V> implements Map<K, V>

以链表的的形式实现键值对的存储,
存储 键 - 值 对的数据结构, Node<K, V>

	static class Node<K, V> implements Map.Entry<K, V>, Serializable {
		
		K key;
		V value;
		Node<K, V> next;
}

Map接口

Map接口方法介绍

实现代码:

代码参考了 jdk1.8 LinkedList 的实现;
对于 LinkedList的实现感兴趣的请看这篇博客LinkedList源码浅析

/**
 * <p> 以单链表的形式实现(键-值)对
 * <p> put 的时间规模为 O(1), get remove set 的时间规模的最坏时为 O(n)
 * <p> 这个链表不支持 往后遍历, 不同于hash 表的是它不需要扩容也没有容量的限制,内存利用率非常高而且省内存.在内存紧缺的情况下非常有好处.
 * <p> 
 * @author chenyq
 * @date 2019-01-01
 * @email 806512500@qq.com
 * 
 * @param <K>
 * @param <V>
 */
public class LinkedMap<K, V> implements Map<K, V>, Cloneable, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 8623363011603830634L;
	
	/**
	 * 头节点
	 */
	Node<K, V> first;
	/**
	 * 尾节点, 尾节点必须符合 (next == null)
	 */
	Node<K, V> last;
	/**
	 * 映射表的数量
	 */
	int size;
	/**
	 * 映射的结构被修改过的计数器
	 */
	int modCount;
	/**
	 * Node 键-值 对 的视图
	 */
	Set<Entry<K, V>> entrySet;
	/**
	 * key 键的视图
	 */
	Set<K> keySet;
	/**
	 * value 值的视图
	 */
	Collection<V> values;
	
	public LinkedMap() {
		
	}
	
	public LinkedMap(Map<K, V> m) {
		putAll(m);
	}
	
	@Override
	public int size() {
		return size;
	}

	@Override
	public boolean isEmpty() {
		return size == 0;
	}

	@Override
	public boolean containsKey(Object key) {
		return get(key) != null;
	}

	@Override
	public boolean containsValue(Object value) {
		Node<K, V> f = first;
		while(f != null) {
			if(f.getValue().equals(value))
				return true;
			f = f.next;
		}
		return false;
	}

	@Override
	public V get(Object key) {
		Node<K, V> n;
		return (n= node(key)) == null ? null : n.getValue();
	}

	@Override
	public V put(K key, V value) {
		if (key == null || value == null) {
			throw new NullPointerException();
		}
		return add(key, value);
	}
	
	V add(K k, V v) {
		Node<K, V> n = node(k);
		if (n != null) {
			return n.setValue(v);
		}
		modCount++;
		linklast(new Node<>(k, v));
		return null;
	}
	
	Node<K, V> node(Object key) {
		Node<K, V> node = first;
		while (node != null) {
			K k = node.getKey();
			if(key == k || (key != null && key.equals(k))) {
				return node;
			}
			node = node.next;
		}
		return null;
	}
	
	void linklast(Node<K, V> n) {
		Node<K, V> l = last;
		last = n;
		
		if (first == null) {
			first = n;
		} else {
			l.next = n;
		}
		size++;
	}

	@Override
	public V remove(Object key) {
		Node<K, V> n;
		return (n = unlink(key)) == null ? null : n.getValue();
	}
	
	Node<K, V> unlink(Object key) {
		Node<K, V> prev = first;
		Node<K, V> e = prev;
		while(e != null) {
			Node<K, V> next = e.next;
			K k;
			if ((k = e.getKey()) == key || (k != null && k.equals(key))) {
				size--;
				modCount++;
				if (e == first) {
					first = next;
				} else {
					prev.next = next;
				}
				return e;
			}
			prev = e;
			e = next;
		}
		
		return e;
	}

	@Override
	public void putAll(Map<? extends K, ? extends V> m) {
		if (m == null) {
			throw new NullPointerException();
		}
		modCount++;
		for(Entry<? extends K, ? extends V> entry : m.entrySet()) {
			add(entry.getKey(), entry.getValue());
		}
	}

	@Override
	public void clear() {
		Node<K, V> n, f = first;
		first = null;
		last = null;
		while(f != null) {
			n = f.next;
			f.next = null;
			f = n;
		}
		size = 0;
		modCount++;
	}

	@Override
	public Set<K> keySet() {
		return keySet == null ? (keySet =  new KeySet()) : keySet;
	}
	
	/**
	 * 这是一个只支持包含返回所有 key 的迭代器的Set视图
	 */
	class KeySet extends AbstractSet<K> {

		@Override
		public Iterator<K> iterator() {
			return new KeySetIterator();
		}

		@Override
		public int size() {
			return size;
		}
		
	}

	@Override
	public Collection<V> values() {
		return values == null ? (values = new ValueCollection()) : values;
	}
	/**
	 * 返回所有 value 的collection 的视图
	 */
	class ValueCollection extends AbstractCollection<V> {

		@Override
		public Iterator<V> iterator() {
			return new ValueSetIterator();
		}

		@Override
		public int size() {
			return size;
		}
		
	}

	@Override
	public Set<Entry<K, V>> entrySet() {
		return entrySet == null ? (entrySet = new EntrySet()) : entrySet;
	}
	/**
	 * 返回包含所有 键值对的Set 集合视图
	 *
	 */
	class EntrySet extends AbstractSet<Entry<K, V>> {

		@Override
		public Iterator<Entry<K, V>> iterator() {
			return new EntrySetIterator();
		}

		@Override
		public int size() {
			return LinkedMap.this.size;
		}

		@Override
		public String toString() {
			return "EntrySet []";
		}
	}
	
	
	@Override
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}

	/**
	 * 
	 * 这是一个迭代器, 
	 * @param <E>
	 */
	abstract class LinkedIterator<E> implements Iterator<E> {
		/**
		 * 下一个元素的所引
		 */
		int index;
		/**
		 * 下一个元素的指针
		 */
		Node<K, V> next;
		/**
		 * 并发修改的计数器
		 */
		int expectedModCount;
		
		Node<K, V> current;
		
		public LinkedIterator() {
			expectedModCount = modCount;
			next = first;
		}
		
		@Override
		public boolean hasNext() {
			return index < size;
		}

		Entry<K, V> nextEntry() {
			checkModCount();
			if (next == null) {
				throw new NoSuchElementException();
			}
			current = next;
			next = next.next;
			index++;
			return current;
		}
		
		void checkModCount() {
			if (expectedModCount != modCount) {
				throw new ConcurrentModificationException();
			}
		}
		
		@Override
		public void remove() {
			checkModCount();
			LinkedMap.this.unlink(current.key);
			expectedModCount = modCount;
			index--;
		}
	}

	class EntrySetIterator extends LinkedIterator<Entry<K, V>> {

		@Override
		public Entry<K, V> next() {
			return nextEntry();
		}
	}
	class KeySetIterator extends LinkedIterator<K> {
		
		@Override
		public K next() {
			return nextEntry().getKey();
		}
		
	}
	class ValueSetIterator extends LinkedIterator<V> {
		
		@Override
		public V next() {
			return nextEntry().getValue();
		}
		
	}
	
	
	@Override
	public String toString() {
		if (size == 0) {
			return "[]";
		}
		StringBuilder sb = new StringBuilder();
		Node<K, V> n = first;
		do {
			sb.append(n.getKey()).append('=').append(n.getValue()).append(',').append(' ');
		} while ((n = n.next) != null);
		int len = sb.length();
		
		return sb.delete(len - 2, len).append(']').toString();
	}



	/**
	 * 
	 * 这个是用于存储键值对的节点, 即链表.是单链表, 只能往前迭代.
	 * @param <K>
	 * @param <V>
	 */
	static class Node<K, V> implements Map.Entry<K, V>, Serializable {

		/**
		 * 
		 */
		private static final long serialVersionUID = 8356467749770808672L;
		
		K key;
		V value;
		Node<K, V> next;
		
		public Node(K key, V value) {
			this.key = key;
			this.value = value;
		}

		@Override
		public K getKey() {
			return key;
		}

		@Override
		public V getValue() {
			return value;
		}

		@Override
		public V setValue(V value) {
			V oldValue = value;
			this.value = value;
			return oldValue;
		}

		@Override
		public String toString() {
			return key + "=" + value;
		}
		
		
	}
}

测试代码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: Java集合框架中的Map是一种键值对的数据结构,可以存储一组具有唯一键和对应值的元素。使用泛型可以在编译时进行类型检查,确保集合中只能存储指定类型的元素,提高代码的可读性和安全性。 在引用中的示例代码中,List<String>定义了一个只能存储字符串类型元素的列表。在引用中的示例代码中,Collection<String>和Collection<Integer>分别定义了只能存储字符串类型和整数类型元素的集合。使用泛型通配符可以增加集合的灵活性。比如在coll.removeAll(c)方法中,传入的Collection对象的泛型可以是任意类型。另外,泛型还可以应用于Map集合,如引用中的示例代码中,Set<Map.Entry<String,String>>定义了只能存储键值对类型为String的元素的集合。 综上所述,Java集合框架中的Map和泛型可以一起使用,通过泛型可以指定集合中存储的元素类型,增加代码的可读性和类型安全性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [java基础中的--------Map+泛型](https://blog.csdn.net/liutaiwu/article/details/107915445)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值