Skip to content

Commit b2a02b5

Browse files
committed
Fill in documentation for HashSet.
Example how to use the set with a custom type. Fill in examples for the missing methods.
1 parent d9f1d6b commit b2a02b5

File tree

1 file changed

+267
-37
lines changed

1 file changed

+267
-37
lines changed

src/libstd/collections/hashmap.rs

+267-37
Original file line numberDiff line numberDiff line change
@@ -1514,49 +1514,39 @@ pub type SetMoveItems<K> =
15141514
/// println!("{}", *book);
15151515
/// }
15161516
/// ```
1517+
///
1518+
/// The easiest way to use `HashSet` with a custom type is to derive
1519+
/// `Eq` and `Hash`. We must also derive `PartialEq`, this will in the
1520+
/// future be implied by `Eq`.
1521+
///
1522+
/// ```rust
1523+
/// use std::collections::HashSet;
1524+
///
1525+
/// #[deriving(Hash, Eq, PartialEq, Show)]
1526+
/// struct Viking<'a> {
1527+
/// name: &'a str,
1528+
/// power: uint,
1529+
/// }
1530+
///
1531+
/// let mut vikings = HashSet::new();
1532+
///
1533+
/// vikings.insert(Viking { name: "Einar", power: 9u });
1534+
/// vikings.insert(Viking { name: "Einar", power: 9u });
1535+
/// vikings.insert(Viking { name: "Olaf", power: 4u });
1536+
/// vikings.insert(Viking { name: "Harald", power: 8u });
1537+
///
1538+
/// // Use derived implementation to print the vikings.
1539+
/// for x in vikings.iter() {
1540+
/// println!("{}", x);
1541+
/// }
1542+
/// ```
15171543
#[deriving(Clone)]
15181544
pub struct HashSet<T, H = RandomSipHasher> {
15191545
map: HashMap<T, (), H>
15201546
}
15211547

1522-
impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
1523-
fn eq(&self, other: &HashSet<T, H>) -> bool {
1524-
if self.len() != other.len() { return false; }
1525-
1526-
self.iter().all(|key| other.contains(key))
1527-
}
1528-
}
1529-
1530-
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {}
1531-
1532-
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Collection for HashSet<T, H> {
1533-
fn len(&self) -> uint { self.map.len() }
1534-
}
1535-
1536-
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Mutable for HashSet<T, H> {
1537-
fn clear(&mut self) { self.map.clear() }
1538-
}
1539-
1540-
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Set<T> for HashSet<T, H> {
1541-
fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
1542-
1543-
fn is_disjoint(&self, other: &HashSet<T, H>) -> bool {
1544-
self.iter().all(|v| !other.contains(v))
1545-
}
1546-
1547-
fn is_subset(&self, other: &HashSet<T, H>) -> bool {
1548-
self.iter().all(|v| other.contains(v))
1549-
}
1550-
}
1551-
1552-
impl<T: Eq + Hash<S>, S, H: Hasher<S>> MutableSet<T> for HashSet<T, H> {
1553-
fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
1554-
1555-
fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
1556-
}
1557-
15581548
impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
1559-
/// Create an empty HashSet
1549+
/// Create an empty HashSet.
15601550
///
15611551
/// # Example
15621552
///
@@ -1589,6 +1579,17 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
15891579
/// keys.
15901580
///
15911581
/// The hash set is also created with the default initial capacity.
1582+
///
1583+
/// # Example
1584+
///
1585+
/// ```rust
1586+
/// # use std::collections::HashSet;
1587+
/// use std::hash::sip::SipHasher;
1588+
///
1589+
/// let h = SipHasher::new();
1590+
/// let mut set = HashSet::with_hasher(h);
1591+
/// set.insert(2u);
1592+
/// ```
15921593
#[inline]
15931594
pub fn with_hasher(hasher: H) -> HashSet<T, H> {
15941595
HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
@@ -1601,6 +1602,17 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
16011602
/// is designed to allow `HashSet`s to be resistant to attacks that
16021603
/// cause many collisions and very poor performance. Setting it
16031604
/// manually using this function can expose a DoS attack vector.
1605+
///
1606+
/// # Example
1607+
///
1608+
/// ```rust
1609+
/// # use std::collections::HashSet;
1610+
/// use std::hash::sip::SipHasher;
1611+
///
1612+
/// let h = SipHasher::new();
1613+
/// let mut set = HashSet::with_capacity_and_hasher(10u, h);
1614+
/// set.insert(1i);
1615+
/// ```
16041616
#[inline]
16051617
pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> {
16061618
HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
@@ -1621,6 +1633,45 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
16211633

16221634
/// Returns true if the hash set contains a value equivalent to the
16231635
/// given query value.
1636+
///
1637+
/// # Example
1638+
///
1639+
/// This is a slightly silly example where we define the number's
1640+
/// parity as the equivilance class. It is important that the
1641+
/// values hash the same, which is why we implement `Hash`.
1642+
///
1643+
/// ```rust
1644+
/// # use std::collections::HashSet;
1645+
/// use std::hash::Hash;
1646+
/// use std::hash::sip::SipState;
1647+
///
1648+
/// #[deriving(Eq, PartialEq)]
1649+
/// struct EvenOrOdd {
1650+
/// num: uint
1651+
/// };
1652+
///
1653+
/// impl Hash for EvenOrOdd {
1654+
/// fn hash(&self, state: &mut SipState) {
1655+
/// let parity = self.num % 2;
1656+
/// parity.hash(state);
1657+
/// }
1658+
/// }
1659+
///
1660+
/// impl Equiv<EvenOrOdd> for EvenOrOdd {
1661+
/// fn equiv(&self, other: &EvenOrOdd) -> bool {
1662+
/// self.num % 2 == other.num % 2
1663+
/// }
1664+
/// }
1665+
///
1666+
/// let mut set = HashSet::new();
1667+
/// set.insert(EvenOrOdd { num: 3u });
1668+
///
1669+
/// assert!(set.contains_equiv(&EvenOrOdd { num: 3u }));
1670+
/// assert!(set.contains_equiv(&EvenOrOdd { num: 5u }));
1671+
/// assert!(!set.contains_equiv(&EvenOrOdd { num: 4u }));
1672+
/// assert!(!set.contains_equiv(&EvenOrOdd { num: 2u }));
1673+
///
1674+
/// ```
16241675
pub fn contains_equiv<Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool {
16251676
self.map.contains_key_equiv(value)
16261677
}
@@ -1771,7 +1822,154 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
17711822
}
17721823
}
17731824

1825+
impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
1826+
/// Partial equality between sets.
1827+
///
1828+
/// # Example
1829+
///
1830+
/// ```rust
1831+
/// # use std::collections::HashSet;
1832+
/// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
1833+
/// let b: HashSet<int> = [1i, 2, 3, 4].iter().map(|&x| x).collect();
1834+
/// let c: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
1835+
///
1836+
/// assert!(a.eq(&c));
1837+
///
1838+
/// // eq and ne defines the == and != operators
1839+
/// assert!(a == c);
1840+
/// assert!(a != b);
1841+
/// ```
1842+
fn eq(&self, other: &HashSet<T, H>) -> bool {
1843+
if self.len() != other.len() { return false; }
1844+
1845+
self.iter().all(|key| other.contains(key))
1846+
}
1847+
}
1848+
1849+
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {}
1850+
1851+
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Collection for HashSet<T, H> {
1852+
/// Return the number of elements in the set.
1853+
///
1854+
/// # Example
1855+
///
1856+
/// ```rust
1857+
/// # use std::collections::HashSet;
1858+
/// let set: HashSet<int> = [1i, 2, 3, 2].iter().map(|&x| x).collect();
1859+
/// assert_eq!(set.len(), 3);
1860+
/// ```
1861+
fn len(&self) -> uint { self.map.len() }
1862+
}
1863+
1864+
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Mutable for HashSet<T, H> {
1865+
/// Clear the set. Keeps the allocated memory for reuse.
1866+
///
1867+
/// # Example
1868+
///
1869+
/// ```rust
1870+
/// # use std::collections::HashSet;
1871+
/// let mut set: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
1872+
/// set.clear();
1873+
/// assert!(set.is_empty());
1874+
/// ```
1875+
fn clear(&mut self) { self.map.clear() }
1876+
}
1877+
1878+
impl<T: Eq + Hash<S>, S, H: Hasher<S>> Set<T> for HashSet<T, H> {
1879+
/// Return true if `value` is contained by the set.
1880+
///
1881+
/// # Example
1882+
///
1883+
/// ```rust
1884+
/// # use std::collections::HashSet;
1885+
/// let set: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
1886+
/// assert_eq!(set.contains(&1), true);
1887+
/// assert_eq!(set.contains(&4), false);
1888+
/// ```
1889+
fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
1890+
1891+
/// Return true if the set is disjoint with `other`.
1892+
///
1893+
/// # Example
1894+
///
1895+
/// ```rust
1896+
/// # use std::collections::HashSet;
1897+
/// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
1898+
/// let mut b: HashSet<int> = HashSet::new();
1899+
///
1900+
/// assert_eq!(a.is_disjoint(&b), true);
1901+
/// b.insert(4);
1902+
/// assert_eq!(a.is_disjoint(&b), true);
1903+
/// b.insert(1);
1904+
/// assert_eq!(a.is_disjoint(&b), false);
1905+
/// ```
1906+
fn is_disjoint(&self, other: &HashSet<T, H>) -> bool {
1907+
self.iter().all(|v| !other.contains(v))
1908+
}
1909+
1910+
/// Return true if the set is a subset of `other`.
1911+
///
1912+
/// # Example
1913+
///
1914+
/// ```rust
1915+
/// # use std::collections::HashSet;
1916+
/// let sup: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
1917+
/// let mut set: HashSet<int> = HashSet::new();
1918+
///
1919+
/// assert_eq!(set.is_subset(&sup), true);
1920+
/// set.insert(2);
1921+
/// assert_eq!(set.is_subset(&sup), true);
1922+
/// set.insert(4);
1923+
/// assert_eq!(set.is_subset(&sup), false);
1924+
/// ```
1925+
fn is_subset(&self, other: &HashSet<T, H>) -> bool {
1926+
self.iter().all(|v| other.contains(v))
1927+
}
1928+
}
1929+
1930+
impl<T: Eq + Hash<S>, S, H: Hasher<S>> MutableSet<T> for HashSet<T, H> {
1931+
/// Insert an element.
1932+
///
1933+
/// # Example
1934+
///
1935+
/// ```rust
1936+
/// # use std::collections::HashSet;
1937+
/// let mut set = HashSet::new();
1938+
/// set.insert(2i);
1939+
/// set.insert(2i);
1940+
/// assert_eq!(set.len(), 1);
1941+
/// ```
1942+
fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
1943+
1944+
/// Remove an element.
1945+
///
1946+
/// # Example
1947+
///
1948+
/// ```rust
1949+
/// # use std::collections::HashSet;
1950+
/// let mut set = HashSet::new();
1951+
/// set.insert(2i);
1952+
///
1953+
/// // Return boolean success flag.
1954+
/// assert_eq!(set.remove(&2), true);
1955+
/// assert_eq!(set.remove(&2), false);
1956+
/// ```
1957+
fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
1958+
}
1959+
1960+
17741961
impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
1962+
/// Implement the `Show` trait for easy output format. The values in the
1963+
/// set must also implement `Show`.
1964+
///
1965+
/// # Example
1966+
///
1967+
/// ```rust
1968+
/// # use std::collections::HashSet;
1969+
/// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
1970+
/// // Will call .fmt() to print, in some order.
1971+
/// println!("{}", a);
1972+
/// ```
17751973
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
17761974
try!(write!(f, "{{"));
17771975

@@ -1785,6 +1983,17 @@ impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
17851983
}
17861984

17871985
impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> {
1986+
/// Build a set from an external iterator.
1987+
///
1988+
/// # Example
1989+
///
1990+
/// ```rust
1991+
/// # use std::collections::HashSet;
1992+
/// let values = vec!(1i, 2, 3);
1993+
/// let set: HashSet<int> = values.move_iter().collect();
1994+
/// let another_set: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
1995+
/// assert_eq!(set, another_set);
1996+
/// ```
17881997
fn from_iter<I: Iterator<T>>(iter: I) -> HashSet<T, H> {
17891998
let (lower, _) = iter.size_hint();
17901999
let mut set = HashSet::with_capacity_and_hasher(lower, Default::default());
@@ -1794,6 +2003,18 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T,
17942003
}
17952004

17962005
impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extendable<T> for HashSet<T, H> {
2006+
/// Extend the set with the values yielded by an iterator.
2007+
///
2008+
/// # Example
2009+
///
2010+
/// ```rust
2011+
/// # use std::collections::HashSet;
2012+
/// let values = vec!(1i, 2, 3);
2013+
/// let mut set = HashSet::new();
2014+
/// set.insert(0i);
2015+
/// set.extend(values.move_iter());
2016+
/// assert_eq!(set.len(), 4);
2017+
/// ```
17972018
fn extend<I: Iterator<T>>(&mut self, mut iter: I) {
17982019
for k in iter {
17992020
self.insert(k);
@@ -1802,6 +2023,15 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extendable<T> for HashSet<T, H>
18022023
}
18032024

18042025
impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
2026+
/// Create a default set.
2027+
///
2028+
/// # Example
2029+
///
2030+
/// ```rust
2031+
/// # use std::collections::HashSet;
2032+
/// use std::default::Default;
2033+
/// let mut set: HashSet<int> = Default::default();
2034+
/// ```
18052035
fn default() -> HashSet<T, H> {
18062036
HashSet::with_hasher(Default::default())
18072037
}

0 commit comments

Comments
 (0)