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-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};
|
|
|
|
use hash::Hash;
|
2013-07-15 20:55:52 -05:00
|
|
|
use iterator::{Iterator, IteratorUtil, FromIterator, ChainIterator};
|
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;
|
2013-05-04 08:54:58 -05:00
|
|
|
use util::{replace, unreachable};
|
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 {
|
|
|
|
((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-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-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
|
|
|
/// 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))
|
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
pub fn consume(self) -> HashMapConsumeIterator<K, V> {
|
|
|
|
// `consume_rev_iter` is more efficient than `consume_iter` for vectors
|
|
|
|
HashMapConsumeIterator {iter: self.buckets.consume_rev_iter()}
|
|
|
|
}
|
|
|
|
|
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-07-02 14:47:32 -05:00
|
|
|
self.find(k).map_consume(|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-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-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());
|
|
|
|
for self.iter().advance |(key, value)| {
|
|
|
|
new_map.insert((*key).clone(), (*value).clone());
|
|
|
|
}
|
|
|
|
new_map
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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>>>,
|
|
|
|
}
|
|
|
|
|
2013-07-15 13:43:16 -05:00
|
|
|
/// HashMap consume iterator
|
|
|
|
pub struct HashMapConsumeIterator<K, V> {
|
|
|
|
priv iter: vec::VecConsumeRevIterator<Option<Bucket<K, V>>>,
|
|
|
|
}
|
|
|
|
|
2013-06-21 10:05:05 -05:00
|
|
|
/// HashSet iterator
|
|
|
|
pub struct HashSetIterator<'self, K> {
|
|
|
|
priv iter: vec::VecIterator<'self, Option<Bucket<K, ()>>>,
|
|
|
|
}
|
|
|
|
|
2013-07-15 13:43:16 -05:00
|
|
|
/// HashSet consume iterator
|
|
|
|
pub struct HashSetConsumeIterator<K> {
|
|
|
|
priv iter: vec::VecConsumeRevIterator<Option<Bucket<K, ()>>>,
|
|
|
|
}
|
|
|
|
|
2013-06-21 10:05:05 -05:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-15 13:43:16 -05:00
|
|
|
impl<K, V> Iterator<(K, V)> for HashMapConsumeIterator<K, V> {
|
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<(K, V)> {
|
|
|
|
for self.iter.advance |elt| {
|
|
|
|
match elt {
|
|
|
|
Some(Bucket {key, value, _}) => return Some((key, value)),
|
|
|
|
None => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-21 10:05:05 -05:00
|
|
|
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-15 13:43:16 -05:00
|
|
|
impl<K> Iterator<K> for HashSetConsumeIterator<K> {
|
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<K> {
|
|
|
|
for self.iter.advance |elt| {
|
|
|
|
match elt {
|
|
|
|
Some(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-07-14 12:18:50 -05:00
|
|
|
}
|
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
|
|
|
/// 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-07-15 20:55:52 -05:00
|
|
|
self.difference_iter(other).advance(f)
|
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-07-15 20:55:52 -05:00
|
|
|
self.symmetric_difference_iter(other).advance(f)
|
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-07-15 20:55:52 -05:00
|
|
|
self.intersection_iter(other).advance(f)
|
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-07-15 20:55:52 -05:00
|
|
|
self.union_iter(other).advance(f)
|
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-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-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.
|
|
|
|
pub fn consume(self) -> HashSetConsumeIterator<T> {
|
|
|
|
// `consume_rev_iter` is more efficient than `consume_iter` for vectors
|
|
|
|
HashSetConsumeIterator {iter: self.map.buckets.consume_rev_iter()}
|
|
|
|
}
|
|
|
|
|
2013-07-15 20:55:52 -05:00
|
|
|
/// Visit the values representing the difference
|
|
|
|
pub fn difference_iter<'a>(&'a self, other: &'a HashSet<T>)
|
|
|
|
-> SetAlgebraIter<'a, T> {
|
|
|
|
EnvFilterIterator{iter: self.iter(), env: other,
|
|
|
|
filter: |elt, other| !other.contains(elt) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Visit the values representing the symmetric difference
|
|
|
|
pub fn symmetric_difference_iter<'a>(&'a self, other: &'a HashSet<T>)
|
|
|
|
-> ChainIterator<&'a T, SetAlgebraIter<'a, T>, SetAlgebraIter<'a, T>> {
|
|
|
|
self.difference_iter(other).chain_(other.difference_iter(self))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Visit the values representing the intersection
|
|
|
|
pub fn intersection_iter<'a>(&'a self, other: &'a HashSet<T>)
|
|
|
|
-> SetAlgebraIter<'a, T> {
|
|
|
|
EnvFilterIterator{iter: self.iter(), env: other,
|
|
|
|
filter: |elt, other| other.contains(elt) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Visit the values representing the union
|
|
|
|
pub fn union_iter<'a>(&'a self, other: &'a HashSet<T>)
|
|
|
|
-> ChainIterator<&'a T, HashSetIterator<'a, T>, SetAlgebraIter<'a, T>> {
|
|
|
|
self.iter().chain_(other.difference_iter(self))
|
|
|
|
}
|
|
|
|
|
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-07-14 12:18:50 -05:00
|
|
|
|
2013-07-15 20:55:52 -05:00
|
|
|
// FIXME #7814: use std::iterator::FilterIterator
|
|
|
|
/// Building block for Set operation iterators
|
|
|
|
pub struct EnvFilterIterator<A, Env, I> {
|
|
|
|
priv env: Env,
|
|
|
|
priv filter: &'static fn(&A, Env) -> bool,
|
|
|
|
priv iter: I,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'self, A, Env: Clone, I: Iterator<&'self A>> Iterator<&'self A>
|
|
|
|
for EnvFilterIterator<A, Env, I> {
|
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) -> Option<&'self A> {
|
|
|
|
loop {
|
|
|
|
match self.iter.next() {
|
|
|
|
Some(elt) => if (self.filter)(elt, self.env.clone()) {
|
|
|
|
return Some(elt)
|
|
|
|
},
|
|
|
|
None => return None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn size_hint(&self) -> (uint, Option<uint>) {
|
|
|
|
let (_, upper) = self.iter.size_hint();
|
|
|
|
(0, upper)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set operations iterator
|
|
|
|
pub type SetAlgebraIter<'self, T> =
|
|
|
|
EnvFilterIterator<T, &'self HashSet<T>, HashSetIterator<'self, T>>;
|
|
|
|
|
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-07-17 14:32:49 -05:00
|
|
|
use container::{Container, Map};
|
2013-04-03 07:45:14 -05:00
|
|
|
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-07-15 13:43:16 -05:00
|
|
|
let hm = {
|
|
|
|
let mut hm = HashMap::new();
|
|
|
|
|
|
|
|
hm.insert('a', 1);
|
|
|
|
hm.insert('b', 2);
|
|
|
|
|
|
|
|
hm
|
|
|
|
};
|
|
|
|
|
2013-07-16 09:39:24 -05:00
|
|
|
let v = hm.consume().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-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)];
|
2013-07-14 12:18:50 -05:00
|
|
|
|
2013-07-14 10:26:03 -05:00
|
|
|
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::*;
|
2013-07-17 14:32:49 -05:00
|
|
|
use container::Container;
|
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];
|
2013-07-15 20:55:52 -05:00
|
|
|
for a.intersection_iter(&b).advance |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];
|
2013-07-15 20:55:52 -05:00
|
|
|
for a.difference_iter(&b).advance |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];
|
2013-07-15 20:55:52 -05:00
|
|
|
for a.symmetric_difference_iter(&b).advance |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];
|
2013-07-15 20:55:52 -05:00
|
|
|
for a.union_iter(&b).advance |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];
|
2013-07-14 12:18:50 -05:00
|
|
|
|
2013-07-14 11:20:48 -05:00
|
|
|
let set: HashSet<int> = xs.iter().transform(|&x| x).collect();
|
|
|
|
|
|
|
|
for xs.iter().advance |x: &int| {
|
|
|
|
assert!(set.contains(x));
|
|
|
|
}
|
|
|
|
}
|
2013-07-15 13:43:16 -05:00
|
|
|
|
|
|
|
#[test]
|
2013-07-16 09:39:24 -05:00
|
|
|
fn test_consume() {
|
2013-07-15 13:43:16 -05:00
|
|
|
let hs = {
|
|
|
|
let mut hs = HashSet::new();
|
|
|
|
|
|
|
|
hs.insert('a');
|
|
|
|
hs.insert('b');
|
|
|
|
|
|
|
|
hs
|
|
|
|
};
|
|
|
|
|
2013-07-16 09:39:24 -05:00
|
|
|
let v = hs.consume().collect::<~[char]>();
|
2013-07-15 13:43:16 -05:00
|
|
|
assert!(['a', 'b'] == v || ['b', 'a'] == v);
|
|
|
|
}
|
2013-01-29 15:07:11 -06:00
|
|
|
}
|