Put nodes in a NodeStorage

This commit is contained in:
Gwilym Kuiper 2022-03-17 23:58:30 +00:00
parent 03f5cd0953
commit e999b44c67

View file

@ -33,10 +33,24 @@ where
} }
} }
struct NodeStorage<K, V>(Vec<Option<Node<K, V>>>);
impl<K, V> NodeStorage<K, V> {
fn with_size(capacity: usize) -> Self {
let next_power_of_2 = find_next_power_of_2(capacity);
Self(iter::repeat_with(|| None).take(next_power_of_2).collect())
}
fn len(&self) -> usize {
self.0.len()
}
}
pub struct HashMap<K, V> { pub struct HashMap<K, V> {
number_of_elements: usize, number_of_elements: usize,
max_distance_to_initial_bucket: u32, max_distance_to_initial_bucket: u32,
nodes: Vec<Option<Node<K, V>>>, nodes: NodeStorage<K, V>,
hasher: BuildHasherDefault<FxHasher>, hasher: BuildHasherDefault<FxHasher>,
} }
@ -47,12 +61,10 @@ impl<K, V> HashMap<K, V> {
} }
pub fn with_capacity(capacity: usize) -> Self { pub fn with_capacity(capacity: usize) -> Self {
let next_power_of_2 = find_next_power_of_2(capacity);
Self { Self {
number_of_elements: 0, number_of_elements: 0,
max_distance_to_initial_bucket: 0, max_distance_to_initial_bucket: 0,
nodes: iter::repeat_with(|| None).take(next_power_of_2).collect(), nodes: NodeStorage::with_size(capacity),
hasher: Default::default(), hasher: Default::default(),
} }
} }
@ -84,7 +96,7 @@ where
for distance_to_initial_bucket in 0..=self.max_distance_to_initial_bucket { for distance_to_initial_bucket in 0..=self.max_distance_to_initial_bucket {
let location = fast_mod(self.nodes.len(), hash + distance_to_initial_bucket); let location = fast_mod(self.nodes.len(), hash + distance_to_initial_bucket);
let node = &self.nodes[location]; let node = &self.nodes.0[location];
if let Some(node) = node { if let Some(node) = node {
if &node.key == key { if &node.key == key {
return Some(location); return Some(location);
@ -106,9 +118,9 @@ where
let hash = self.hash(&key); let hash = self.hash(&key);
if let Some(location) = self.get_location(&key, hash) { if let Some(location) = self.get_location(&key, hash) {
let old_node = self.nodes[location].take().unwrap(); let old_node = self.nodes.0[location].take().unwrap();
let (new_node, old_value) = old_node.with_new_key_value(key, value); let (new_node, old_value) = old_node.with_new_key_value(key, value);
self.nodes[location] = Some(new_node); self.nodes.0[location] = Some(new_node);
return Some(old_value); return Some(old_value);
} }
@ -121,7 +133,7 @@ where
let hash = self.hash(key); let hash = self.hash(key);
self.get_location(key, hash) self.get_location(key, hash)
.map(|location| &self.nodes[location].as_ref().unwrap().value) .map(|location| &self.nodes.0[location].as_ref().unwrap().value)
} }
pub fn remove(&mut self, key: &K) -> Option<V> { pub fn remove(&mut self, key: &K) -> Option<V> {
@ -159,7 +171,7 @@ impl<K, V> HashMap<K, V> {
loop { loop {
let location = fast_mod(self.nodes.len(), hash + new_node.distance_to_initial_bucket); let location = fast_mod(self.nodes.len(), hash + new_node.distance_to_initial_bucket);
let current_node = self.nodes[location].as_mut(); let current_node = self.nodes.0[location].as_mut();
if let Some(current_node) = current_node { if let Some(current_node) = current_node {
if current_node.distance_to_initial_bucket <= new_node.distance_to_initial_bucket { if current_node.distance_to_initial_bucket <= new_node.distance_to_initial_bucket {
@ -170,7 +182,7 @@ impl<K, V> HashMap<K, V> {
mem::swap(&mut new_node, current_node); mem::swap(&mut new_node, current_node);
} }
} else { } else {
self.nodes[location] = Some(new_node); self.nodes.0[location] = Some(new_node);
break; break;
} }
@ -187,12 +199,12 @@ impl<K, V> HashMap<K, V> {
let next_location = fast_mod(self.nodes.len(), (current_location + 1) as HashType); let next_location = fast_mod(self.nodes.len(), (current_location + 1) as HashType);
// if the next node is empty, then we can clear the current node // if the next node is empty, then we can clear the current node
if self.nodes[next_location].is_none() { if self.nodes.0[next_location].is_none() {
break self.nodes[current_location].take().unwrap(); break self.nodes.0[current_location].take().unwrap();
} }
self.nodes.swap(current_location, next_location); self.nodes.0.swap(current_location, next_location);
self.nodes[current_location] self.nodes.0[current_location]
.as_mut() .as_mut()
.unwrap() .unwrap()
.distance_to_initial_bucket -= 1; .distance_to_initial_bucket -= 1;
@ -218,7 +230,7 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
return None; return None;
} }
if let Some(node) = &self.map.nodes[self.at] { if let Some(node) = &self.map.nodes.0[self.at] {
self.at += 1; self.at += 1;
return Some((&node.key, &node.value)); return Some((&node.key, &node.value));
} }