Java源码阅读之HashMap 下

该博客围绕Java中HashMap展开,介绍了其克隆与序列化、迭代器的使用,还阐述了红黑树数据结构,这些内容有助于深入理解HashMap的源码和API。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java源码阅读之HashMap

克隆与序列化

// HashMap的克隆方法属于深拷贝,即克隆的对象和原对象之间没有任何联系
public Object clone(){
	HashMap<K,V> result;
	try{
		// 对result分配相同的内存空间,即相同的结构
		result = (HashMap<K,V>)super.clone();
	}catch(CloneNotSupportException e){
		// 抛出错误,但此处不应该出错,因为hashmap指定为Cloneable
		throw new InternalError(e);
	}
	// 重新初始化result,进行深拷贝
	result.reinitialize();
	result.putMapEntries(this, false);
	return result;
}

// 获取map的装载因子
final float loadFactor(){
	return loadFoctor;
}
// 获取map的当前容量
final int capacity(){
	return (table != null) ? table.length : (thershold > 0) ? thershold : DEFAULT_INITIAL_CAPACITY;
}

// 序列化对象,向流中写入对象
private void writeObject(java.io.ObjectOutputStream s) throws IOException{
	int buckets = capacity();
	// 写入loadfactor, thershold, 和其他继承属性
	s.defaultWriteObject();
	// 写入map的容量
	s.writeInt(bucktes);
	// 写入map中已有的键值对的数量
	s.writeInt(size);
	// 写入所有的键值对
	internalWriteEntries(s);
}

// 反序列化对象,从对象流中读出对象数据
private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException{	
	// 读取threshold,loadFactor等
	s.defaultReadObject();
	reinitialize();
	if(loadFactor < 0 || Float.isNaa(loadFactor)){
		throw new InvalidObjectException("Illegal load factor: " + loadFactor);
	}
	s.readInt(); // 读取map的容量
	int mappings = s.readInt(); // 读取map的大小,即元素个数
	if(mappings < 0){
		throw new InvalidObjectException("Illegal mapping counts: " + mappings);
	}else if(mappings > 0){
		float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
		float fc = (float) mappings / lf + 1.0f;
		int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ? DEFAUT_INITIAL_CAPACITY : (fc > MAXMIUM_CAPACITY) : MAXMIUM_CAPACITY : tableSizeFor(fc));
		float ft = (float) cap * lf;
		threshold = ((cap < MAXMIUM_CAPACITY && ft < MAXMIUM_CAPACITY) ? (int)ft : MAXMIUM_CAPACITY);
	
		Node<K,V>[] tab = (Node<K,V> [])new Node[cap];
		for(int i = 0; i < mappings; i++){
			K key = (K) s.readObject();
			V value = (V) s.readObject();
			putVal(hash(key), key, value, false, false);
		}
	}
	
}

void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException{
	Node<K,V>[] tab;
	if(size > 0 && (tab = table) != null){
		for(int i = 0 ; i < tab.length; i ++){
			for(Node<K,V> e = tab[i]; e != null; e = e.next){
				s.writeObject(e.key);
				s.writeObject(e.value);
			}
		}
	}
}

迭代器

abstract class HashIterator{
	Node<K,V> next;
	Node<K,V> current;
	int expectedModCount;
	int index;

	HashIterator(){
		expectedModCount = modCount;
		Node<K,V>[] t = table;
		current = next = null;
		index = 0;
		// 定位到第一个元素
		do {} while(index < t.length && next=t[index++] != null);
	}
	public final boolean hasNext(){
		return next != null;
	}
	
	final Node<K,V> nextNode(){
		Node<K,V> t;
		Node<K,V> e = next;
		if(modCount != expectedModCount){
			throw new ConcurrentComodificationException();
		}
		if(next == null){
			throw new NoSuchElementException();
		}
		if((next = (current = e).next) == null && (t = table) != null){
			do {} while(index < t.length && (next = t[index ++]) != null);
		}
		return e;
	} 

	public final void remove(){
		Node<K,V> p = current;
		if(p == null){
			throw new IllegalStateException();
		}
		if(modCount != expectedModCount){
			throw new ConrrentComodificationException();
		}
		current = null;
		K key = p.key;
		removeNode(hash(key), key, null, false, false);
		expectedModCount = modCount;
	}
}

static class HashMapSpliterator<K,V>{
	final HashMap<K,V> map;
	Node<K,V> current;
	int index;
	int fence;
	int est;
	int expectedModCount;

	HashMapSpliterator(HashMap<K,V> m, int origin, int fence, int est, int expectedModCount){
		this.map = m;
		this.index = origin;
		this.fence = fence;
		this.est = est;
		this.expectedModCount = expectedModCount;
	}
	
	final int getFence(){
		int hi;
		if((hi = fence) < 0){
			HashMap<K,V> m = map;
			est = m.size();
			expectedModCount = m.modCount;
			Node<K,V>[] tab = m.table;
			hi = fence = (tab == null) ? 0 : tab.length;
		}
		return hi;
	}
	
	public final long estimateSize(){
		getFence();
		return (long)est;
	}
}

红黑数数据结构

static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V>{
	TreeNode<K,V> parent;
	TreeNode<K,V> left;
	TreeNode<K,V> right;
	TreeNode<K,V> prev;
	boolean red;

	TreeNode(int hash, K key, V value, Node<K,V> next){
		super(hash, key, value, next);
	}

	// 返回包含当前节点的红黑的根节点
	final TreeNode<K,V> root(){
		for(TreeNode<K,V> r = this, p;;){
			if((p = r.parent) == null){
				return r;
			}
			r = p;
		}
	}
	
	// 因为在删除或者插入的过程中,会导致当前根节点并不是第一个节点,需要将根节点移到开头处
	static <K,V> void moveRootToFront(Node<K,V>[] tab, TreeNode<K,V> root){
		int n;
		if(root != null && tab != null && (n = tab.length) > 0){
			int index = (n - 1) & root.hash;
			TreeNode<K,V> first = (TreeNode<K,V>)tab[index];
			if(root != first){
				Node<K,V> rn; // 当前根节点的后继节点
				tab[index] = root; // 让当前第一个几点指向根节点
				TreeNode<K,V> rp = root.prev; // 根节点的前一个节点
				if((rn = root.next) != null){
					((TreeNode<K,V>)rn).prev = rp;
				}
				if(rp != null){
					rp.next = rn;
				}
				if(first != null){
					first.prev = root;
				}
				root.next = first;
				root.prev = null;
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值