2013-01-20 13:18:24 -06:00
|
|
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-12-24 10:08:28 -06:00
|
|
|
//! Unordered containers, implemented as hash-tables (`HashSet` and `HashMap` types)
|
2013-03-27 02:03:10 -05:00
|
|
|
//!
|
|
|
|
//! The tables use a keyed hash with new random keys generated for each container, so the ordering
|
|
|
|
//! of a set of keys in a hash table is randomized.
|
2013-12-27 05:36:02 -06:00
|
|
|
//!
|
|
|
|
//! # Example
|
|
|
|
//!
|
|
|
|
//! ```rust
|
|
|
|
//! use std::hashmap::HashMap;
|
|
|
|
//!
|
|
|
|
//! // type inference lets us omit an explicit type signature (which
|
|
|
|
//! // would be `HashMap<&str, &str>` in this example).
|
|
|
|
//! let mut book_reviews = HashMap::new();
|
|
|
|
//!
|
|
|
|
//! // review some books.
|
|
|
|
//! book_reviews.insert("Adventures of Hucklebury Fin", "My favorite book.");
|
|
|
|
//! book_reviews.insert("Grimms' Fairy Tales", "Masterpiece.");
|
|
|
|
//! book_reviews.insert("Pride and Prejudice", "Very enjoyable.");
|
|
|
|
//! book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot.");
|
|
|
|
//!
|
|
|
|
//! // check for a specific one.
|
|
|
|
//! if !book_reviews.contains_key(& &"Les Misérables") {
|
|
|
|
//! println!("We've got {} reviews, but Les Misérables ain't one.",
|
|
|
|
//! book_reviews.len());
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! // oops, this review has a lot of spelling mistakes, let's delete it.
|
|
|
|
//! book_reviews.remove(& &"The Adventures of Sherlock Holmes");
|
|
|
|
//!
|
|
|
|
//! // look up the values associated with some keys.
|
|
|
|
//! let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
|
|
|
|
//! for book in to_find.iter() {
|
|
|
|
//! match book_reviews.find(book) {
|
|
|
|
//! Some(review) => println!("{}: {}", *book, *review),
|
|
|
|
//! None => println!("{} is unreviewed.", *book)
|
|
|
|
//! }
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! // iterate over everything.
|
|
|
|
//! for (book, review) in book_reviews.iter() {
|
|
|
|
//! println!("{}: \"{}\"", *book, *review);
|
|
|
|
//! }
|
|
|
|
//! ```
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-07-13 21:44:36 -05:00
|
|
|
use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
|
2013-07-15 20:55:52 -05:00
|
|
|
use clone::Clone;
|
2013-04-03 07:45:14 -05:00
|
|
|
use cmp::{Eq, Equiv};
|
2013-09-09 21:28:05 -05:00
|
|
|
use default::Default;
|
2013-04-03 07:45:14 -05:00
|
|
|
use hash::Hash;
|
2013-12-31 13:09:18 -06:00
|
|
|
use iter;
|
2013-09-08 10:01:16 -05:00
|
|
|
use iter::{Iterator, FromIterator, Extendable};
|
|
|
|
use iter::{FilterMap, Chain, Repeat, Zip};
|
Replaces the free-standing functions in f32, &c.
The free-standing functions in f32, f64, i8, i16, i32, i64, u8, u16,
u32, u64, float, int, and uint are replaced with generic functions in
num instead.
If you were previously using any of those functions, just replace them
with the corresponding function with the same name in num.
Note: If you were using a function that corresponds to an operator, use
the operator instead.
2013-07-08 11:05:17 -05:00
|
|
|
use num;
|
2013-04-03 07:45:14 -05:00
|
|
|
use option::{None, Option, Some};
|
2013-09-20 06:47:05 -05:00
|
|
|
use rand::Rng;
|
2013-04-03 07:45:14 -05:00
|
|
|
use rand;
|
|
|
|
use uint;
|
2013-09-19 00:04:03 -05:00
|
|
|
use util::replace;
|
2013-07-02 14:47:32 -05:00
|
|
|
use vec::{ImmutableVector, MutableVector, OwnedVector};
|
|
|
|
use vec;
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
static INITIAL_CAPACITY: uint = 32u; // 2^5
|
|
|
|
|
|
|
|
struct Bucket<K,V> {
|
|
|
|
hash: uint,
|
|
|
|
key: K,
|
|
|
|
value: V,
|
|
|
|
}
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2013-05-28 16:35:52 -05:00
|
|
|
/// A hash map implementation which uses linear probing along with the SipHash
|
|
|
|
/// hash function for internal state. This means that the order of all hash maps
|
|
|
|
/// is randomized by keying each hash map randomly on creation.
|
|
|
|
///
|
|
|
|
/// It is required that the keys implement the `Eq` and `Hash` traits, although
|
|
|
|
/// this can frequently be achieved by just implementing the `Eq` and
|
|
|
|
/// `IterBytes` traits as `Hash` is automatically implemented for types that
|
|
|
|
/// implement `IterBytes`.
|
2013-04-03 08:28:36 -05:00
|
|
|
pub struct HashMap<K,V> {
|
2013-04-03 07:45:14 -05:00
|
|
|
priv k0: u64,
|
|
|
|
priv k1: u64,
|
|
|
|
priv resize_at: uint,
|
|
|
|
priv size: uint,
|
|
|
|
priv buckets: ~[Option<Bucket<K, V>>],
|
|
|
|
}
|
2012-09-26 19:47:29 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
// We could rewrite FoundEntry to have type Option<&Bucket<K, V>>
|
|
|
|
// which would be nifty
|
|
|
|
enum SearchResult {
|
|
|
|
FoundEntry(uint), FoundHole(uint), TableFull
|
|
|
|
}
|
2013-01-24 21:00:58 -06:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn resize_at(capacity: uint) -> uint {
|
2013-08-01 03:11:25 -05:00
|
|
|
(capacity * 3) / 4
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl<K:Hash + Eq,V> HashMap<K, V> {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn to_bucket(&self, h: uint) -> uint {
|
|
|
|
// A good hash function with entropy spread over all of the
|
|
|
|
// bits is assumed. SipHash is more than good enough.
|
|
|
|
h % self.buckets.len()
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn next_bucket(&self, idx: uint, len_buckets: uint) -> uint {
|
2013-06-13 02:25:28 -05:00
|
|
|
(idx + 1) % len_buckets
|
2012-08-30 21:01:22 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-11-18 23:15:42 -06:00
|
|
|
fn bucket_sequence(&self, hash: uint, op: |uint| -> bool) -> bool {
|
2013-05-02 17:33:18 -05:00
|
|
|
let start_idx = self.to_bucket(hash);
|
|
|
|
let len_buckets = self.buckets.len();
|
|
|
|
let mut idx = start_idx;
|
|
|
|
loop {
|
|
|
|
if !op(idx) { return false; }
|
2013-04-03 07:45:14 -05:00
|
|
|
idx = self.next_bucket(idx, len_buckets);
|
|
|
|
if idx == start_idx {
|
2013-05-02 17:33:18 -05:00
|
|
|
return true;
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-08-28 13:59:31 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn bucket_for_key(&self, k: &K) -> SearchResult {
|
|
|
|
let hash = k.hash_keyed(self.k0, self.k1) as uint;
|
|
|
|
self.bucket_for_key_with_hash(hash, k)
|
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-18 17:53:29 -05:00
|
|
|
fn bucket_for_key_equiv<Q:Hash + Equiv<K>>(&self, k: &Q)
|
|
|
|
-> SearchResult {
|
2013-04-03 07:45:14 -05:00
|
|
|
let hash = k.hash_keyed(self.k0, self.k1) as uint;
|
|
|
|
self.bucket_for_key_with_hash_equiv(hash, k)
|
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn bucket_for_key_with_hash(&self,
|
|
|
|
hash: uint,
|
|
|
|
k: &K)
|
|
|
|
-> SearchResult {
|
2013-07-31 14:07:44 -05:00
|
|
|
let mut ret = TableFull;
|
2013-11-20 16:17:12 -06:00
|
|
|
self.bucket_sequence(hash, |i| {
|
2013-04-03 07:45:14 -05:00
|
|
|
match self.buckets[i] {
|
2013-07-31 14:07:44 -05:00
|
|
|
Some(ref bkt) if bkt.hash == hash && *k == bkt.key => {
|
|
|
|
ret = FoundEntry(i); false
|
2013-04-03 07:45:14 -05:00
|
|
|
},
|
2013-07-31 14:07:44 -05:00
|
|
|
None => { ret = FoundHole(i); false }
|
|
|
|
_ => true,
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
2013-11-20 16:17:12 -06:00
|
|
|
});
|
2013-07-31 14:07:44 -05:00
|
|
|
ret
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-04 21:43:14 -06:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn bucket_for_key_with_hash_equiv<Q:Equiv<K>>(&self,
|
|
|
|
hash: uint,
|
|
|
|
k: &Q)
|
|
|
|
-> SearchResult {
|
2013-07-31 14:07:44 -05:00
|
|
|
let mut ret = TableFull;
|
2013-11-20 16:17:12 -06:00
|
|
|
self.bucket_sequence(hash, |i| {
|
2013-04-03 07:45:14 -05:00
|
|
|
match self.buckets[i] {
|
2013-07-31 14:07:44 -05:00
|
|
|
Some(ref bkt) if bkt.hash == hash && k.equiv(&bkt.key) => {
|
|
|
|
ret = FoundEntry(i); false
|
2013-04-03 07:45:14 -05:00
|
|
|
},
|
2013-07-31 14:07:44 -05:00
|
|
|
None => { ret = FoundHole(i); false }
|
|
|
|
_ => true,
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-11-20 16:17:12 -06:00
|
|
|
});
|
2013-07-31 14:07:44 -05:00
|
|
|
ret
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-04 21:43:14 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Expand the capacity of the array to the next power of two
|
|
|
|
/// and re-insert each of the existing buckets.
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-03 07:45:14 -05:00
|
|
|
fn expand(&mut self) {
|
|
|
|
let new_capacity = self.buckets.len() * 2;
|
|
|
|
self.resize(new_capacity);
|
|
|
|
}
|
2013-02-15 00:35:15 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Expands the capacity of the array and re-insert each of the
|
|
|
|
/// existing buckets.
|
|
|
|
fn resize(&mut self, new_capacity: uint) {
|
|
|
|
self.resize_at = resize_at(new_capacity);
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-05-05 23:42:54 -05:00
|
|
|
let old_buckets = replace(&mut self.buckets,
|
|
|
|
vec::from_fn(new_capacity, |_| None));
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
self.size = 0;
|
2013-12-16 04:26:25 -06:00
|
|
|
for bucket in old_buckets.move_iter() {
|
2013-04-03 07:45:14 -05:00
|
|
|
self.insert_opt_bucket(bucket);
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
fn insert_opt_bucket(&mut self, bucket: Option<Bucket<K, V>>) {
|
|
|
|
match bucket {
|
|
|
|
Some(Bucket{hash: hash, key: key, value: value}) => {
|
|
|
|
self.insert_internal(hash, key, value);
|
2012-08-28 13:59:31 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
None => {}
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-10 15:11:35 -05:00
|
|
|
fn value_for_bucket<'a>(&'a self, idx: uint) -> &'a V {
|
|
|
|
match self.buckets[idx] {
|
|
|
|
Some(ref bkt) => &bkt.value,
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!("HashMap::find: internal logic error"),
|
2013-04-10 15:11:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-04-10 15:11:35 -05:00
|
|
|
fn mut_value_for_bucket<'a>(&'a mut self, idx: uint) -> &'a mut V {
|
|
|
|
match self.buckets[idx] {
|
|
|
|
Some(ref mut bkt) => &mut bkt.value,
|
2013-09-19 00:04:03 -05:00
|
|
|
None => unreachable!()
|
2013-04-10 15:11:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Inserts the key value pair into the buckets.
|
|
|
|
/// Assumes that there will be a bucket.
|
|
|
|
/// True if there was no previous entry with that key
|
2013-05-04 08:54:58 -05:00
|
|
|
fn insert_internal(&mut self, hash: uint, k: K, v: V) -> Option<V> {
|
2013-04-03 07:45:14 -05:00
|
|
|
match self.bucket_for_key_with_hash(hash, &k) {
|
2013-10-21 15:08:31 -05:00
|
|
|
TableFull => { fail!("Internal logic error"); }
|
2013-04-03 07:45:14 -05:00
|
|
|
FoundHole(idx) => {
|
|
|
|
self.buckets[idx] = Some(Bucket{hash: hash, key: k,
|
|
|
|
value: v});
|
|
|
|
self.size += 1;
|
2013-05-04 08:54:58 -05:00
|
|
|
None
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
FoundEntry(idx) => {
|
2013-05-04 08:54:58 -05:00
|
|
|
match self.buckets[idx] {
|
2013-10-21 15:08:31 -05:00
|
|
|
None => { fail!("insert_internal: Internal logic error") }
|
2013-05-04 08:54:58 -05:00
|
|
|
Some(ref mut b) => {
|
|
|
|
b.hash = hash;
|
|
|
|
b.key = k;
|
|
|
|
Some(replace(&mut b.value, v))
|
|
|
|
}
|
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-08-22 23:01:30 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
fn pop_internal(&mut self, hash: uint, k: &K) -> Option<V> {
|
|
|
|
// Removing from an open-addressed hashtable
|
|
|
|
// is, well, painful. The problem is that
|
|
|
|
// the entry may lie on the probe path for other
|
|
|
|
// entries, so removing it would make you think that
|
|
|
|
// those probe paths are empty.
|
|
|
|
//
|
|
|
|
// To address this we basically have to keep walking,
|
|
|
|
// re-inserting entries we find until we reach an empty
|
|
|
|
// bucket. We know we will eventually reach one because
|
|
|
|
// we insert one ourselves at the beginning (the removed
|
|
|
|
// entry).
|
|
|
|
//
|
|
|
|
// I found this explanation elucidating:
|
|
|
|
// http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf
|
|
|
|
let mut idx = match self.bucket_for_key_with_hash(hash, k) {
|
|
|
|
TableFull | FoundHole(_) => return None,
|
|
|
|
FoundEntry(idx) => idx
|
|
|
|
};
|
|
|
|
|
|
|
|
let len_buckets = self.buckets.len();
|
2013-07-17 16:41:50 -05:00
|
|
|
let bucket = self.buckets[idx].take();
|
2013-04-03 07:45:14 -05:00
|
|
|
|
2013-11-20 16:17:12 -06:00
|
|
|
let value = bucket.map(|bucket| bucket.value);
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
/* re-inserting buckets may cause changes in size, so remember
|
|
|
|
what our new size is ahead of time before we start insertions */
|
|
|
|
let size = self.size - 1;
|
|
|
|
idx = self.next_bucket(idx, len_buckets);
|
|
|
|
while self.buckets[idx].is_some() {
|
2013-07-17 16:41:50 -05:00
|
|
|
let bucket = self.buckets[idx].take();
|
2013-04-03 07:45:14 -05:00
|
|
|
self.insert_opt_bucket(bucket);
|
2012-10-08 09:05:01 -05:00
|
|
|
idx = self.next_bucket(idx, len_buckets);
|
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
self.size = size;
|
2012-10-08 09:05:01 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
value
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
|
2013-04-18 17:53:29 -05:00
|
|
|
impl<K:Hash + Eq,V> Container for HashMap<K, V> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return the number of elements in the map
|
2013-06-23 22:44:11 -05:00
|
|
|
fn len(&self) -> uint { self.size }
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-21 20:59:19 -06:00
|
|
|
|
2013-04-18 17:53:29 -05:00
|
|
|
impl<K:Hash + Eq,V> Mutable for HashMap<K, V> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Clear the map, removing all key-value pairs.
|
|
|
|
fn clear(&mut self) {
|
2013-08-07 09:58:56 -05:00
|
|
|
for bkt in self.buckets.mut_iter() {
|
|
|
|
*bkt = None;
|
2013-01-21 16:25:57 -06:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
self.size = 0;
|
2013-01-21 16:25:57 -06:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-21 16:25:57 -06:00
|
|
|
|
2013-04-18 17:53:29 -05:00
|
|
|
impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return a reference to the value corresponding to the key
|
2013-04-10 15:11:35 -05:00
|
|
|
fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
|
|
|
|
match self.bucket_for_key(k) {
|
|
|
|
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
|
|
|
|
TableFull | FoundHole(_) => None,
|
|
|
|
}
|
|
|
|
}
|
2013-07-13 21:44:36 -05:00
|
|
|
}
|
2013-04-10 15:11:35 -05:00
|
|
|
|
2013-07-13 21:44:36 -05:00
|
|
|
impl<K:Hash + Eq,V> MutableMap<K, V> for HashMap<K, V> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return a mutable reference to the value corresponding to the key
|
2013-05-06 22:29:54 -05:00
|
|
|
fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> {
|
|
|
|
let idx = match self.bucket_for_key(k) {
|
|
|
|
FoundEntry(idx) => idx,
|
|
|
|
TableFull | FoundHole(_) => return None
|
|
|
|
};
|
|
|
|
Some(self.mut_value_for_bucket(idx))
|
|
|
|
}
|
|
|
|
|
2013-05-04 08:54:58 -05:00
|
|
|
/// Insert a key-value pair from the map. If the key already had a value
|
|
|
|
/// present in the map, that value is returned. Otherwise None is returned.
|
|
|
|
fn swap(&mut self, k: K, v: V) -> Option<V> {
|
|
|
|
// this could be faster.
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
if self.size >= self.resize_at {
|
|
|
|
// n.b.: We could also do this after searching, so
|
|
|
|
// that we do not resize if this call to insert is
|
|
|
|
// simply going to update a key in place. My sense
|
|
|
|
// though is that it's worse to have to search through
|
|
|
|
// buckets to find the right spot twice than to just
|
|
|
|
// resize in this corner case.
|
|
|
|
self.expand();
|
|
|
|
}
|
|
|
|
|
|
|
|
let hash = k.hash_keyed(self.k0, self.k1) as uint;
|
|
|
|
self.insert_internal(hash, k, v)
|
2013-01-21 17:22:03 -06:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-05-04 08:54:58 -05:00
|
|
|
/// Removes a key from the map, returning the value at the key if the key
|
|
|
|
/// was previously in the map.
|
|
|
|
fn pop(&mut self, k: &K) -> Option<V> {
|
|
|
|
let hash = k.hash_keyed(self.k0, self.k1) as uint;
|
|
|
|
self.pop_internal(hash, k)
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
}
|
2013-03-28 22:30:50 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl<K: Hash + Eq, V> HashMap<K, V> {
|
2013-04-03 08:28:36 -05:00
|
|
|
/// Create an empty HashMap
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn new() -> HashMap<K, V> {
|
2013-04-03 08:28:36 -05:00
|
|
|
HashMap::with_capacity(INITIAL_CAPACITY)
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-23 16:06:32 -06:00
|
|
|
|
2013-08-01 03:11:25 -05:00
|
|
|
/// Create an empty HashMap with space for at least `capacity`
|
|
|
|
/// elements in the hash table.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn with_capacity(capacity: uint) -> HashMap<K, V> {
|
2013-08-01 03:11:25 -05:00
|
|
|
let mut r = rand::task_rng();
|
|
|
|
HashMap::with_capacity_and_keys(r.gen(), r.gen(), capacity)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create an empty HashMap with space for at least `capacity`
|
|
|
|
/// elements, using `k0` and `k1` as the keys.
|
|
|
|
///
|
|
|
|
/// Warning: `k0` and `k1` are normally randomly generated, and
|
|
|
|
/// are designed to allow HashMaps to be resistant to attacks that
|
|
|
|
/// cause many collisions and very poor performance. Setting them
|
|
|
|
/// manually using this function can expose a DoS attack vector.
|
|
|
|
pub fn with_capacity_and_keys(k0: u64, k1: u64, capacity: uint) -> HashMap<K, V> {
|
|
|
|
let cap = num::max(INITIAL_CAPACITY, capacity);
|
|
|
|
HashMap {
|
|
|
|
k0: k0, k1: k1,
|
|
|
|
resize_at: resize_at(cap),
|
|
|
|
size: 0,
|
|
|
|
buckets: vec::from_fn(cap, |_| None)
|
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-02-15 00:35:15 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Reserve space for at least `n` elements in the hash table.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn reserve_at_least(&mut self, n: uint) {
|
2013-04-03 07:45:14 -05:00
|
|
|
if n > self.buckets.len() {
|
|
|
|
let buckets = n * 4 / 3 + 1;
|
|
|
|
self.resize(uint::next_power_of_two(buckets));
|
2012-10-08 09:05:01 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-05-31 20:48:06 -05:00
|
|
|
/// Modify and return the value corresponding to the key in the map, or
|
|
|
|
/// insert and return a new value if it doesn't exist.
|
2013-12-26 07:24:10 -06:00
|
|
|
///
|
|
|
|
/// This method allows for all insertion behaviours of a hashmap,
|
|
|
|
/// see methods like `insert`, `find_or_insert` and
|
|
|
|
/// `insert_or_update_with` for less general and more friendly
|
|
|
|
/// variations of this.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// use std::hashmap::HashMap;
|
|
|
|
///
|
|
|
|
/// // map some strings to vectors of strings
|
|
|
|
/// let mut map = HashMap::<~str, ~[~str]>::new();
|
|
|
|
/// map.insert(~"a key", ~[~"value"]);
|
|
|
|
/// map.insert(~"z key", ~[~"value"]);
|
|
|
|
///
|
|
|
|
/// let new = ~[~"a key", ~"b key", ~"z key"];
|
|
|
|
/// for k in new.move_iter() {
|
|
|
|
/// map.mangle(k, ~"new value",
|
|
|
|
/// // if the key doesn't exist in the map yet, add it in
|
|
|
|
/// // the obvious way.
|
|
|
|
/// |_k, v| ~[v],
|
|
|
|
/// // if the key does exist either prepend or append this
|
|
|
|
/// // new value based on the first letter of the key.
|
|
|
|
/// |key, already, new| {
|
|
|
|
/// if key.starts_with("z") {
|
|
|
|
/// already.unshift(new);
|
|
|
|
/// } else {
|
|
|
|
/// already.push(new);
|
|
|
|
/// }
|
|
|
|
/// });
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// for (k, v) in map.iter() {
|
|
|
|
/// println!("{} -> {:?}", *k, *v);
|
|
|
|
/// }
|
|
|
|
/// ```
|
2013-11-18 23:15:42 -06:00
|
|
|
pub fn mangle<'a,
|
|
|
|
A>(
|
|
|
|
&'a mut self,
|
|
|
|
k: K,
|
|
|
|
a: A,
|
|
|
|
not_found: |&K, A| -> V,
|
|
|
|
found: |&K, &mut V, A|)
|
|
|
|
-> &'a mut V {
|
2013-05-06 22:29:54 -05:00
|
|
|
if self.size >= self.resize_at {
|
|
|
|
// n.b.: We could also do this after searching, so
|
|
|
|
// that we do not resize if this call to insert is
|
|
|
|
// simply going to update a key in place. My sense
|
|
|
|
// though is that it's worse to have to search through
|
|
|
|
// buckets to find the right spot twice than to just
|
|
|
|
// resize in this corner case.
|
|
|
|
self.expand();
|
|
|
|
}
|
|
|
|
|
|
|
|
let hash = k.hash_keyed(self.k0, self.k1) as uint;
|
|
|
|
let idx = match self.bucket_for_key_with_hash(hash, &k) {
|
2013-10-21 15:08:31 -05:00
|
|
|
TableFull => fail!("Internal logic error"),
|
2013-05-31 20:48:06 -05:00
|
|
|
FoundEntry(idx) => { found(&k, self.mut_value_for_bucket(idx), a); idx }
|
2013-05-06 22:29:54 -05:00
|
|
|
FoundHole(idx) => {
|
2013-05-31 20:48:06 -05:00
|
|
|
let v = not_found(&k, a);
|
|
|
|
self.buckets[idx] = Some(Bucket{hash: hash, key: k, value: v});
|
2013-05-06 22:29:54 -05:00
|
|
|
self.size += 1;
|
|
|
|
idx
|
2013-05-31 20:48:06 -05:00
|
|
|
}
|
2013-05-06 22:29:54 -05:00
|
|
|
};
|
|
|
|
|
2013-05-31 20:48:06 -05:00
|
|
|
self.mut_value_for_bucket(idx)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return the value corresponding to the key in the map, or insert
|
|
|
|
/// and return the value if it doesn't exist.
|
|
|
|
pub fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a mut V {
|
|
|
|
self.mangle(k, v, |_k, a| a, |_k,_v,_a| ())
|
2013-05-06 22:29:54 -05:00
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return the value corresponding to the key in the map, or create,
|
|
|
|
/// insert, and return a new value if it doesn't exist.
|
2013-11-18 23:15:42 -06:00
|
|
|
pub fn find_or_insert_with<'a>(&'a mut self, k: K, f: |&K| -> V)
|
2013-05-31 20:48:06 -05:00
|
|
|
-> &'a mut V {
|
|
|
|
self.mangle(k, (), |k,_a| f(k), |_k,_v,_a| ())
|
2013-05-06 22:29:54 -05:00
|
|
|
}
|
|
|
|
|
2013-05-31 20:50:20 -05:00
|
|
|
/// Insert a key-value pair into the map if the key is not already present.
|
|
|
|
/// Otherwise, modify the existing value for the key.
|
|
|
|
/// Returns the new or modified value for the key.
|
2013-11-18 23:15:42 -06:00
|
|
|
pub fn insert_or_update_with<'a>(
|
|
|
|
&'a mut self,
|
|
|
|
k: K,
|
|
|
|
v: V,
|
|
|
|
f: |&K, &mut V|)
|
|
|
|
-> &'a mut V {
|
2013-05-31 20:50:20 -05:00
|
|
|
self.mangle(k, v, |_k,a| a, |k,v,_a| f(k,v))
|
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
/// Retrieves a value for the given key, failing if the key is not
|
|
|
|
/// present.
|
|
|
|
pub fn get<'a>(&'a self, k: &K) -> &'a V {
|
2013-04-10 15:11:35 -05:00
|
|
|
match self.find(k) {
|
|
|
|
Some(v) => v,
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!("No entry found for key: {:?}", k),
|
2013-04-10 15:11:35 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 14:56:05 -05:00
|
|
|
/// Retrieves a (mutable) value for the given key, failing if the key
|
|
|
|
/// is not present.
|
|
|
|
pub fn get_mut<'a>(&'a mut self, k: &K) -> &'a mut V {
|
|
|
|
match self.find_mut(k) {
|
|
|
|
Some(v) => v,
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!("No entry found for key: {:?}", k),
|
2013-05-31 14:56:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the map contains a value for the specified key,
|
|
|
|
/// using equivalence
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn contains_key_equiv<Q:Hash + Equiv<K>>(&self, key: &Q) -> bool {
|
2013-04-03 07:45:14 -05:00
|
|
|
match self.bucket_for_key_equiv(key) {
|
|
|
|
FoundEntry(_) => {true}
|
|
|
|
TableFull | FoundHole(_) => {false}
|
2013-03-04 21:43:14 -06:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-04 21:43:14 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return the value corresponding to the key in the map, using
|
|
|
|
/// equivalence
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn find_equiv<'a, Q:Hash + Equiv<K>>(&'a self, k: &Q)
|
|
|
|
-> Option<&'a V> {
|
2013-04-10 15:11:35 -05:00
|
|
|
match self.bucket_for_key_equiv(k) {
|
|
|
|
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
|
|
|
|
TableFull | FoundHole(_) => None,
|
|
|
|
}
|
|
|
|
}
|
2013-06-21 10:05:05 -05:00
|
|
|
|
2013-12-31 13:09:18 -06:00
|
|
|
/// An iterator visiting all keys in arbitrary order.
|
|
|
|
/// Iterator element type is &'a K.
|
|
|
|
pub fn keys<'a>(&'a self) -> HashMapKeyIterator<'a, K, V> {
|
|
|
|
self.iter().map(|(k, _v)| k)
|
2013-06-24 16:45:00 -05:00
|
|
|
}
|
|
|
|
|
2013-12-31 13:09:18 -06:00
|
|
|
/// An iterator visiting all values in arbitrary order.
|
|
|
|
/// Iterator element type is &'a V.
|
|
|
|
pub fn values<'a>(&'a self) -> HashMapValueIterator<'a, K, V> {
|
|
|
|
self.iter().map(|(_k, v)| v)
|
2013-06-24 16:45:00 -05:00
|
|
|
}
|
|
|
|
|
2013-06-21 10:05:05 -05:00
|
|
|
/// An iterator visiting all key-value pairs in arbitrary order.
|
|
|
|
/// Iterator element type is (&'a K, &'a V).
|
|
|
|
pub fn iter<'a>(&'a self) -> HashMapIterator<'a, K, V> {
|
|
|
|
HashMapIterator { iter: self.buckets.iter() }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An iterator visiting all key-value pairs in arbitrary order,
|
|
|
|
/// with mutable references to the values.
|
|
|
|
/// Iterator element type is (&'a K, &'a mut V).
|
|
|
|
pub fn mut_iter<'a>(&'a mut self) -> HashMapMutIterator<'a, K, V> {
|
|
|
|
HashMapMutIterator { iter: self.buckets.mut_iter() }
|
|
|
|
}
|
2013-07-16 09:39:24 -05:00
|
|
|
|
|
|
|
/// Creates a consuming iterator, that is, one that moves each key-value
|
|
|
|
/// pair out of the map in arbitrary order. The map cannot be used after
|
|
|
|
/// calling this.
|
2013-08-07 21:21:36 -05:00
|
|
|
pub fn move_iter(self) -> HashMapMoveIterator<K, V> {
|
2013-12-16 04:26:25 -06:00
|
|
|
HashMapMoveIterator {iter: self.buckets.move_iter()}
|
2013-07-16 09:39:24 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-07-31 16:11:57 -05:00
|
|
|
|
2013-07-02 14:47:32 -05:00
|
|
|
impl<K: Hash + Eq, V: Clone> HashMap<K, V> {
|
2013-05-05 11:17:59 -05:00
|
|
|
/// Like `find`, but returns a copy of the value.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn find_copy(&self, k: &K) -> Option<V> {
|
2013-09-20 01:08:47 -05:00
|
|
|
self.find(k).map(|v| (*v).clone())
|
2013-05-05 11:17:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Like `get`, but returns a copy of the value.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn get_copy(&self, k: &K) -> V {
|
2013-07-02 14:47:32 -05:00
|
|
|
(*self.get(k)).clone()
|
2013-05-05 11:17:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-18 17:53:29 -05:00
|
|
|
impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
|
2013-04-03 08:28:36 -05:00
|
|
|
fn eq(&self, other: &HashMap<K, V>) -> bool {
|
2013-04-03 07:45:14 -05:00
|
|
|
if self.len() != other.len() { return false; }
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-11-20 16:17:12 -06:00
|
|
|
self.iter().all(|(key, value)| {
|
2013-04-03 07:45:14 -05:00
|
|
|
match other.find(key) {
|
2013-07-18 00:35:34 -05:00
|
|
|
None => false,
|
|
|
|
Some(v) => value == v
|
2012-12-10 11:00:52 -06:00
|
|
|
}
|
2013-11-20 16:17:12 -06:00
|
|
|
})
|
2012-12-10 11:00:52 -06:00
|
|
|
}
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2013-04-03 08:28:36 -05:00
|
|
|
fn ne(&self, other: &HashMap<K, V>) -> bool { !self.eq(other) }
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2013-07-02 14:47:32 -05:00
|
|
|
impl<K:Hash + Eq + Clone,V:Clone> Clone for HashMap<K,V> {
|
|
|
|
fn clone(&self) -> HashMap<K,V> {
|
|
|
|
let mut new_map = HashMap::with_capacity(self.len());
|
2013-08-03 11:45:23 -05:00
|
|
|
for (key, value) in self.iter() {
|
2013-07-02 14:47:32 -05:00
|
|
|
new_map.insert((*key).clone(), (*value).clone());
|
|
|
|
}
|
|
|
|
new_map
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-21 10:05:05 -05:00
|
|
|
/// HashMap iterator
|
2013-07-18 10:38:17 -05:00
|
|
|
#[deriving(Clone)]
|
2013-12-10 01:16:18 -06:00
|
|
|
pub struct HashMapIterator<'a, K, V> {
|
|
|
|
priv iter: vec::VecIterator<'a, Option<Bucket<K, V>>>,
|
2013-06-21 10:05:05 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// HashMap mutable values iterator
|
2013-12-10 01:16:18 -06:00
|
|
|
pub struct HashMapMutIterator<'a, K, V> {
|
|
|
|
priv iter: vec::VecMutIterator<'a, Option<Bucket<K, V>>>,
|
2013-06-21 10:05:05 -05:00
|
|
|
}
|
|
|
|
|
2013-08-07 21:21:36 -05:00
|
|
|
/// HashMap move iterator
|
|
|
|
pub struct HashMapMoveIterator<K, V> {
|
2013-12-16 04:26:25 -06:00
|
|
|
priv iter: vec::MoveIterator<Option<Bucket<K, V>>>,
|
2013-07-15 13:43:16 -05:00
|
|
|
}
|
|
|
|
|
2013-12-31 13:09:18 -06:00
|
|
|
/// HashMap keys iterator
|
|
|
|
pub type HashMapKeyIterator<'a, K, V> =
|
|
|
|
iter::Map<'static, (&'a K, &'a V), &'a K, HashMapIterator<'a, K, V>>;
|
|
|
|
|
|
|
|
/// HashMap values iterator
|
|
|
|
pub type HashMapValueIterator<'a, K, V> =
|
|
|
|
iter::Map<'static, (&'a K, &'a V), &'a V, HashMapIterator<'a, K, V>>;
|
|
|
|
|
2013-06-21 10:05:05 -05:00
|
|
|
/// HashSet iterator
|
2013-07-18 10:38:17 -05:00
|
|
|
#[deriving(Clone)]
|
2013-12-10 01:16:18 -06:00
|
|
|
pub struct HashSetIterator<'a, K> {
|
|
|
|
priv iter: vec::VecIterator<'a, Option<Bucket<K, ()>>>,
|
2013-06-21 10:05:05 -05:00
|
|
|
}
|
|
|
|
|
2013-08-07 21:21:36 -05:00
|
|
|
/// HashSet move iterator
|
|
|
|
pub struct HashSetMoveIterator<K> {
|
2013-12-16 04:26:25 -06:00
|
|
|
priv iter: vec::MoveIterator<Option<Bucket<K, ()>>>,
|
2013-07-15 13:43:16 -05:00
|
|
|
}
|
|
|
|
|
2013-12-10 01:16:18 -06:00
|
|
|
impl<'a, K, V> Iterator<(&'a K, &'a V)> for HashMapIterator<'a, K, V> {
|
2013-06-21 10:05:05 -05:00
|
|
|
#[inline]
|
2013-12-10 01:16:18 -06:00
|
|
|
fn next(&mut self) -> Option<(&'a K, &'a V)> {
|
2013-08-03 11:45:23 -05:00
|
|
|
for elt in self.iter {
|
2013-06-21 10:05:05 -05:00
|
|
|
match elt {
|
|
|
|
&Some(ref bucket) => return Some((&bucket.key, &bucket.value)),
|
|
|
|
&None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-10 01:16:18 -06:00
|
|
|
impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for HashMapMutIterator<'a, K, V> {
|
2013-06-21 10:05:05 -05:00
|
|
|
#[inline]
|
2013-12-10 01:16:18 -06:00
|
|
|
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
|
2013-08-03 11:45:23 -05:00
|
|
|
for elt in self.iter {
|
2013-06-21 10:05:05 -05:00
|
|
|
match elt {
|
|
|
|
&Some(ref mut bucket) => return Some((&bucket.key, &mut bucket.value)),
|
|
|
|
&None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-07 21:21:36 -05:00
|
|
|
impl<K, V> Iterator<(K, V)> for HashMapMoveIterator<K, V> {
|
2013-07-15 13:43:16 -05:00
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<(K, V)> {
|
2013-08-03 11:45:23 -05:00
|
|
|
for elt in self.iter {
|
2013-07-15 13:43:16 -05:00
|
|
|
match elt {
|
2013-11-28 14:22:53 -06:00
|
|
|
Some(Bucket {key, value, ..}) => return Some((key, value)),
|
2013-07-15 13:43:16 -05:00
|
|
|
None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-10 01:16:18 -06:00
|
|
|
impl<'a, K> Iterator<&'a K> for HashSetIterator<'a, K> {
|
2013-06-21 10:05:05 -05:00
|
|
|
#[inline]
|
2013-12-10 01:16:18 -06:00
|
|
|
fn next(&mut self) -> Option<&'a K> {
|
2013-08-03 11:45:23 -05:00
|
|
|
for elt in self.iter {
|
2013-06-21 10:05:05 -05:00
|
|
|
match elt {
|
|
|
|
&Some(ref bucket) => return Some(&bucket.key),
|
|
|
|
&None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-07 21:21:36 -05:00
|
|
|
impl<K> Iterator<K> for HashSetMoveIterator<K> {
|
2013-07-15 13:43:16 -05:00
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<K> {
|
2013-08-03 11:45:23 -05:00
|
|
|
for elt in self.iter {
|
2013-07-15 13:43:16 -05:00
|
|
|
match elt {
|
|
|
|
Some(bucket) => return Some(bucket.key),
|
|
|
|
None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
std: Move the iterator param on FromIterator and Extendable to the method.
If they are on the trait then it is extremely annoying to use them as
generic parameters to a function, e.g. with the iterator param on the trait
itself, if one was to pass an Extendable<int> to a function that filled it
either from a Range or a Map<VecIterator>, one needs to write something
like:
fn foo<E: Extendable<int, Range<int>> +
Extendable<int, Map<&'self int, int, VecIterator<int>>>
(e: &mut E, ...) { ... }
since using a generic, i.e. `foo<E: Extendable<int, I>, I: Iterator<int>>`
means that `foo` takes 2 type parameters, and the caller has to specify them
(which doesn't work anyway, as they'll mismatch with the iterators used in
`foo` itself).
This patch changes it to:
fn foo<E: Extendable<int>>(e: &mut E, ...) { ... }
2013-08-13 08:08:14 -05:00
|
|
|
impl<K: Eq + Hash, V> FromIterator<(K, V)> for HashMap<K, V> {
|
|
|
|
fn from_iterator<T: Iterator<(K, V)>>(iter: &mut T) -> HashMap<K, V> {
|
2013-07-14 10:26:03 -05:00
|
|
|
let (lower, _) = iter.size_hint();
|
|
|
|
let mut map = HashMap::with_capacity(lower);
|
2013-07-29 19:17:17 -05:00
|
|
|
map.extend(iter);
|
|
|
|
map
|
|
|
|
}
|
|
|
|
}
|
2013-07-14 10:26:03 -05:00
|
|
|
|
std: Move the iterator param on FromIterator and Extendable to the method.
If they are on the trait then it is extremely annoying to use them as
generic parameters to a function, e.g. with the iterator param on the trait
itself, if one was to pass an Extendable<int> to a function that filled it
either from a Range or a Map<VecIterator>, one needs to write something
like:
fn foo<E: Extendable<int, Range<int>> +
Extendable<int, Map<&'self int, int, VecIterator<int>>>
(e: &mut E, ...) { ... }
since using a generic, i.e. `foo<E: Extendable<int, I>, I: Iterator<int>>`
means that `foo` takes 2 type parameters, and the caller has to specify them
(which doesn't work anyway, as they'll mismatch with the iterators used in
`foo` itself).
This patch changes it to:
fn foo<E: Extendable<int>>(e: &mut E, ...) { ... }
2013-08-13 08:08:14 -05:00
|
|
|
impl<K: Eq + Hash, V> Extendable<(K, V)> for HashMap<K, V> {
|
|
|
|
fn extend<T: Iterator<(K, V)>>(&mut self, iter: &mut T) {
|
2013-08-03 11:45:23 -05:00
|
|
|
for (k, v) in *iter {
|
2013-07-29 19:17:17 -05:00
|
|
|
self.insert(k, v);
|
2013-07-14 10:26:03 -05:00
|
|
|
}
|
|
|
|
}
|
2013-07-14 12:18:50 -05:00
|
|
|
}
|
2013-06-21 10:05:05 -05:00
|
|
|
|
2013-09-09 21:28:05 -05:00
|
|
|
impl<K: Eq + Hash, V> Default for HashMap<K, V> {
|
|
|
|
fn default() -> HashMap<K, V> { HashMap::new() }
|
|
|
|
}
|
|
|
|
|
2013-05-28 16:35:52 -05:00
|
|
|
/// An implementation of a hash set using the underlying representation of a
|
|
|
|
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
|
|
|
|
/// requires that the elements implement the `Eq` and `Hash` traits.
|
2013-04-03 08:28:36 -05:00
|
|
|
pub struct HashSet<T> {
|
|
|
|
priv map: HashMap<T, ()>
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2013-04-18 17:53:29 -05:00
|
|
|
impl<T:Hash + Eq> Eq for HashSet<T> {
|
2013-04-03 08:28:36 -05:00
|
|
|
fn eq(&self, other: &HashSet<T>) -> bool { self.map == other.map }
|
|
|
|
fn ne(&self, other: &HashSet<T>) -> bool { self.map != other.map }
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-23 15:47:27 -06:00
|
|
|
|
2013-04-18 17:53:29 -05:00
|
|
|
impl<T:Hash + Eq> Container for HashSet<T> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return the number of elements in the set
|
2013-06-23 22:44:11 -05:00
|
|
|
fn len(&self) -> uint { self.map.len() }
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-21 16:25:57 -06:00
|
|
|
|
2013-04-18 17:53:29 -05:00
|
|
|
impl<T:Hash + Eq> Mutable for HashSet<T> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Clear the set, removing all values.
|
|
|
|
fn clear(&mut self) { self.map.clear() }
|
|
|
|
}
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2013-04-18 17:53:29 -05:00
|
|
|
impl<T:Hash + Eq> Set<T> for HashSet<T> {
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the set contains a value
|
|
|
|
fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the set has no elements in common with `other`.
|
|
|
|
/// This is equivalent to checking for an empty intersection.
|
2013-04-03 08:28:36 -05:00
|
|
|
fn is_disjoint(&self, other: &HashSet<T>) -> bool {
|
2013-06-21 10:05:26 -05:00
|
|
|
self.iter().all(|v| !other.contains(v))
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-29 15:07:11 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the set is a subset of another
|
2013-04-03 08:28:36 -05:00
|
|
|
fn is_subset(&self, other: &HashSet<T>) -> bool {
|
2013-06-21 10:05:26 -05:00
|
|
|
self.iter().all(|v| other.contains(v))
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-29 18:30:26 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the set is a superset of another
|
2013-04-03 08:28:36 -05:00
|
|
|
fn is_superset(&self, other: &HashSet<T>) -> bool {
|
2013-04-03 07:45:14 -05:00
|
|
|
other.is_subset(self)
|
|
|
|
}
|
|
|
|
}
|
2013-01-20 13:18:24 -06:00
|
|
|
|
2013-07-13 21:44:36 -05:00
|
|
|
impl<T:Hash + Eq> MutableSet<T> for HashSet<T> {
|
|
|
|
/// Add a value to the set. Return true if the value was not already
|
|
|
|
/// present in the set.
|
|
|
|
fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
|
|
|
|
|
|
|
|
/// Remove a value from the set. Return true if the value was
|
|
|
|
/// present in the set.
|
|
|
|
fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
|
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl<T:Hash + Eq> HashSet<T> {
|
2013-04-03 08:28:36 -05:00
|
|
|
/// Create an empty HashSet
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn new() -> HashSet<T> {
|
2013-04-03 08:28:36 -05:00
|
|
|
HashSet::with_capacity(INITIAL_CAPACITY)
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-28 22:30:50 -05:00
|
|
|
|
2013-04-03 08:28:36 -05:00
|
|
|
/// Create an empty HashSet with space for at least `n` elements in
|
2013-04-03 07:45:14 -05:00
|
|
|
/// the hash table.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn with_capacity(capacity: uint) -> HashSet<T> {
|
2013-04-03 08:28:36 -05:00
|
|
|
HashSet { map: HashMap::with_capacity(capacity) }
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-02-15 00:35:15 -06:00
|
|
|
|
2013-09-10 17:39:26 -05:00
|
|
|
/// Create an empty HashSet with space for at least `capacity`
|
|
|
|
/// elements in the hash table, using `k0` and `k1` as the keys.
|
|
|
|
///
|
|
|
|
/// Warning: `k0` and `k1` are normally randomly generated, and
|
|
|
|
/// are designed to allow HashSets to be resistant to attacks that
|
|
|
|
/// cause many collisions and very poor performance. Setting them
|
|
|
|
/// manually using this function can expose a DoS attack vector.
|
|
|
|
pub fn with_capacity_and_keys(k0: u64, k1: u64, capacity: uint) -> HashSet<T> {
|
|
|
|
HashSet { map: HashMap::with_capacity_and_keys(k0, k1, capacity) }
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Reserve space for at least `n` elements in the hash table.
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn reserve_at_least(&mut self, n: uint) {
|
2013-04-03 07:45:14 -05:00
|
|
|
self.map.reserve_at_least(n)
|
|
|
|
}
|
2013-03-21 14:41:37 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
/// Returns true if the hash set contains a value equivalent to the
|
|
|
|
/// given query value.
|
|
|
|
pub fn contains_equiv<Q:Hash + Equiv<T>>(&self, value: &Q) -> bool {
|
2013-05-11 10:42:59 -05:00
|
|
|
self.map.contains_key_equiv(value)
|
|
|
|
}
|
2013-06-21 10:05:05 -05:00
|
|
|
|
|
|
|
/// An iterator visiting all elements in arbitrary order.
|
|
|
|
/// Iterator element type is &'a T.
|
|
|
|
pub fn iter<'a>(&'a self) -> HashSetIterator<'a, T> {
|
|
|
|
HashSetIterator { iter: self.map.buckets.iter() }
|
|
|
|
}
|
2013-07-15 20:55:52 -05:00
|
|
|
|
2013-07-16 09:39:24 -05:00
|
|
|
/// Creates a consuming iterator, that is, one that moves each value out
|
|
|
|
/// of the set in arbitrary order. The set cannot be used after calling
|
|
|
|
/// this.
|
2013-08-07 21:21:36 -05:00
|
|
|
pub fn move_iter(self) -> HashSetMoveIterator<T> {
|
2013-12-16 04:26:25 -06:00
|
|
|
HashSetMoveIterator {iter: self.map.buckets.move_iter()}
|
2013-07-16 09:39:24 -05:00
|
|
|
}
|
|
|
|
|
2013-07-15 20:55:52 -05:00
|
|
|
/// Visit the values representing the difference
|
2013-11-23 04:18:51 -06:00
|
|
|
pub fn difference<'a>(&'a self, other: &'a HashSet<T>) -> SetAlgebraIter<'a, T> {
|
2013-08-03 14:34:00 -05:00
|
|
|
Repeat::new(other)
|
|
|
|
.zip(self.iter())
|
|
|
|
.filter_map(|(other, elt)| {
|
|
|
|
if !other.contains(elt) { Some(elt) } else { None }
|
|
|
|
})
|
2013-07-15 20:55:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Visit the values representing the symmetric difference
|
2013-11-23 04:18:51 -06:00
|
|
|
pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T>)
|
2013-07-27 16:41:20 -05:00
|
|
|
-> Chain<SetAlgebraIter<'a, T>, SetAlgebraIter<'a, T>> {
|
2013-11-23 04:18:51 -06:00
|
|
|
self.difference(other).chain(other.difference(self))
|
2013-07-15 20:55:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Visit the values representing the intersection
|
2013-11-23 04:18:51 -06:00
|
|
|
pub fn intersection<'a>(&'a self, other: &'a HashSet<T>)
|
2013-07-15 20:55:52 -05:00
|
|
|
-> SetAlgebraIter<'a, T> {
|
2013-08-03 14:34:00 -05:00
|
|
|
Repeat::new(other)
|
|
|
|
.zip(self.iter())
|
|
|
|
.filter_map(|(other, elt)| {
|
|
|
|
if other.contains(elt) { Some(elt) } else { None }
|
|
|
|
})
|
2013-07-15 20:55:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Visit the values representing the union
|
2013-11-23 04:18:51 -06:00
|
|
|
pub fn union<'a>(&'a self, other: &'a HashSet<T>)
|
2013-07-27 16:41:20 -05:00
|
|
|
-> Chain<HashSetIterator<'a, T>, SetAlgebraIter<'a, T>> {
|
2013-11-23 04:18:51 -06:00
|
|
|
self.iter().chain(other.difference(self))
|
2013-07-15 20:55:52 -05:00
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
|
2013-08-09 09:44:35 -05:00
|
|
|
impl<T:Hash + Eq + Clone> Clone for HashSet<T> {
|
|
|
|
fn clone(&self) -> HashSet<T> {
|
|
|
|
HashSet {
|
|
|
|
map: self.map.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
std: Move the iterator param on FromIterator and Extendable to the method.
If they are on the trait then it is extremely annoying to use them as
generic parameters to a function, e.g. with the iterator param on the trait
itself, if one was to pass an Extendable<int> to a function that filled it
either from a Range or a Map<VecIterator>, one needs to write something
like:
fn foo<E: Extendable<int, Range<int>> +
Extendable<int, Map<&'self int, int, VecIterator<int>>>
(e: &mut E, ...) { ... }
since using a generic, i.e. `foo<E: Extendable<int, I>, I: Iterator<int>>`
means that `foo` takes 2 type parameters, and the caller has to specify them
(which doesn't work anyway, as they'll mismatch with the iterators used in
`foo` itself).
This patch changes it to:
fn foo<E: Extendable<int>>(e: &mut E, ...) { ... }
2013-08-13 08:08:14 -05:00
|
|
|
impl<K: Eq + Hash> FromIterator<K> for HashSet<K> {
|
|
|
|
fn from_iterator<T: Iterator<K>>(iter: &mut T) -> HashSet<K> {
|
2013-07-14 11:20:48 -05:00
|
|
|
let (lower, _) = iter.size_hint();
|
|
|
|
let mut set = HashSet::with_capacity(lower);
|
2013-07-29 19:17:17 -05:00
|
|
|
set.extend(iter);
|
|
|
|
set
|
|
|
|
}
|
|
|
|
}
|
2013-07-14 11:20:48 -05:00
|
|
|
|
std: Move the iterator param on FromIterator and Extendable to the method.
If they are on the trait then it is extremely annoying to use them as
generic parameters to a function, e.g. with the iterator param on the trait
itself, if one was to pass an Extendable<int> to a function that filled it
either from a Range or a Map<VecIterator>, one needs to write something
like:
fn foo<E: Extendable<int, Range<int>> +
Extendable<int, Map<&'self int, int, VecIterator<int>>>
(e: &mut E, ...) { ... }
since using a generic, i.e. `foo<E: Extendable<int, I>, I: Iterator<int>>`
means that `foo` takes 2 type parameters, and the caller has to specify them
(which doesn't work anyway, as they'll mismatch with the iterators used in
`foo` itself).
This patch changes it to:
fn foo<E: Extendable<int>>(e: &mut E, ...) { ... }
2013-08-13 08:08:14 -05:00
|
|
|
impl<K: Eq + Hash> Extendable<K> for HashSet<K> {
|
|
|
|
fn extend<T: Iterator<K>>(&mut self, iter: &mut T) {
|
2013-08-03 11:45:23 -05:00
|
|
|
for k in *iter {
|
2013-07-29 19:17:17 -05:00
|
|
|
self.insert(k);
|
2013-07-14 11:20:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-07-14 12:18:50 -05:00
|
|
|
|
2013-09-09 21:28:05 -05:00
|
|
|
impl<K: Eq + Hash> Default for HashSet<K> {
|
|
|
|
fn default() -> HashSet<K> { HashSet::new() }
|
|
|
|
}
|
|
|
|
|
2013-08-03 14:34:00 -05:00
|
|
|
// `Repeat` is used to feed the filter closure an explicit capture
|
|
|
|
// of a reference to the other set
|
2013-07-15 20:55:52 -05:00
|
|
|
/// Set operations iterator
|
2013-12-10 01:16:18 -06:00
|
|
|
pub type SetAlgebraIter<'a, T> =
|
|
|
|
FilterMap<'static,(&'a HashSet<T>, &'a T), &'a T,
|
|
|
|
Zip<Repeat<&'a HashSet<T>>,HashSetIterator<'a,T>>>;
|
2013-07-15 20:55:52 -05:00
|
|
|
|
2013-07-14 11:20:48 -05:00
|
|
|
|
2013-04-30 06:02:29 -05:00
|
|
|
#[cfg(test)]
|
2013-04-03 07:45:14 -05:00
|
|
|
mod test_map {
|
2013-08-01 17:35:46 -05:00
|
|
|
use prelude::*;
|
2013-04-03 07:45:14 -05:00
|
|
|
use super::*;
|
2013-02-10 17:30:44 -06:00
|
|
|
|
2013-05-30 12:03:11 -05:00
|
|
|
#[test]
|
|
|
|
fn test_create_capacity_zero() {
|
|
|
|
let mut m = HashMap::with_capacity(0);
|
|
|
|
assert!(m.insert(1, 1));
|
|
|
|
}
|
|
|
|
|
2012-10-08 09:05:01 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_insert() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 2));
|
|
|
|
assert!(m.insert(2, 4));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*m.get(&1), 2);
|
|
|
|
assert_eq!(*m.get(&2), 4);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_find_mut() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 12));
|
|
|
|
assert!(m.insert(2, 8));
|
|
|
|
assert!(m.insert(5, 14));
|
|
|
|
let new = 100;
|
|
|
|
match m.find_mut(&5) {
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!(), Some(x) => *x = new
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
assert_eq!(m.find(&5), Some(&new));
|
|
|
|
}
|
2013-03-24 18:07:36 -05:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_insert_overwrite() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 2));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*m.get(&1), 2);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(!m.insert(1, 3));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*m.get(&1), 3);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_insert_conflicts() {
|
2013-08-01 03:11:25 -05:00
|
|
|
let mut m = HashMap::with_capacity(4);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 2));
|
|
|
|
assert!(m.insert(5, 3));
|
|
|
|
assert!(m.insert(9, 4));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*m.get(&9), 4);
|
|
|
|
assert_eq!(*m.get(&5), 3);
|
|
|
|
assert_eq!(*m.get(&1), 2);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_conflict_remove() {
|
2013-08-01 03:11:25 -05:00
|
|
|
let mut m = HashMap::with_capacity(4);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 2));
|
|
|
|
assert!(m.insert(5, 3));
|
|
|
|
assert!(m.insert(9, 4));
|
|
|
|
assert!(m.remove(&1));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*m.get(&9), 4);
|
|
|
|
assert_eq!(*m.get(&5), 3);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_is_empty() {
|
2013-08-01 03:11:25 -05:00
|
|
|
let mut m = HashMap::with_capacity(4);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(1, 2));
|
|
|
|
assert!(!m.is_empty());
|
|
|
|
assert!(m.remove(&1));
|
|
|
|
assert!(m.is_empty());
|
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_pop() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
m.insert(1, 2);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(m.pop(&1), Some(2));
|
|
|
|
assert_eq!(m.pop(&1), None);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_swap() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(m.swap(1, 2), None);
|
|
|
|
assert_eq!(m.swap(1, 3), Some(2));
|
|
|
|
assert_eq!(m.swap(1, 4), Some(3));
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_find_or_insert() {
|
2013-08-08 13:38:10 -05:00
|
|
|
let mut m: HashMap<int,int> = HashMap::new();
|
2013-05-31 20:48:06 -05:00
|
|
|
assert_eq!(*m.find_or_insert(1, 2), 2);
|
|
|
|
assert_eq!(*m.find_or_insert(1, 3), 2);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_find_or_insert_with() {
|
2013-08-08 13:38:10 -05:00
|
|
|
let mut m: HashMap<int,int> = HashMap::new();
|
2013-05-31 20:48:06 -05:00
|
|
|
assert_eq!(*m.find_or_insert_with(1, |_| 2), 2);
|
|
|
|
assert_eq!(*m.find_or_insert_with(1, |_| 3), 2);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-05-31 20:50:20 -05:00
|
|
|
#[test]
|
|
|
|
fn test_insert_or_update_with() {
|
2013-08-08 13:38:10 -05:00
|
|
|
let mut m: HashMap<int,int> = HashMap::new();
|
2013-05-31 20:50:20 -05:00
|
|
|
assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 2);
|
|
|
|
assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 3);
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-08-07 21:21:36 -05:00
|
|
|
fn test_move_iter() {
|
2013-07-15 13:43:16 -05:00
|
|
|
let hm = {
|
|
|
|
let mut hm = HashMap::new();
|
|
|
|
|
|
|
|
hm.insert('a', 1);
|
|
|
|
hm.insert('b', 2);
|
|
|
|
|
|
|
|
hm
|
|
|
|
};
|
|
|
|
|
2013-08-07 21:21:36 -05:00
|
|
|
let v = hm.move_iter().collect::<~[(char, int)]>();
|
2013-07-15 13:43:16 -05:00
|
|
|
assert!([('a', 1), ('b', 2)] == v || [('b', 2), ('a', 1)] == v);
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_iterate() {
|
2013-08-01 03:11:25 -05:00
|
|
|
let mut m = HashMap::with_capacity(4);
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(0u, 32) {
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.insert(i, i*2));
|
2012-07-31 16:11:57 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
let mut observed = 0;
|
2013-08-03 11:45:23 -05:00
|
|
|
for (k, v) in m.iter() {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(*v, *k * 2);
|
2013-04-03 07:45:14 -05:00
|
|
|
observed |= (1 << *k);
|
2012-09-14 17:19:54 -05:00
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(observed, 0xFFFF_FFFF);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-12-31 13:09:18 -06:00
|
|
|
#[test]
|
|
|
|
fn test_keys() {
|
|
|
|
let vec = ~[(1, 'a'), (2, 'b'), (3, 'c')];
|
|
|
|
let map = vec.move_iter().collect::<HashMap<int, char>>();
|
|
|
|
let keys = map.keys().map(|&k| k).collect::<~[int]>();
|
|
|
|
assert_eq!(keys.len(), 3);
|
|
|
|
assert!(keys.contains(&1));
|
|
|
|
assert!(keys.contains(&2));
|
|
|
|
assert!(keys.contains(&3));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_values() {
|
|
|
|
let vec = ~[(1, 'a'), (2, 'b'), (3, 'c')];
|
|
|
|
let map = vec.move_iter().collect::<HashMap<int, char>>();
|
|
|
|
let values = map.values().map(|&v| v).collect::<~[char]>();
|
|
|
|
assert_eq!(values.len(), 3);
|
|
|
|
assert!(values.contains(&'a'));
|
|
|
|
assert!(values.contains(&'b'));
|
|
|
|
assert!(values.contains(&'c'));
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_find() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.find(&1).is_none());
|
|
|
|
m.insert(1, 2);
|
|
|
|
match m.find(&1) {
|
2013-10-21 15:08:31 -05:00
|
|
|
None => fail!(),
|
2013-04-03 07:45:14 -05:00
|
|
|
Some(v) => assert!(*v == 2)
|
|
|
|
}
|
|
|
|
}
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_eq() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m1 = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
m1.insert(1, 2);
|
|
|
|
m1.insert(2, 3);
|
|
|
|
m1.insert(3, 4);
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m2 = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
m2.insert(1, 2);
|
|
|
|
m2.insert(2, 3);
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m1 != m2);
|
2012-12-10 11:00:52 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
m2.insert(3, 4);
|
2012-12-30 12:35:03 -06:00
|
|
|
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(m1, m2);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-12-30 12:35:03 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_expand() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new();
|
2012-12-30 12:35:03 -06:00
|
|
|
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(m.len(), 0);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(m.is_empty());
|
2012-12-30 12:35:03 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
let mut i = 0u;
|
|
|
|
let old_resize_at = m.resize_at;
|
|
|
|
while old_resize_at == m.resize_at {
|
|
|
|
m.insert(i, i);
|
|
|
|
i += 1;
|
2013-03-02 04:09:36 -06:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(m.len(), i);
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(!m.is_empty());
|
2012-12-30 12:35:03 -06:00
|
|
|
}
|
2013-06-11 05:33:30 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_find_equiv() {
|
|
|
|
let mut m = HashMap::new();
|
|
|
|
|
|
|
|
let (foo, bar, baz) = (1,2,3);
|
|
|
|
m.insert(~"foo", foo);
|
|
|
|
m.insert(~"bar", bar);
|
|
|
|
m.insert(~"baz", baz);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(m.find_equiv(&("foo")), Some(&foo));
|
|
|
|
assert_eq!(m.find_equiv(&("bar")), Some(&bar));
|
|
|
|
assert_eq!(m.find_equiv(&("baz")), Some(&baz));
|
|
|
|
|
|
|
|
assert_eq!(m.find_equiv(&("qux")), None);
|
|
|
|
}
|
2013-07-14 10:26:03 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_from_iter() {
|
|
|
|
let xs = ~[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
|
2013-07-14 12:18:50 -05:00
|
|
|
|
2013-08-09 22:09:47 -05:00
|
|
|
let map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
|
2013-07-14 10:26:03 -05:00
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for &(k, v) in xs.iter() {
|
2013-07-14 10:26:03 -05:00
|
|
|
assert_eq!(map.find(&k), Some(&v));
|
|
|
|
}
|
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-29 15:07:11 -06:00
|
|
|
|
2013-04-30 06:02:29 -05:00
|
|
|
#[cfg(test)]
|
2013-04-03 07:45:14 -05:00
|
|
|
mod test_set {
|
|
|
|
use super::*;
|
2013-08-01 02:16:42 -05:00
|
|
|
use prelude::*;
|
2013-07-17 14:32:49 -05:00
|
|
|
use container::Container;
|
2013-06-28 11:08:32 -05:00
|
|
|
use vec::ImmutableEqVector;
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_disjoint() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut xs = HashSet::new();
|
|
|
|
let mut ys = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(xs.is_disjoint(&ys));
|
|
|
|
assert!(ys.is_disjoint(&xs));
|
|
|
|
assert!(xs.insert(5));
|
|
|
|
assert!(ys.insert(11));
|
|
|
|
assert!(xs.is_disjoint(&ys));
|
|
|
|
assert!(ys.is_disjoint(&xs));
|
|
|
|
assert!(xs.insert(7));
|
|
|
|
assert!(xs.insert(19));
|
|
|
|
assert!(xs.insert(4));
|
|
|
|
assert!(ys.insert(2));
|
|
|
|
assert!(ys.insert(-11));
|
|
|
|
assert!(xs.is_disjoint(&ys));
|
|
|
|
assert!(ys.is_disjoint(&xs));
|
|
|
|
assert!(ys.insert(7));
|
|
|
|
assert!(!xs.is_disjoint(&ys));
|
|
|
|
assert!(!ys.is_disjoint(&xs));
|
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_subset_and_superset() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut a = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(a.insert(0));
|
|
|
|
assert!(a.insert(5));
|
|
|
|
assert!(a.insert(11));
|
|
|
|
assert!(a.insert(7));
|
|
|
|
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut b = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
assert!(b.insert(0));
|
|
|
|
assert!(b.insert(7));
|
|
|
|
assert!(b.insert(19));
|
|
|
|
assert!(b.insert(250));
|
|
|
|
assert!(b.insert(11));
|
|
|
|
assert!(b.insert(200));
|
|
|
|
|
|
|
|
assert!(!a.is_subset(&b));
|
|
|
|
assert!(!a.is_superset(&b));
|
|
|
|
assert!(!b.is_subset(&a));
|
|
|
|
assert!(!b.is_superset(&a));
|
|
|
|
|
|
|
|
assert!(b.insert(5));
|
|
|
|
|
|
|
|
assert!(a.is_subset(&b));
|
|
|
|
assert!(!a.is_superset(&b));
|
|
|
|
assert!(!b.is_subset(&a));
|
|
|
|
assert!(b.is_superset(&a));
|
|
|
|
}
|
2013-01-29 18:30:26 -06:00
|
|
|
|
2013-06-21 10:05:16 -05:00
|
|
|
#[test]
|
|
|
|
fn test_iterate() {
|
|
|
|
let mut a = HashSet::new();
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in range(0u, 32) {
|
2013-06-21 10:05:16 -05:00
|
|
|
assert!(a.insert(i));
|
|
|
|
}
|
|
|
|
let mut observed = 0;
|
2013-08-03 11:45:23 -05:00
|
|
|
for k in a.iter() {
|
2013-06-21 10:05:16 -05:00
|
|
|
observed |= (1 << *k);
|
|
|
|
}
|
|
|
|
assert_eq!(observed, 0xFFFF_FFFF);
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_intersection() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut a = HashSet::new();
|
|
|
|
let mut b = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
assert!(a.insert(11));
|
|
|
|
assert!(a.insert(1));
|
|
|
|
assert!(a.insert(3));
|
|
|
|
assert!(a.insert(77));
|
|
|
|
assert!(a.insert(103));
|
|
|
|
assert!(a.insert(5));
|
|
|
|
assert!(a.insert(-5));
|
|
|
|
|
|
|
|
assert!(b.insert(2));
|
|
|
|
assert!(b.insert(11));
|
|
|
|
assert!(b.insert(77));
|
|
|
|
assert!(b.insert(-9));
|
|
|
|
assert!(b.insert(-42));
|
|
|
|
assert!(b.insert(5));
|
|
|
|
assert!(b.insert(3));
|
|
|
|
|
|
|
|
let mut i = 0;
|
|
|
|
let expected = [3, 5, 11, 77];
|
2013-11-23 04:18:51 -06:00
|
|
|
for x in a.intersection(&b) {
|
2013-06-28 11:08:32 -05:00
|
|
|
assert!(expected.contains(x));
|
2013-04-03 07:45:14 -05:00
|
|
|
i += 1
|
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(i, expected.len());
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_difference() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut a = HashSet::new();
|
|
|
|
let mut b = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
assert!(a.insert(1));
|
|
|
|
assert!(a.insert(3));
|
|
|
|
assert!(a.insert(5));
|
|
|
|
assert!(a.insert(9));
|
|
|
|
assert!(a.insert(11));
|
|
|
|
|
|
|
|
assert!(b.insert(3));
|
|
|
|
assert!(b.insert(9));
|
|
|
|
|
|
|
|
let mut i = 0;
|
|
|
|
let expected = [1, 5, 11];
|
2013-11-23 04:18:51 -06:00
|
|
|
for x in a.difference(&b) {
|
2013-06-28 11:08:32 -05:00
|
|
|
assert!(expected.contains(x));
|
2013-04-03 07:45:14 -05:00
|
|
|
i += 1
|
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(i, expected.len());
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
|
|
|
fn test_symmetric_difference() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut a = HashSet::new();
|
|
|
|
let mut b = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
assert!(a.insert(1));
|
|
|
|
assert!(a.insert(3));
|
|
|
|
assert!(a.insert(5));
|
|
|
|
assert!(a.insert(9));
|
|
|
|
assert!(a.insert(11));
|
|
|
|
|
|
|
|
assert!(b.insert(-2));
|
|
|
|
assert!(b.insert(3));
|
|
|
|
assert!(b.insert(9));
|
|
|
|
assert!(b.insert(14));
|
|
|
|
assert!(b.insert(22));
|
|
|
|
|
|
|
|
let mut i = 0;
|
|
|
|
let expected = [-2, 1, 5, 11, 14, 22];
|
2013-11-23 04:18:51 -06:00
|
|
|
for x in a.symmetric_difference(&b) {
|
2013-06-28 11:08:32 -05:00
|
|
|
assert!(expected.contains(x));
|
2013-04-03 07:45:14 -05:00
|
|
|
i += 1
|
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(i, expected.len());
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_union() {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut a = HashSet::new();
|
|
|
|
let mut b = HashSet::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
assert!(a.insert(1));
|
|
|
|
assert!(a.insert(3));
|
|
|
|
assert!(a.insert(5));
|
|
|
|
assert!(a.insert(9));
|
|
|
|
assert!(a.insert(11));
|
|
|
|
assert!(a.insert(16));
|
|
|
|
assert!(a.insert(19));
|
|
|
|
assert!(a.insert(24));
|
|
|
|
|
|
|
|
assert!(b.insert(-2));
|
|
|
|
assert!(b.insert(1));
|
|
|
|
assert!(b.insert(5));
|
|
|
|
assert!(b.insert(9));
|
|
|
|
assert!(b.insert(13));
|
|
|
|
assert!(b.insert(19));
|
|
|
|
|
|
|
|
let mut i = 0;
|
|
|
|
let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
|
2013-11-23 04:18:51 -06:00
|
|
|
for x in a.union(&b) {
|
2013-06-28 11:08:32 -05:00
|
|
|
assert!(expected.contains(x));
|
2013-04-03 07:45:14 -05:00
|
|
|
i += 1
|
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(i, expected.len());
|
2013-01-29 20:58:47 -06:00
|
|
|
}
|
2013-07-14 11:20:48 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_from_iter() {
|
|
|
|
let xs = ~[1, 2, 3, 4, 5, 6, 7, 8, 9];
|
2013-07-14 12:18:50 -05:00
|
|
|
|
2013-08-09 22:09:47 -05:00
|
|
|
let set: HashSet<int> = xs.iter().map(|&x| x).collect();
|
2013-07-14 11:20:48 -05:00
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for x in xs.iter() {
|
2013-07-14 11:20:48 -05:00
|
|
|
assert!(set.contains(x));
|
|
|
|
}
|
|
|
|
}
|
2013-07-15 13:43:16 -05:00
|
|
|
|
|
|
|
#[test]
|
2013-08-07 21:21:36 -05:00
|
|
|
fn test_move_iter() {
|
2013-07-15 13:43:16 -05:00
|
|
|
let hs = {
|
|
|
|
let mut hs = HashSet::new();
|
|
|
|
|
|
|
|
hs.insert('a');
|
|
|
|
hs.insert('b');
|
|
|
|
|
|
|
|
hs
|
|
|
|
};
|
|
|
|
|
2013-08-07 21:21:36 -05:00
|
|
|
let v = hs.move_iter().collect::<~[char]>();
|
2013-07-15 13:43:16 -05:00
|
|
|
assert!(['a', 'b'] == v || ['b', 'a'] == v);
|
|
|
|
}
|
2013-08-09 09:44:35 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_eq() {
|
|
|
|
let mut s1 = HashSet::new();
|
|
|
|
s1.insert(1);
|
|
|
|
s1.insert(2);
|
|
|
|
s1.insert(3);
|
|
|
|
|
|
|
|
let mut s2 = HashSet::new();
|
|
|
|
s2.insert(1);
|
|
|
|
s2.insert(2);
|
|
|
|
|
|
|
|
assert!(s1 != s2);
|
|
|
|
|
|
|
|
s2.insert(3);
|
|
|
|
|
|
|
|
assert_eq!(s1, s2);
|
|
|
|
}
|
2013-01-29 15:07:11 -06:00
|
|
|
}
|