3 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * Copyright (C) 1997-2000 GLib Team and others
5 * Copyright (C) 2007-2008 Jürg Billeter
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * Jürg Billeter <j@bitron.ch>
28 * Hashtable implementation of the Set interface.
30 public class Gee.HashSet<G> : Object, Iterable<G>, Collection<G>, Set<G> {
32 get { return _nnodes; }
35 public HashFunc hash_func {
36 set { _hash_func = value; }
39 public EqualFunc equal_func {
40 set { _equal_func = value; }
43 private int _array_size;
45 private Node<G>[] _nodes;
47 // concurrent modification protection
48 private int _stamp = 0;
50 private HashFunc _hash_func;
51 private EqualFunc _equal_func;
53 private const int MIN_SIZE = 11;
54 private const int MAX_SIZE = 13845163;
56 public HashSet (HashFunc hash_func = GLib.direct_hash, EqualFunc equal_func = GLib.direct_equal) {
57 this.hash_func = hash_func;
58 this.equal_func = equal_func;
62 _array_size = MIN_SIZE;
63 _nodes = new Node<G>[_array_size];
66 private Node<G>** lookup_node (G key) {
67 uint hash_value = _hash_func (key);
68 Node<G>** node = &_nodes[hash_value % _array_size];
69 while ((*node) != null && (hash_value != (*node)->key_hash || !_equal_func ((*node)->key, key))) {
70 node = &((*node)->next);
75 public bool contains (G key) {
76 Node<G>** node = lookup_node (key);
77 return (*node != null);
80 public Type get_element_type () {
84 public Gee.Iterator<G> iterator () {
85 return new Iterator<G> (this);
88 public bool add (G key) {
89 Node<G>** node = lookup_node (key);
93 uint hash_value = _hash_func (key);
94 *node = new Node<G> (key, hash_value);
102 public bool remove (G key) {
103 Node<G>** node = lookup_node (key);
106 *node = (*node)->next;
115 public void clear () {
116 for (int i = 0; i < _array_size; i++) {
117 Node<G> node = #_nodes[i];
118 while (node != null) {
119 Node next = #node.next;
128 private void resize () {
129 if ((_array_size >= 3 * _nnodes && _array_size >= MIN_SIZE) ||
130 (3 * _array_size <= _nnodes && _array_size < MAX_SIZE)) {
131 int new_array_size = (int) SpacedPrimes.closest (_nnodes);
132 new_array_size = new_array_size.clamp (MIN_SIZE, MAX_SIZE);
134 Node<G>[] new_nodes = new Node<G>[new_array_size];
136 for (int i = 0; i < _array_size; i++) {
139 for (node = #_nodes[i]; node != null; node = #next) {
141 uint hash_val = node.key_hash % new_array_size;
142 node.next = #new_nodes[hash_val];
143 new_nodes[hash_val] = #node;
147 _array_size = new_array_size;
156 private class Node<G> {
159 public uint key_hash;
161 public Node (G# k, uint hash) {
167 private class Iterator<G> : Object, Gee.Iterator<G> {
168 public HashSet<G> set {
171 _stamp = _set._stamp;
175 private HashSet<G> _set;
176 private int _index = -1;
177 private weak Node<G> _node;
179 // concurrent modification protection
180 private int _stamp = 0;
182 public Iterator (HashSet set) {
186 public bool next () {
190 while (_node == null && _index + 1 < _set._array_size) {
192 _node = _set._nodes[_index];
194 return (_node != null);
198 assert (_stamp == _set._stamp);
199 assert (_node != null);