diff --git a/maps/hashmap/hashmap.go b/maps/hashmap/hashmap.go new file mode 100644 index 0000000..3aa5585 --- /dev/null +++ b/maps/hashmap/hashmap.go @@ -0,0 +1,102 @@ +/* +Copyright (c) Emir Pasic, All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. See the file LICENSE included +with this distribution for more information. +*/ + +// Implementation of unorder map backed by a hash table. +// Elements are unordered in the map. +// Structure is not thread safe. +// References: http://en.wikipedia.org/wiki/Associative_array + +package hashmap + +import ( + "fmt" + "github.com/emirpasic/gods/maps" +) + +func assertInterfaceImplementation() { + var _ maps.Interface = (*Map)(nil) +} + +type Map struct { + m map[interface{}]interface{} +} + +// Instantiates a hash map. +func New() *Map { + return &Map{m: make(map[interface{}]interface{})} +} + +// Inserts element into the map. +func (m *Map) Put(key interface{}, value interface{}) { + m.m[key] = value +} + +// Searches the elemnt in the map by key and returns its value or nil if key is not found in map. +// Second return parameter is true if key was found, otherwise false. +func (m *Map) Get(key interface{}) (value interface{}, found bool) { + value, found = m.m[key] + return +} + +// Remove the element from the map by key. +func (m *Map) Remove(key interface{}) { + delete(m.m, key) +} + +// Returns true if map does not contain any elements +func (m *Map) Empty() bool { + return m.Size() == 0 +} + +// Returns number of elements in the map. +func (m *Map) Size() int { + return len(m.m) +} + +// Returns all keys (random order). +func (m *Map) Keys() []interface{} { + keys := make([]interface{}, m.Size()) + count := 0 + for key, _ := range m.m { + keys[count] = key + count += 1 + } + return keys +} + +// Returns all values (random order). +func (m *Map) Values() []interface{} { + values := make([]interface{}, m.Size()) + count := 0 + for _, value := range m.m { + values[count] = value + count += 1 + } + return values +} + +// Removes all elements from the map. +func (m *Map) Clear() { + m.m = make(map[interface{}]interface{}) +} + +func (m *Map) String() string { + str := "HashMap\n" + str += fmt.Sprintf("%v", m.m) + return str +} diff --git a/maps/hashmap/hashmap_test.go b/maps/hashmap/hashmap_test.go new file mode 100644 index 0000000..34b2242 --- /dev/null +++ b/maps/hashmap/hashmap_test.go @@ -0,0 +1,171 @@ +/* +Copyright (c) Emir Pasic, All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library. See the file LICENSE included +with this distribution for more information. +*/ + +package hashmap + +import ( + "fmt" + "testing" +) + +func TestHashMap(t *testing.T) { + + m := New() + + // insertions + m.Put(5, "e") + m.Put(6, "f") + m.Put(7, "g") + m.Put(3, "c") + m.Put(4, "d") + m.Put(1, "x") + m.Put(2, "b") + m.Put(1, "a") //overwrite + + // Test Size() + if actualValue := m.Size(); actualValue != 7 { + t.Errorf("Got %v expected %v", actualValue, 7) + } + + // test Keys() + if actualValue, expactedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expactedValue) { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + + // test Values() + if actualValue, expactedValue := m.Values(), []interface{}{"a", "b", "c", "d", "e", "f", "g"}; !sameElements(actualValue, expactedValue) { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + + // key,expectedValue,expectedFound + tests1 := [][]interface{}{ + {1, "a", true}, + {2, "b", true}, + {3, "c", true}, + {4, "d", true}, + {5, "e", true}, + {6, "f", true}, + {7, "g", true}, + {8, nil, false}, + } + + for _, test := range tests1 { + // retrievals + actualValue, actualFound := m.Get(test[0]) + if actualValue != test[1] || actualFound != test[2] { + t.Errorf("Got %v expected %v", actualValue, test[1]) + } + } + + // removals + m.Remove(5) + m.Remove(6) + m.Remove(7) + m.Remove(8) + m.Remove(5) + + // test Keys() + if actualValue, expactedValue := m.Keys(), []interface{}{1, 2, 3, 4}; !sameElements(actualValue, expactedValue) { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + + // test Values() + if actualValue, expactedValue := m.Values(), []interface{}{"a", "b", "c", "d"}; !sameElements(actualValue, expactedValue) { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + // Test Size() + if actualValue := m.Size(); actualValue != 4 { + t.Errorf("Got %v expected %v", actualValue, 7) + } + + tests2 := [][]interface{}{ + {1, "a", true}, + {2, "b", true}, + {3, "c", true}, + {4, "d", true}, + {5, nil, false}, + {6, nil, false}, + {7, nil, false}, + {8, nil, false}, + } + + for _, test := range tests2 { + // retrievals + actualValue, actualFound := m.Get(test[0]) + if actualValue != test[1] || actualFound != test[2] { + t.Errorf("Got %v expected %v", actualValue, test[1]) + } + } + + // removals + m.Remove(1) + m.Remove(4) + m.Remove(2) + m.Remove(3) + m.Remove(2) + m.Remove(2) + + // Test Keys() + if actualValue, expactedValue := fmt.Sprintf("", m.Keys()...), ""; actualValue != expactedValue { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + + // test Values() + if actualValue, expactedValue := fmt.Sprintf("", m.Values()...), ""; actualValue != expactedValue { + t.Errorf("Got %v expected %v", actualValue, expactedValue) + } + + // Test Size() + if actualValue := m.Size(); actualValue != 0 { + t.Errorf("Got %v expected %v", actualValue, 0) + } + + // Test Empty() + if actualValue := m.Empty(); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + + m.Put(1, "a") + m.Put(2, "b") + m.Clear() + + // Test Empty() + if actualValue := m.Empty(); actualValue != true { + t.Errorf("Got %v expected %v", actualValue, true) + } + +} + +func sameElements(a []interface{}, b []interface{}) bool { + if len(a) != len(b) { + return false + } + for _, av := range a { + found := false + for _, bv := range b { + if av == bv { + found = true + break + } + } + if !found { + return false + } + } + return true +} diff --git a/maps/treemap/treemap.go b/maps/treemap/treemap.go index f659595..f5b9636 100644 --- a/maps/treemap/treemap.go +++ b/maps/treemap/treemap.go @@ -17,6 +17,7 @@ with this distribution for more information. */ // Implementation of order map backed by red-black tree. +// Elements are ordered by key in the map. // Structure is not thread safe. // References: http://en.wikipedia.org/wiki/Associative_array @@ -51,31 +52,31 @@ func NewWithStringComparator() *Map { return &Map{tree: rbt.NewWithStringComparator()} } -// Inserts node into the map. +// Inserts key-value pair into the map. // Key should adhere to the comparator's type assertion, otherwise method panics. func (m *Map) Put(key interface{}, value interface{}) { m.tree.Put(key, value) } -// Searches the node in the map by key and returns its value or nil if key is not found in tree. +// Searches the element in the map by key and returns its value or nil if key is not found in tree. // Second return parameter is true if key was found, otherwise false. // Key should adhere to the comparator's type assertion, otherwise method panics. func (m *Map) Get(key interface{}) (value interface{}, found bool) { return m.tree.Get(key) } -// Remove the node from the map by key. +// Remove the element from the map by key. // Key should adhere to the comparator's type assertion, otherwise method panics. func (m *Map) Remove(key interface{}) { m.tree.Remove(key) } -// Returns true if map does not contain any nodes +// Returns true if map does not contain any elements func (m *Map) Empty() bool { return m.tree.Empty() } -// Returns number of items in the map. +// Returns number of elements in the map. func (m *Map) Size() int { return m.tree.Size() } @@ -90,7 +91,7 @@ func (m *Map) Values() []interface{} { return m.tree.Values() } -// Removes all nodes from the map. +// Removes all elements from the map. func (m *Map) Clear() { m.tree.Clear() } diff --git a/maps/treemap/treemap_test.go b/maps/treemap/treemap_test.go index 83c6809..cd7889e 100644 --- a/maps/treemap/treemap_test.go +++ b/maps/treemap/treemap_test.go @@ -23,7 +23,7 @@ import ( "testing" ) -func TestRedBlackTree(t *testing.T) { +func TestTreeMap(t *testing.T) { m := NewWithIntComparator() diff --git a/sets/treeset/treeset_test.go b/sets/treeset/treeset_test.go index e9c317c..1d7b28c 100644 --- a/sets/treeset/treeset_test.go +++ b/sets/treeset/treeset_test.go @@ -23,7 +23,7 @@ import ( "testing" ) -func TestHashSet(t *testing.T) { +func TestTreeSet(t *testing.T) { set := NewWithIntComparator()