Skip to content

Commit 556e5f4

Browse files
committed
Add and methods
0 parents  commit 556e5f4

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
Cargo.lock

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "hashmap-rs"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]

examples/std-1.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use hashmap::HashMap;
2+
3+
// Type inference lets us omit an explicit type signature (which
4+
// would be `HashMap<String, String>` in this example).
5+
let mut book_reviews = HashMap::new();
6+
7+
// Review some books.
8+
book_reviews.insert(
9+
"Adventures of Huckleberry Finn".to_string(),
10+
"My favorite book.".to_string(),
11+
);
12+
book_reviews.insert(
13+
"Grimms' Fairy Tales".to_string(),
14+
"Masterpiece.".to_string(),
15+
);
16+
book_reviews.insert(
17+
"Pride and Prejudice".to_string(),
18+
"Very enjoyable.".to_string(),
19+
);
20+
book_reviews.insert(
21+
"The Adventures of Sherlock Holmes".to_string(),
22+
"Eye lyked it alot.".to_string(),
23+
);
24+
25+
// Check for a specific one.
26+
// When collections store owned values (String), they can still be
27+
// queried using references (&str).
28+
if !book_reviews.contains_key("Les Misérables") {
29+
println!("We've got {} reviews, but Les Misérables ain't one.",
30+
book_reviews.len());
31+
}
32+
33+
// oops, this review has a lot of spelling mistakes, let's delete it.
34+
book_reviews.remove("The Adventures of Sherlock Holmes");
35+
36+
// Look up the values associated with some keys.
37+
let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
38+
for &book in &to_find {
39+
match book_reviews.get(book) {
40+
Some(review) => println!("{}: {}", book, review),
41+
None => println!("{} is unreviewed.", book)
42+
}
43+
}
44+
45+
// Look up the value for a key (will panic if the key is not found).
46+
println!("Review for Jane: {}", book_reviews["Pride and Prejudice"]);
47+
48+
// Iterate over everything.
49+
for (book, review) in &book_reviews {
50+
println!("{}: \"{}\"", book, review);
51+
}

src/lib.rs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use std::collections::hash_map::DefaultHasher;
2+
use std::hash::{Hash, Hasher};
3+
use std::mem;
4+
5+
const INITIAL_NBUCKETS: usize = 1;
6+
7+
pub struct HashMap<K, V> {
8+
buckets: Vec<Vec<(K, V)>>,
9+
items: usize,
10+
}
11+
12+
impl<K, V> HashMap<K, V> {
13+
pub fn new() -> Self {
14+
// this should be 'free' to create
15+
HashMap {
16+
buckets: Vec::new(),
17+
items: 0,
18+
}
19+
}
20+
}
21+
22+
impl<K, V> HashMap<K, V>
23+
where
24+
K: Hash + Eq,
25+
{
26+
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
27+
// if buckets is empty or it is 3/4th full the resize
28+
if self.buckets.is_empty() || self.items > 3 * self.buckets.len() / 4 {
29+
self.resize();
30+
}
31+
32+
let mut hasher = DefaultHasher::new();
33+
key.hash(&mut hasher);
34+
let hash = hasher.finish();
35+
36+
let bucket = (hash % self.buckets.len() as u64) as usize;
37+
let bucket = &mut self.buckets[bucket];
38+
self.items += 1;
39+
40+
for (ref k, ref mut v) in bucket.iter_mut() {
41+
if k == &key {
42+
// update
43+
return Some(mem::replace(v, value));
44+
}
45+
}
46+
47+
bucket.push((key, value));
48+
None
49+
}
50+
51+
pub fn resize(&mut self) {
52+
let target_size = match self.buckets.len() {
53+
0 => INITIAL_NBUCKETS,
54+
n => 2 * n,
55+
};
56+
57+
// create new buckets
58+
let mut new_buckets = Vec::with_capacity(target_size);
59+
new_buckets.extend((0..target_size).map(|_| Vec::new()));
60+
61+
// add elements into new buckets
62+
for (key, val) in self.buckets.iter_mut().flat_map(|bucket| bucket.drain(..)) {
63+
let mut hasher = DefaultHasher::new();
64+
key.hash(&mut hasher);
65+
let hash = hasher.finish();
66+
67+
let bucket = (hash % new_buckets.len() as u64) as usize;
68+
let bucket = &mut new_buckets[bucket];
69+
bucket.push((key, val));
70+
}
71+
72+
// replace old buckets with new buckets
73+
mem::replace(&mut self.buckets, new_buckets);
74+
}
75+
}
76+
77+
#[cfg(test)]
78+
79+
mod tests {
80+
use super::*;
81+
82+
#[test]
83+
fn insert() {
84+
let mut map = HashMap::new();
85+
map.insert("foo", 42);
86+
}
87+
}

0 commit comments

Comments
 (0)