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-03-27 02:03:10 -05:00
|
|
|
//! An unordered map and set type implemented as hash tables
|
|
|
|
//!
|
|
|
|
//! 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.
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
#[mutable_doc];
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
use container::{Container, Mutable, Map, Set};
|
|
|
|
use cmp::{Eq, Equiv};
|
|
|
|
use hash::Hash;
|
2013-07-14 10:26:03 -05:00
|
|
|
use iterator::{Iterator, IteratorUtil, FromIterator};
|
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};
|
|
|
|
use rand::RngUtil;
|
|
|
|
use rand;
|
|
|
|
use uint;
|
|
|
|
use vec;
|
2013-07-01 10:26:44 -05:00
|
|
|
use vec::{ImmutableVector, MutableVector, OwnedVector};
|
2013-05-05 11:17:59 -05:00
|
|
|
use kinds::Copy;
|
2013-05-04 08:54:58 -05:00
|
|
|
use util::{replace, unreachable};
|
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 {
|
|
|
|
((capacity as float) * 3. / 4.) as uint
|
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
|
2013-05-28 16:35:52 -05:00
|
|
|
/// Creates a new hash map with the specified capacity.
|
2013-04-03 07:45:14 -05:00
|
|
|
pub fn linear_map_with_capacity<K:Eq + Hash,V>(
|
2013-04-03 08:28:36 -05:00
|
|
|
initial_capacity: uint) -> HashMap<K, V> {
|
2013-05-03 01:09:50 -05:00
|
|
|
let mut r = rand::task_rng();
|
2013-04-24 07:29:19 -05:00
|
|
|
linear_map_with_capacity_and_keys(r.gen(), r.gen(),
|
2013-04-03 07:45:14 -05:00
|
|
|
initial_capacity)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn linear_map_with_capacity_and_keys<K:Eq + Hash,V>(
|
|
|
|
k0: u64, k1: u64,
|
2013-04-03 08:28:36 -05:00
|
|
|
initial_capacity: uint) -> HashMap<K, V> {
|
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
|
|
|
let cap = num::max(INITIAL_CAPACITY, initial_capacity);
|
2013-04-03 08:28:36 -05:00
|
|
|
HashMap {
|
2013-04-03 07:45:14 -05:00
|
|
|
k0: k0, k1: k1,
|
2013-05-30 12:03:11 -05:00
|
|
|
resize_at: resize_at(cap),
|
2013-04-03 07:45:14 -05:00
|
|
|
size: 0,
|
2013-05-30 12:03:11 -05:00
|
|
|
buckets: vec::from_fn(cap, |_| 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-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-05-02 17:33:18 -05:00
|
|
|
fn bucket_sequence(&self, hash: uint,
|
|
|
|
op: &fn(uint) -> bool) -> bool {
|
|
|
|
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-05-02 17:33:18 -05:00
|
|
|
for self.bucket_sequence(hash) |i| {
|
2013-04-03 07:45:14 -05:00
|
|
|
match self.buckets[i] {
|
|
|
|
Some(ref bkt) => if bkt.hash == hash && *k == bkt.key {
|
|
|
|
return FoundEntry(i);
|
|
|
|
},
|
|
|
|
None => return FoundHole(i)
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
TableFull
|
|
|
|
}
|
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-05-02 17:33:18 -05:00
|
|
|
for self.bucket_sequence(hash) |i| {
|
2013-04-03 07:45:14 -05:00
|
|
|
match self.buckets[i] {
|
|
|
|
Some(ref bkt) => {
|
|
|
|
if bkt.hash == hash && k.equiv(&bkt.key) {
|
2012-09-07 12:34:39 -05:00
|
|
|
return FoundEntry(i);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
},
|
|
|
|
None => return FoundHole(i)
|
|
|
|
}
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
TableFull
|
|
|
|
}
|
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-07-01 10:26:44 -05:00
|
|
|
// consume_rev_iter is more efficient
|
|
|
|
for old_buckets.consume_rev_iter().advance |bucket| {
|
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-05-05 17:18:51 -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,
|
|
|
|
None => unreachable()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-05-05 17:18:51 -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-05-05 17:18:51 -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-05-05 23:42:54 -05:00
|
|
|
let bucket = replace(&mut self.buckets[idx], None);
|
2013-04-03 07:45:14 -05:00
|
|
|
|
|
|
|
let value = match bucket {
|
|
|
|
None => None,
|
2013-05-05 23:42:54 -05:00
|
|
|
Some(Bucket{value, _}) => {
|
2013-04-03 07:45:14 -05:00
|
|
|
Some(value)
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
/* 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-05-05 23:42:54 -05:00
|
|
|
let bucket = replace(&mut self.buckets[idx], None);
|
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
|
|
|
fn search(&self, hash: uint,
|
|
|
|
op: &fn(x: &Option<Bucket<K, V>>) -> bool) {
|
|
|
|
let _ = self.bucket_sequence(hash, |i| op(&self.buckets[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-01-23 15:47:27 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the map contains no elements
|
2013-06-23 22:44:11 -05:00
|
|
|
fn is_empty(&self) -> bool { self.len() == 0 }
|
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) {
|
|
|
|
for uint::range(0, self.buckets.len()) |idx| {
|
|
|
|
self.buckets[idx] = 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 true if the map contains a value for the specified key
|
|
|
|
fn contains_key(&self, k: &K) -> bool {
|
|
|
|
match self.bucket_for_key(k) {
|
|
|
|
FoundEntry(_) => {true}
|
|
|
|
TableFull | FoundHole(_) => {false}
|
2013-01-21 17:22:03 -06:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-21 17:22:03 -06:00
|
|
|
|
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-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-04-03 07:45:14 -05:00
|
|
|
/// Insert a key-value pair into the map. An existing value for a
|
|
|
|
/// key is replaced by the new value. Return true if the key did
|
|
|
|
/// not already exist in the map.
|
|
|
|
fn insert(&mut self, k: K, v: V) -> bool {
|
2013-05-04 08:54:58 -05:00
|
|
|
self.swap(k, v).is_none()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Remove a key-value pair from the map. Return true if the key
|
|
|
|
/// was present in the map, otherwise false.
|
|
|
|
fn remove(&mut self, k: &K) -> bool {
|
|
|
|
self.pop(k).is_some()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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-04-03 08:28:36 -05:00
|
|
|
/// Create an empty HashMap 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) -> HashMap<K, V> {
|
2013-04-03 07:45:14 -05:00
|
|
|
linear_map_with_capacity(capacity)
|
|
|
|
}
|
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.
|
|
|
|
pub fn mangle<'a,A>(&'a mut self, k: K, a: A, not_found: &fn(&K, A) -> V,
|
|
|
|
found: &fn(&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-05-05 17:18:51 -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-05-31 17:17:22 -05:00
|
|
|
pub fn find_or_insert_with<'a>(&'a mut self, k: K, f: &fn(&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.
|
|
|
|
pub fn insert_or_update_with<'a>(&'a mut self, k: K, v: V,
|
|
|
|
f: &fn(&K, &mut V)) -> &'a mut V {
|
|
|
|
self.mangle(k, v, |_k,a| a, |k,v,_a| f(k,v))
|
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
/// Calls a function on each element of a hash map, destroying the hash
|
|
|
|
/// map in the process.
|
|
|
|
pub fn consume(&mut self, f: &fn(K, V)) {
|
2013-05-30 12:03:11 -05:00
|
|
|
let buckets = replace(&mut self.buckets,
|
|
|
|
vec::from_fn(INITIAL_CAPACITY, |_| None));
|
2013-04-03 07:45:14 -05:00
|
|
|
self.size = 0;
|
|
|
|
|
2013-07-01 10:26:44 -05:00
|
|
|
for buckets.consume_iter().advance |bucket| {
|
2013-04-03 07:45:14 -05:00
|
|
|
match bucket {
|
|
|
|
None => {},
|
2013-05-05 23:42:54 -05:00
|
|
|
Some(Bucket{key, value, _}) => {
|
2013-04-03 07:45:14 -05:00
|
|
|
f(key, value)
|
2012-10-08 09:05:01 -05:00
|
|
|
}
|
2012-07-26 18:09:22 -05:00
|
|
|
}
|
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2012-08-21 17:55:17 -05:00
|
|
|
|
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-05-05 17:18:51 -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,
|
|
|
|
None => fail!("No entry found for key: %?", k),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-06-24 16:45:00 -05:00
|
|
|
/// Visit all keys
|
|
|
|
pub fn each_key(&self, blk: &fn(k: &K) -> bool) -> bool {
|
|
|
|
self.iter().advance(|(k, _)| blk(k))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Visit all values
|
|
|
|
pub fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) -> bool {
|
|
|
|
self.iter().advance(|(_, v)| blk(v))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Iterate over the map and mutate the contained values
|
|
|
|
pub fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) -> bool {
|
|
|
|
for uint::range(0, self.buckets.len()) |i| {
|
|
|
|
match self.buckets[i] {
|
|
|
|
Some(Bucket{key: ref key, value: ref mut value, _}) => {
|
|
|
|
if !blk(key, value) { return false; }
|
|
|
|
}
|
|
|
|
None => ()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
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-04-03 07:45:14 -05:00
|
|
|
}
|
2012-07-31 16:11:57 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl<K: Hash + Eq, V: Copy> 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-05-05 11:17:59 -05:00
|
|
|
self.find(k).map_consume(|v| copy *v)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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-05-05 11:17:59 -05:00
|
|
|
copy *self.get(k)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-06-21 10:05:26 -05:00
|
|
|
for self.iter().advance |(key, value)| {
|
2013-04-03 07:45:14 -05:00
|
|
|
match other.find(key) {
|
|
|
|
None => return false,
|
|
|
|
Some(v) => if value != v { return false },
|
2012-12-10 11:00:52 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
true
|
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-06-21 10:05:05 -05:00
|
|
|
/// HashMap iterator
|
|
|
|
pub struct HashMapIterator<'self, K, V> {
|
|
|
|
priv iter: vec::VecIterator<'self, Option<Bucket<K, V>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// HashMap mutable values iterator
|
|
|
|
pub struct HashMapMutIterator<'self, K, V> {
|
|
|
|
priv iter: vec::VecMutIterator<'self, Option<Bucket<K, V>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// HashSet iterator
|
|
|
|
pub struct HashSetIterator<'self, K> {
|
|
|
|
priv iter: vec::VecIterator<'self, Option<Bucket<K, ()>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'self, K, V> Iterator<(&'self K, &'self V)> for HashMapIterator<'self, K, V> {
|
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<(&'self K, &'self V)> {
|
|
|
|
for self.iter.advance |elt| {
|
|
|
|
match elt {
|
|
|
|
&Some(ref bucket) => return Some((&bucket.key, &bucket.value)),
|
|
|
|
&None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'self, K, V> Iterator<(&'self K, &'self mut V)> for HashMapMutIterator<'self, K, V> {
|
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<(&'self K, &'self mut V)> {
|
|
|
|
for self.iter.advance |elt| {
|
|
|
|
match elt {
|
|
|
|
&Some(ref mut bucket) => return Some((&bucket.key, &mut bucket.value)),
|
|
|
|
&None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'self, K> Iterator<&'self K> for HashSetIterator<'self, K> {
|
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<&'self K> {
|
|
|
|
for self.iter.advance |elt| {
|
|
|
|
match elt {
|
|
|
|
&Some(ref bucket) => return Some(&bucket.key),
|
|
|
|
&None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-14 10:26:03 -05:00
|
|
|
impl<K: Eq + Hash, V, T: Iterator<(K, V)>> FromIterator<(K, V), T> for HashMap<K, V> {
|
|
|
|
pub fn from_iterator(iter: &mut T) -> HashMap<K, V> {
|
|
|
|
let (lower, _) = iter.size_hint();
|
|
|
|
let mut map = HashMap::with_capacity(lower);
|
|
|
|
|
|
|
|
for iter.advance |(k, v)| {
|
|
|
|
map.insert(k, v);
|
|
|
|
}
|
|
|
|
|
|
|
|
map
|
|
|
|
}
|
|
|
|
}
|
2013-06-21 10:05:05 -05:00
|
|
|
|
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-01-21 20:59:19 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Return true if the set contains no elements
|
2013-06-23 22:44:11 -05:00
|
|
|
fn is_empty(&self) -> bool { self.map.is_empty() }
|
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
|
|
|
/// 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, ()) }
|
2013-01-29 15:07:11 -06:00
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// 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-01-29 16:04:25 -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)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Visit the values representing the difference
|
2013-05-02 17:33:18 -05:00
|
|
|
fn difference(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
2013-06-21 10:05:26 -05:00
|
|
|
self.iter().advance(|v| other.contains(v) || f(v))
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Visit the values representing the symmetric difference
|
2013-05-02 17:33:18 -05:00
|
|
|
fn symmetric_difference(&self,
|
|
|
|
other: &HashSet<T>,
|
|
|
|
f: &fn(&T) -> bool) -> bool {
|
2013-06-21 19:08:35 -05:00
|
|
|
self.difference(other, |t| f(t)) && other.difference(self, |t| f(t))
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Visit the values representing the intersection
|
2013-05-02 17:33:18 -05:00
|
|
|
fn intersection(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
2013-06-21 10:05:26 -05:00
|
|
|
self.iter().advance(|v| !other.contains(v) || f(v))
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
/// Visit the values representing the union
|
2013-05-02 17:33:18 -05:00
|
|
|
fn union(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
|
2013-06-21 19:08:35 -05:00
|
|
|
self.iter().advance(|t| f(t)) &&
|
|
|
|
other.iter().advance(|v| self.contains(v) || f(v))
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-01-20 13:18:24 -06:00
|
|
|
|
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-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-04-03 07:45:14 -05:00
|
|
|
/// Consumes all of the elements in the set, emptying it out
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn consume(&mut self, f: &fn(T)) {
|
2013-04-03 07:45:14 -05:00
|
|
|
self.map.consume(|k, _| f(k))
|
2013-01-20 13:18:24 -06:00
|
|
|
}
|
2013-05-11 10:42:59 -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-04-03 07:45:14 -05:00
|
|
|
}
|
|
|
|
|
2013-07-14 11:20:48 -05:00
|
|
|
impl<K: Eq + Hash, T: Iterator<K>> FromIterator<K, T> for HashSet<K> {
|
|
|
|
pub fn from_iterator(iter: &mut T) -> HashSet<K> {
|
|
|
|
let (lower, _) = iter.size_hint();
|
|
|
|
let mut set = HashSet::with_capacity(lower);
|
|
|
|
|
|
|
|
for iter.advance |k| {
|
|
|
|
set.insert(k);
|
|
|
|
}
|
|
|
|
|
|
|
|
set
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-30 06:02:29 -05:00
|
|
|
#[cfg(test)]
|
2013-04-03 07:45:14 -05:00
|
|
|
mod test_map {
|
|
|
|
use container::{Container, Map, Set};
|
|
|
|
use option::{None, Some};
|
|
|
|
use super::*;
|
|
|
|
use uint;
|
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) {
|
|
|
|
None => fail!(), Some(x) => *x = new
|
|
|
|
}
|
|
|
|
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-04-03 07:45:14 -05:00
|
|
|
let mut m = linear_map_with_capacity(4);
|
|
|
|
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-04-03 07:45:14 -05:00
|
|
|
let mut m = linear_map_with_capacity(4);
|
|
|
|
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-04-03 07:45:14 -05:00
|
|
|
let mut m = linear_map_with_capacity(4);
|
|
|
|
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-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new::<int, int>();
|
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-04-03 08:28:36 -05:00
|
|
|
let mut m = HashMap::new::<int, int>();
|
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() {
|
|
|
|
let mut m = HashMap::new::<int, int>();
|
|
|
|
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-04-15 10:08:52 -05:00
|
|
|
fn test_consume() {
|
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, 3));
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut m2 = HashMap::new();
|
2013-04-03 07:45:14 -05:00
|
|
|
do m.consume |k, v| {
|
|
|
|
m2.insert(k, v);
|
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(m.len(), 0);
|
|
|
|
assert_eq!(m2.len(), 2);
|
|
|
|
assert_eq!(m2.get(&1), &2);
|
|
|
|
assert_eq!(m2.get(&2), &3);
|
2013-04-03 07:45:14 -05:00
|
|
|
}
|
2013-03-02 04:09:36 -06:00
|
|
|
|
2013-05-30 12:03:11 -05:00
|
|
|
#[test]
|
|
|
|
fn test_consume_still_usable() {
|
|
|
|
let mut m = HashMap::new();
|
|
|
|
assert!(m.insert(1, 2));
|
|
|
|
do m.consume |_, _| {}
|
|
|
|
assert!(m.insert(1, 2));
|
|
|
|
}
|
|
|
|
|
2013-04-03 07:45:14 -05:00
|
|
|
#[test]
|
2013-04-15 10:08:52 -05:00
|
|
|
fn test_iterate() {
|
2013-04-03 07:45:14 -05:00
|
|
|
let mut m = linear_map_with_capacity(4);
|
|
|
|
for uint::range(0, 32) |i| {
|
|
|
|
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-06-21 10:05:26 -05:00
|
|
|
for m.iter().advance |(k, v)| {
|
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-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) {
|
|
|
|
None => fail!(),
|
|
|
|
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)];
|
|
|
|
|
|
|
|
let map: HashMap<int, int> = xs.iter().transform(|&x| x).collect();
|
|
|
|
|
|
|
|
for xs.iter().advance |&(k, v)| {
|
|
|
|
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::*;
|
|
|
|
use container::{Container, Map, Set};
|
2013-06-28 11:08:32 -05:00
|
|
|
use vec::ImmutableEqVector;
|
2013-06-21 10:05:16 -05:00
|
|
|
use uint;
|
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();
|
|
|
|
for uint::range(0, 32) |i| {
|
|
|
|
assert!(a.insert(i));
|
|
|
|
}
|
|
|
|
let mut observed = 0;
|
|
|
|
for a.iter().advance |k| {
|
|
|
|
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];
|
|
|
|
for a.intersection(&b) |x| {
|
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];
|
|
|
|
for a.difference(&b) |x| {
|
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];
|
|
|
|
for a.symmetric_difference(&b) |x| {
|
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];
|
|
|
|
for a.union(&b) |x| {
|
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];
|
|
|
|
|
|
|
|
let set: HashSet<int> = xs.iter().transform(|&x| x).collect();
|
|
|
|
|
|
|
|
for xs.iter().advance |x: &int| {
|
|
|
|
assert!(set.contains(x));
|
|
|
|
}
|
|
|
|
}
|
2013-01-29 15:07:11 -06:00
|
|
|
}
|