mirror of
https://github.com/emirpasic/gods
synced 2024-11-18 09:25:50 +00:00
commit
7aedbffbed
40
README.md
40
README.md
@ -21,6 +21,7 @@ Implementation of various data structures and algorithms in Go.
|
|||||||
- [Maps](#maps)
|
- [Maps](#maps)
|
||||||
- [HashMap](#hashmap)
|
- [HashMap](#hashmap)
|
||||||
- [TreeMap](#treemap)
|
- [TreeMap](#treemap)
|
||||||
|
- [LinkedHashMap](#linkedhashmap)
|
||||||
- [HashBidiMap](#hashbidimap)
|
- [HashBidiMap](#hashbidimap)
|
||||||
- [TreeBidiMap](#treebidimap)
|
- [TreeBidiMap](#treebidimap)
|
||||||
- [Trees](#trees)
|
- [Trees](#trees)
|
||||||
@ -63,23 +64,24 @@ Containers are either ordered or unordered. All ordered containers provide [stat
|
|||||||
|
|
||||||
| **Data** | **Structure** | **Ordered** | **[Iterator](#iterator)** | **[Enumerable](#enumerable)** | **Referenced by** |
|
| **Data** | **Structure** | **Ordered** | **[Iterator](#iterator)** | **[Enumerable](#enumerable)** | **Referenced by** |
|
||||||
| :--- | :--- | :---: | :---: | :---: | :---: |
|
| :--- | :--- | :---: | :---: | :---: | :---: |
|
||||||
| **[Lists](#lists)** |
|
| [Lists](#lists) |
|
||||||
| | [ArrayList](#arraylist) | yes | yes* | yes | index |
|
| | [ArrayList](#arraylist) | yes | yes* | yes | index |
|
||||||
| | [SinglyLinkedList](#singlylinkedlist) | yes | yes | yes | index |
|
| | [SinglyLinkedList](#singlylinkedlist) | yes | yes | yes | index |
|
||||||
| | [DoublyLinkedList](#doublylinkedlist) | yes | yes* | yes | index |
|
| | [DoublyLinkedList](#doublylinkedlist) | yes | yes* | yes | index |
|
||||||
| **[Sets](#sets)** |
|
| [Sets](#sets) |
|
||||||
| | [HashSet](#hashset) | no | no | no | index |
|
| | [HashSet](#hashset) | no | no | no | index |
|
||||||
| | [TreeSet](#treeset) | yes | yes* | yes | index |
|
| | [TreeSet](#treeset) | yes | yes* | yes | index |
|
||||||
| | [LinkedHashSet](#linkedhashset) | yes | yes* | yes | index |
|
| | [LinkedHashSet](#linkedhashset) | yes | yes* | yes | index |
|
||||||
| **[Stacks](#stacks)** |
|
| [Stacks](#stacks) |
|
||||||
| | [LinkedListStack](#linkedliststack) | yes | yes | no | index |
|
| | [LinkedListStack](#linkedliststack) | yes | yes | no | index |
|
||||||
| | [ArrayStack](#arraystack) | yes | yes* | no | index |
|
| | [ArrayStack](#arraystack) | yes | yes* | no | index |
|
||||||
| **[Maps](#maps)** |
|
| [Maps](#maps) |
|
||||||
| | [HashMap](#hashmap) | no | no | no | key |
|
| | [HashMap](#hashmap) | no | no | no | key |
|
||||||
| | [TreeMap](#treemap) | yes | yes* | yes | key |
|
| | [TreeMap](#treemap) | yes | yes* | yes | key |
|
||||||
|
| | [LinkedHashMap](#linkedhashmap) | yes | yes* | yes | key |
|
||||||
| | [HashBidiMap](#hashbidimap) | no | no | no | key* |
|
| | [HashBidiMap](#hashbidimap) | no | no | no | key* |
|
||||||
| **[Trees](#trees)** |
|
|
||||||
| | [TreeBidiMap](#treebidimap) | yes | yes* | yes | key* |
|
| | [TreeBidiMap](#treebidimap) | yes | yes* | yes | key* |
|
||||||
|
| [Trees](#trees) |
|
||||||
| | [RedBlackTree](#redblacktree) | yes | yes* | no | key |
|
| | [RedBlackTree](#redblacktree) | yes | yes* | no | key |
|
||||||
| | [AVLTree](#avltree) | yes | yes* | no | key |
|
| | [AVLTree](#avltree) | yes | yes* | no | key |
|
||||||
| | [BTree](#btree) | yes | yes* | no | key |
|
| | [BTree](#btree) | yes | yes* | no | key |
|
||||||
@ -487,6 +489,34 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### LinkedHashMap
|
||||||
|
|
||||||
|
A [map](#maps) that preserves insertion-order. It is backed by a hash table to store values and [doubly-linked list](doublylinkedlist) to store ordering.
|
||||||
|
|
||||||
|
Implements [Map](#maps), [IteratorWithKey](#iteratorwithkey), [EnumerableWithKey](#enumerablewithkey), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces.
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/maps/linkedhashmap"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
m := linkedhashmap.New() // empty (keys are of type int)
|
||||||
|
m.Put(2, "b") // 2->b
|
||||||
|
m.Put(1, "x") // 2->b, 1->x (insertion-order)
|
||||||
|
m.Put(1, "a") // 2->b, 1->a (insertion-order)
|
||||||
|
_, _ = m.Get(2) // b, true
|
||||||
|
_, _ = m.Get(3) // nil, false
|
||||||
|
_ = m.Values() // []interface {}{"b", "a"} (insertion-order)
|
||||||
|
_ = m.Keys() // []interface {}{2, 1} (insertion-order)
|
||||||
|
m.Remove(1) // 2->b
|
||||||
|
m.Clear() // empty
|
||||||
|
m.Empty() // true
|
||||||
|
m.Size() // 0
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
#### HashBidiMap
|
#### HashBidiMap
|
||||||
|
|
||||||
A [map](#maps) based on two hashmaps. Keys are unordered.
|
A [map](#maps) based on two hashmaps. Keys are unordered.
|
||||||
|
23
examples/linkedhashmap/linkedhashmap.go
Normal file
23
examples/linkedhashmap/linkedhashmap.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/maps/linkedhashmap"
|
||||||
|
|
||||||
|
// LinkedHashMapExample to demonstrate basic usage of LinkedHashMapExample
|
||||||
|
func main() {
|
||||||
|
m := linkedhashmap.New() // empty (keys are of type int)
|
||||||
|
m.Put(2, "b") // 2->b
|
||||||
|
m.Put(1, "x") // 2->b, 1->x (insertion-order)
|
||||||
|
m.Put(1, "a") // 2->b, 1->a (insertion-order)
|
||||||
|
_, _ = m.Get(2) // b, true
|
||||||
|
_, _ = m.Get(3) // nil, false
|
||||||
|
_ = m.Values() // []interface {}{"b", "a"} (insertion-order)
|
||||||
|
_ = m.Keys() // []interface {}{2, 1} (insertion-order)
|
||||||
|
m.Remove(1) // 2->b
|
||||||
|
m.Clear() // empty
|
||||||
|
m.Empty() // true
|
||||||
|
m.Size() // 0
|
||||||
|
}
|
@ -14,12 +14,12 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Map)(nil)
|
var _ containers.JSONDeserializer = (*Map)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the map.
|
||||||
func (m *Map) ToJSON() ([]byte, error) {
|
func (m *Map) ToJSON() ([]byte, error) {
|
||||||
return m.forwardMap.ToJSON()
|
return m.forwardMap.ToJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the map from the input JSON representation.
|
||||||
func (m *Map) FromJSON(data []byte) error {
|
func (m *Map) FromJSON(data []byte) error {
|
||||||
elements := make(map[string]interface{})
|
elements := make(map[string]interface{})
|
||||||
err := json.Unmarshal(data, &elements)
|
err := json.Unmarshal(data, &elements)
|
||||||
|
@ -15,7 +15,7 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Map)(nil)
|
var _ containers.JSONDeserializer = (*Map)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the map.
|
||||||
func (m *Map) ToJSON() ([]byte, error) {
|
func (m *Map) ToJSON() ([]byte, error) {
|
||||||
elements := make(map[string]interface{})
|
elements := make(map[string]interface{})
|
||||||
for key, value := range m.m {
|
for key, value := range m.m {
|
||||||
@ -24,7 +24,7 @@ func (m *Map) ToJSON() ([]byte, error) {
|
|||||||
return json.Marshal(&elements)
|
return json.Marshal(&elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the map from the input JSON representation.
|
||||||
func (m *Map) FromJSON(data []byte) error {
|
func (m *Map) FromJSON(data []byte) error {
|
||||||
elements := make(map[string]interface{})
|
elements := make(map[string]interface{})
|
||||||
err := json.Unmarshal(data, &elements)
|
err := json.Unmarshal(data, &elements)
|
||||||
|
80
maps/linkedhashmap/enumerable.go
Normal file
80
maps/linkedhashmap/enumerable.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package linkedhashmap
|
||||||
|
|
||||||
|
import "github.com/emirpasic/gods/containers"
|
||||||
|
|
||||||
|
func assertEnumerableImplementation() {
|
||||||
|
var _ containers.EnumerableWithKey = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each calls the given function once for each element, passing that element's key and value.
|
||||||
|
func (m *Map) Each(f func(key interface{}, value interface{})) {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
f(iterator.Key(), iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map invokes the given function once for each element and returns a container
|
||||||
|
// containing the values returned by the given function as key/value pairs.
|
||||||
|
func (m *Map) Map(f func(key1 interface{}, value1 interface{}) (interface{}, interface{})) *Map {
|
||||||
|
newMap := New()
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
key2, value2 := f(iterator.Key(), iterator.Value())
|
||||||
|
newMap.Put(key2, value2)
|
||||||
|
}
|
||||||
|
return newMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select returns a new container containing all elements for which the given function returns a true value.
|
||||||
|
func (m *Map) Select(f func(key interface{}, value interface{}) bool) *Map {
|
||||||
|
newMap := New()
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Key(), iterator.Value()) {
|
||||||
|
newMap.Put(iterator.Key(), iterator.Value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any passes each element of the container to the given function and
|
||||||
|
// returns true if the function ever returns true for any element.
|
||||||
|
func (m *Map) Any(f func(key interface{}, value interface{}) bool) bool {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Key(), iterator.Value()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// All passes each element of the container to the given function and
|
||||||
|
// returns true if the function returns true for all elements.
|
||||||
|
func (m *Map) All(f func(key interface{}, value interface{}) bool) bool {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if !f(iterator.Key(), iterator.Value()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find passes each element of the container to the given function and returns
|
||||||
|
// the first (key,value) for which the function is true or nil,nil otherwise if no element
|
||||||
|
// matches the criteria.
|
||||||
|
func (m *Map) Find(f func(key interface{}, value interface{}) bool) (interface{}, interface{}) {
|
||||||
|
iterator := m.Iterator()
|
||||||
|
for iterator.Next() {
|
||||||
|
if f(iterator.Key(), iterator.Value()) {
|
||||||
|
return iterator.Key(), iterator.Value()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
81
maps/linkedhashmap/iterator.go
Normal file
81
maps/linkedhashmap/iterator.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package linkedhashmap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
"github.com/emirpasic/gods/lists/doublylinkedlist"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertIteratorImplementation() {
|
||||||
|
var _ containers.ReverseIteratorWithKey = (*Iterator)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator holding the iterator's state
|
||||||
|
type Iterator struct {
|
||||||
|
iterator doublylinkedlist.Iterator
|
||||||
|
table map[interface{}]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterator returns a stateful iterator whose elements are key/value pairs.
|
||||||
|
func (m *Map) Iterator() Iterator {
|
||||||
|
return Iterator{
|
||||||
|
iterator: m.ordering.Iterator(),
|
||||||
|
table: m.table}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
// If Next() returns true, then next element's key and value can be retrieved by Key() and Value().
|
||||||
|
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Next() bool {
|
||||||
|
return iterator.iterator.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
|
||||||
|
// If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Prev() bool {
|
||||||
|
return iterator.iterator.Prev()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current element's value.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Value() interface{} {
|
||||||
|
key := iterator.iterator.Value()
|
||||||
|
return iterator.table[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key returns the current element's key.
|
||||||
|
// Does not modify the state of the iterator.
|
||||||
|
func (iterator *Iterator) Key() interface{} {
|
||||||
|
return iterator.iterator.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin resets the iterator to its initial state (one-before-first)
|
||||||
|
// Call Next() to fetch the first element if any.
|
||||||
|
func (iterator *Iterator) Begin() {
|
||||||
|
iterator.iterator.Begin()
|
||||||
|
}
|
||||||
|
|
||||||
|
// End moves the iterator past the last element (one-past-the-end).
|
||||||
|
// Call Prev() to fetch the last element if any.
|
||||||
|
func (iterator *Iterator) End() {
|
||||||
|
iterator.iterator.End()
|
||||||
|
}
|
||||||
|
|
||||||
|
// First moves the iterator to the first element and returns true if there was a first element in the container.
|
||||||
|
// If First() returns true, then first element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator
|
||||||
|
func (iterator *Iterator) First() bool {
|
||||||
|
return iterator.iterator.First()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last moves the iterator to the last element and returns true if there was a last element in the container.
|
||||||
|
// If Last() returns true, then last element's key and value can be retrieved by Key() and Value().
|
||||||
|
// Modifies the state of the iterator.
|
||||||
|
func (iterator *Iterator) Last() bool {
|
||||||
|
return iterator.iterator.Last()
|
||||||
|
}
|
109
maps/linkedhashmap/linkedhashmap.go
Normal file
109
maps/linkedhashmap/linkedhashmap.go
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package linkedhashmap is a map that preserves insertion-order.
|
||||||
|
//
|
||||||
|
// It is backed by a hash table to store values and doubly-linked list to store ordering.
|
||||||
|
//
|
||||||
|
// Structure is not thread safe.
|
||||||
|
//
|
||||||
|
// Reference: http://en.wikipedia.org/wiki/Associative_array
|
||||||
|
package linkedhashmap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/emirpasic/gods/lists/doublylinkedlist"
|
||||||
|
"github.com/emirpasic/gods/maps"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertMapImplementation() {
|
||||||
|
var _ maps.Map = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map holds the elements in a red-black tree
|
||||||
|
type Map struct {
|
||||||
|
table map[interface{}]interface{}
|
||||||
|
ordering *doublylinkedlist.List
|
||||||
|
}
|
||||||
|
|
||||||
|
// New instantiates a linked-hash-map.
|
||||||
|
func New() *Map {
|
||||||
|
return &Map{
|
||||||
|
table: make(map[interface{}]interface{}),
|
||||||
|
ordering: doublylinkedlist.New(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put 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{}) {
|
||||||
|
if _, contains := m.table[key]; !contains {
|
||||||
|
m.ordering.Append(key)
|
||||||
|
}
|
||||||
|
m.table[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 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) {
|
||||||
|
value = m.table[key]
|
||||||
|
found = value != nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes 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{}) {
|
||||||
|
if _, contains := m.table[key]; contains {
|
||||||
|
delete(m.table, key)
|
||||||
|
index := m.ordering.IndexOf(key)
|
||||||
|
m.ordering.Remove(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty returns true if map does not contain any elements
|
||||||
|
func (m *Map) Empty() bool {
|
||||||
|
return m.Size() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns number of elements in the map.
|
||||||
|
func (m *Map) Size() int {
|
||||||
|
return m.ordering.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns all keys in-order
|
||||||
|
func (m *Map) Keys() []interface{} {
|
||||||
|
return m.ordering.Values()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values returns all values in-order based on the key.
|
||||||
|
func (m *Map) Values() []interface{} {
|
||||||
|
values := make([]interface{}, m.Size())
|
||||||
|
count := 0
|
||||||
|
it := m.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
values[count] = it.Value()
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear removes all elements from the map.
|
||||||
|
func (m *Map) Clear() {
|
||||||
|
m.table = make(map[interface{}]interface{})
|
||||||
|
m.ordering.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of container
|
||||||
|
func (m *Map) String() string {
|
||||||
|
str := "LinkedHashMap\nmap["
|
||||||
|
it := m.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
str += fmt.Sprintf("%v:%v ", it.Key(), it.Value())
|
||||||
|
}
|
||||||
|
return strings.TrimRight(str, " ") + "]"
|
||||||
|
|
||||||
|
}
|
643
maps/linkedhashmap/linkedhashmap_test.go
Normal file
643
maps/linkedhashmap/linkedhashmap_test.go
Normal file
@ -0,0 +1,643 @@
|
|||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package linkedhashmap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMapPut(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
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
|
||||||
|
|
||||||
|
if actualValue := m.Size(); actualValue != 7 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 7)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{5, 6, 7, 3, 4, 1, 2}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{"e", "f", "g", "c", "d", "a", "b"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapRemove(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
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
|
||||||
|
|
||||||
|
m.Remove(5)
|
||||||
|
m.Remove(6)
|
||||||
|
m.Remove(7)
|
||||||
|
m.Remove(8)
|
||||||
|
m.Remove(5)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := m.Keys(), []interface{}{3, 4, 1, 2}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
if actualValue, expectedValue := m.Values(), []interface{}{"c", "d", "a", "b"}; !sameElements(actualValue, expectedValue) {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := m.Size(); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
actualValue, actualFound := m.Get(test[0])
|
||||||
|
if actualValue != test[1] || actualFound != test[2] {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, test[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Remove(1)
|
||||||
|
m.Remove(4)
|
||||||
|
m.Remove(2)
|
||||||
|
m.Remove(3)
|
||||||
|
m.Remove(2)
|
||||||
|
m.Remove(2)
|
||||||
|
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", m.Keys()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := fmt.Sprintf("%s", m.Values()), "[]"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if actualValue := m.Size(); actualValue != 0 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||||
|
}
|
||||||
|
if actualValue := m.Empty(); actualValue != true {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sameElements(a []interface{}, b []interface{}) bool {
|
||||||
|
// If one is nil, the other must also be nil.
|
||||||
|
if (a == nil) != (b == nil) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(a) != len(b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range a {
|
||||||
|
if a[i] != b[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapEach(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put("c", 1)
|
||||||
|
m.Put("a", 2)
|
||||||
|
m.Put("b", 3)
|
||||||
|
count := 0
|
||||||
|
m.Each(func(key interface{}, value interface{}) {
|
||||||
|
count++
|
||||||
|
if actualValue, expectedValue := count, value; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
switch value {
|
||||||
|
case 1:
|
||||||
|
if actualValue, expectedValue := key, "c"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if actualValue, expectedValue := key, "a"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
if actualValue, expectedValue := key, "b"; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapMap(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
mappedMap := m.Map(func(key1 interface{}, value1 interface{}) (key2 interface{}, value2 interface{}) {
|
||||||
|
return key1, value1.(int) * value1.(int)
|
||||||
|
})
|
||||||
|
if actualValue, _ := mappedMap.Get("c"); actualValue != 9 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: c")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedMap.Get("a"); actualValue != 1 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := mappedMap.Get("b"); actualValue != 4 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "mapped: b")
|
||||||
|
}
|
||||||
|
if mappedMap.Size() != 3 {
|
||||||
|
t.Errorf("Got %v expected %v", mappedMap.Size(), 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapSelect(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("b", 1)
|
||||||
|
m.Put("a", 2)
|
||||||
|
selectedMap := m.Select(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) >= "a" && key.(string) <= "b"
|
||||||
|
})
|
||||||
|
if actualValue, _ := selectedMap.Get("b"); actualValue != 1 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: a")
|
||||||
|
}
|
||||||
|
if actualValue, _ := selectedMap.Get("a"); actualValue != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, "value: b")
|
||||||
|
}
|
||||||
|
if selectedMap.Size() != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", selectedMap.Size(), 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapAny(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
any := m.Any(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int) == 3
|
||||||
|
})
|
||||||
|
if any != true {
|
||||||
|
t.Errorf("Got %v expected %v", any, true)
|
||||||
|
}
|
||||||
|
any = m.Any(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int) == 4
|
||||||
|
})
|
||||||
|
if any != false {
|
||||||
|
t.Errorf("Got %v expected %v", any, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapAll(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
all := m.All(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) >= "a" && key.(string) <= "c"
|
||||||
|
})
|
||||||
|
if all != true {
|
||||||
|
t.Errorf("Got %v expected %v", all, true)
|
||||||
|
}
|
||||||
|
all = m.All(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) >= "a" && key.(string) <= "b"
|
||||||
|
})
|
||||||
|
if all != false {
|
||||||
|
t.Errorf("Got %v expected %v", all, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapFind(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
foundKey, foundValue := m.Find(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) == "c"
|
||||||
|
})
|
||||||
|
if foundKey != "c" || foundValue != 3 {
|
||||||
|
t.Errorf("Got %v -> %v expected %v -> %v", foundKey, foundValue, "c", 3)
|
||||||
|
}
|
||||||
|
foundKey, foundValue = m.Find(func(key interface{}, value interface{}) bool {
|
||||||
|
return key.(string) == "x"
|
||||||
|
})
|
||||||
|
if foundKey != nil || foundValue != nil {
|
||||||
|
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundKey, nil, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapChaining(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put("c", 3)
|
||||||
|
m.Put("a", 1)
|
||||||
|
m.Put("b", 2)
|
||||||
|
chainedMap := m.Select(func(key interface{}, value interface{}) bool {
|
||||||
|
return value.(int) > 1
|
||||||
|
}).Map(func(key interface{}, value interface{}) (interface{}, interface{}) {
|
||||||
|
return key.(string) + key.(string), value.(int) * value.(int)
|
||||||
|
})
|
||||||
|
if actualValue := chainedMap.Size(); actualValue != 2 {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 2)
|
||||||
|
}
|
||||||
|
if actualValue, found := chainedMap.Get("aa"); actualValue != nil || found {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||||
|
}
|
||||||
|
if actualValue, found := chainedMap.Get("bb"); actualValue != 4 || !found {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 4)
|
||||||
|
}
|
||||||
|
if actualValue, found := chainedMap.Get("cc"); actualValue != 9 || !found {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, 9)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorNextOnEmpty(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
it := m.Iterator()
|
||||||
|
it = m.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty map")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorPrevOnEmpty(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
it := m.Iterator()
|
||||||
|
it = m.Iterator()
|
||||||
|
for it.Prev() {
|
||||||
|
t.Errorf("Shouldn't iterate on empty map")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorNext(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put("c", 1)
|
||||||
|
m.Put("a", 2)
|
||||||
|
m.Put("b", 3)
|
||||||
|
|
||||||
|
it := m.Iterator()
|
||||||
|
count := 0
|
||||||
|
for it.Next() {
|
||||||
|
count++
|
||||||
|
key := it.Key()
|
||||||
|
value := it.Value()
|
||||||
|
switch key {
|
||||||
|
case "c":
|
||||||
|
if actualValue, expectedValue := value, 1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "a":
|
||||||
|
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "b":
|
||||||
|
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := value, count; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorPrev(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put("c", 1)
|
||||||
|
m.Put("a", 2)
|
||||||
|
m.Put("b", 3)
|
||||||
|
|
||||||
|
it := m.Iterator()
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
countDown := m.Size()
|
||||||
|
for it.Prev() {
|
||||||
|
key := it.Key()
|
||||||
|
value := it.Value()
|
||||||
|
switch key {
|
||||||
|
case "c":
|
||||||
|
if actualValue, expectedValue := value, 1; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "a":
|
||||||
|
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
case "b":
|
||||||
|
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Too many")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := value, countDown; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
countDown--
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := countDown, 0; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorBegin(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
it := m.Iterator()
|
||||||
|
it.Begin()
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
for it.Next() {
|
||||||
|
}
|
||||||
|
it.Begin()
|
||||||
|
it.Next()
|
||||||
|
if key, value := it.Key(), it.Value(); key != 3 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapTreeIteratorEnd(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
it := m.Iterator()
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
it.End()
|
||||||
|
it.Prev()
|
||||||
|
if key, value := it.Key(), it.Value(); key != 2 || value != "b" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 2, "b")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorFirst(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
it := m.Iterator()
|
||||||
|
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if key, value := it.Key(), it.Value(); key != 3 || value != "c" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 3, "c")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapIteratorLast(t *testing.T) {
|
||||||
|
m := New()
|
||||||
|
m.Put(3, "c")
|
||||||
|
m.Put(1, "a")
|
||||||
|
m.Put(2, "b")
|
||||||
|
it := m.Iterator()
|
||||||
|
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
|
||||||
|
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
if key, value := it.Key(), it.Value(); key != 2 || value != "b" {
|
||||||
|
t.Errorf("Got %v,%v expected %v,%v", key, value, 2, "b")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapSerialization(t *testing.T) {
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
original := New()
|
||||||
|
original.Put("d", "4")
|
||||||
|
original.Put("e", "5")
|
||||||
|
original.Put("c", "3")
|
||||||
|
original.Put("b", "2")
|
||||||
|
original.Put("a", "1")
|
||||||
|
|
||||||
|
assertSerialization(original, "A", t)
|
||||||
|
|
||||||
|
serialized, err := original.ToJSON()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
assertSerialization(original, "B", t)
|
||||||
|
|
||||||
|
deserialized := New()
|
||||||
|
err = deserialized.FromJSON(serialized)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
assertSerialization(deserialized, "C", t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection GoBoolExpressions
|
||||||
|
func assertSerialization(m *Map, txt string, t *testing.T) {
|
||||||
|
if actualValue := m.Keys(); false ||
|
||||||
|
actualValue[0].(string) != "d" ||
|
||||||
|
actualValue[1].(string) != "e" ||
|
||||||
|
actualValue[2].(string) != "c" ||
|
||||||
|
actualValue[3].(string) != "b" ||
|
||||||
|
actualValue[4].(string) != "a" {
|
||||||
|
t.Errorf("[%s] Got %v expected %v", txt, actualValue, "[d,e,c,b,a]")
|
||||||
|
}
|
||||||
|
if actualValue := m.Values(); false ||
|
||||||
|
actualValue[0].(string) != "4" ||
|
||||||
|
actualValue[1].(string) != "5" ||
|
||||||
|
actualValue[2].(string) != "3" ||
|
||||||
|
actualValue[3].(string) != "2" ||
|
||||||
|
actualValue[4].(string) != "1" {
|
||||||
|
t.Errorf("[%s] Got %v expected %v", txt, actualValue, "[4,5,3,2,1]")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Size(), 5; actualValue != expectedValue {
|
||||||
|
t.Errorf("[%s] Got %v expected %v", txt, actualValue, expectedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkGet(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Get(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkPut(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkRemove(b *testing.B, m *Map, size int) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Remove(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapGet100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapGet1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapGet10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapGet100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkGet(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapPut100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := New()
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapPut1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapPut10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapPut100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkPut(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapRemove100(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapRemove1000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 1000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapRemove10000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 10000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTreeMapRemove100000(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
size := 100000
|
||||||
|
m := New()
|
||||||
|
for n := 0; n < size; n++ {
|
||||||
|
m.Put(n, struct{}{})
|
||||||
|
}
|
||||||
|
b.StartTimer()
|
||||||
|
benchmarkRemove(b, m, size)
|
||||||
|
}
|
103
maps/linkedhashmap/serialization.go
Normal file
103
maps/linkedhashmap/serialization.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// Copyright (c) 2015, Emir Pasic. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package linkedhashmap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/emirpasic/gods/containers"
|
||||||
|
"github.com/emirpasic/gods/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertSerializationImplementation() {
|
||||||
|
var _ containers.JSONSerializer = (*Map)(nil)
|
||||||
|
var _ containers.JSONDeserializer = (*Map)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToJSON outputs the JSON representation of map.
|
||||||
|
func (m *Map) ToJSON() ([]byte, error) {
|
||||||
|
var b []byte
|
||||||
|
buf := bytes.NewBuffer(b)
|
||||||
|
|
||||||
|
buf.WriteRune('{')
|
||||||
|
|
||||||
|
it := m.Iterator()
|
||||||
|
lastIndex := m.Size() - 1
|
||||||
|
index := 0
|
||||||
|
|
||||||
|
for it.Next() {
|
||||||
|
km, err := json.Marshal(it.Key())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
buf.Write(km)
|
||||||
|
|
||||||
|
buf.WriteRune(':')
|
||||||
|
|
||||||
|
vm, err := json.Marshal(it.Value())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
buf.Write(vm)
|
||||||
|
|
||||||
|
if index != lastIndex {
|
||||||
|
buf.WriteRune(',')
|
||||||
|
}
|
||||||
|
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteRune('}')
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromJSON populates map from the input JSON representation.
|
||||||
|
//func (m *Map) FromJSON(data []byte) error {
|
||||||
|
// elements := make(map[string]interface{})
|
||||||
|
// err := json.Unmarshal(data, &elements)
|
||||||
|
// if err == nil {
|
||||||
|
// m.Clear()
|
||||||
|
// for key, value := range elements {
|
||||||
|
// m.Put(key, value)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return err
|
||||||
|
//}
|
||||||
|
|
||||||
|
// FromJSON populates map from the input JSON representation.
|
||||||
|
func (m *Map) FromJSON(data []byte) error {
|
||||||
|
elements := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal(data, &elements)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
index := make(map[string]int)
|
||||||
|
var keys []interface{}
|
||||||
|
for key := range elements {
|
||||||
|
keys = append(keys, key)
|
||||||
|
esc, _ := json.Marshal(key)
|
||||||
|
index[key] = bytes.Index(data, esc)
|
||||||
|
}
|
||||||
|
|
||||||
|
byIndex := func(a, b interface{}) int {
|
||||||
|
key1 := a.(string)
|
||||||
|
key2 := b.(string)
|
||||||
|
index1 := index[key1]
|
||||||
|
index2 := index[key2]
|
||||||
|
return index1 - index2
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.Sort(keys, byIndex)
|
||||||
|
|
||||||
|
m.Clear()
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
m.Put(key, elements[key.(string)])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -15,7 +15,7 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Map)(nil)
|
var _ containers.JSONDeserializer = (*Map)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the map.
|
||||||
func (m *Map) ToJSON() ([]byte, error) {
|
func (m *Map) ToJSON() ([]byte, error) {
|
||||||
elements := make(map[string]interface{})
|
elements := make(map[string]interface{})
|
||||||
it := m.Iterator()
|
it := m.Iterator()
|
||||||
@ -25,7 +25,7 @@ func (m *Map) ToJSON() ([]byte, error) {
|
|||||||
return json.Marshal(&elements)
|
return json.Marshal(&elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the map from the input JSON representation.
|
||||||
func (m *Map) FromJSON(data []byte) error {
|
func (m *Map) FromJSON(data []byte) error {
|
||||||
elements := make(map[string]interface{})
|
elements := make(map[string]interface{})
|
||||||
err := json.Unmarshal(data, &elements)
|
err := json.Unmarshal(data, &elements)
|
||||||
|
@ -474,34 +474,52 @@ func TestMapIteratorLast(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMapSerialization(t *testing.T) {
|
func TestMapSerialization(t *testing.T) {
|
||||||
m := NewWithStringComparators()
|
for i := 0; i < 10; i++ {
|
||||||
m.Put("a", "1")
|
original := NewWith(utils.StringComparator, utils.StringComparator)
|
||||||
m.Put("b", "2")
|
original.Put("d", "4")
|
||||||
m.Put("c", "3")
|
original.Put("e", "5")
|
||||||
|
original.Put("c", "3")
|
||||||
|
original.Put("b", "2")
|
||||||
|
original.Put("a", "1")
|
||||||
|
|
||||||
var err error
|
assertSerialization(original, "A", t)
|
||||||
assert := func() {
|
|
||||||
if actualValue := m.Keys(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" {
|
serialized, err := original.ToJSON()
|
||||||
t.Errorf("Got %v expected %v", actualValue, "[a,b,c]")
|
|
||||||
}
|
|
||||||
if actualValue := m.Values(); actualValue[0].(string) != "1" || actualValue[1].(string) != "2" || actualValue[2].(string) != "3" {
|
|
||||||
t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
|
|
||||||
}
|
|
||||||
if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue {
|
|
||||||
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Got error %v", err)
|
t.Errorf("Got error %v", err)
|
||||||
}
|
}
|
||||||
|
assertSerialization(original, "B", t)
|
||||||
|
|
||||||
|
deserialized := NewWith(utils.StringComparator, utils.StringComparator)
|
||||||
|
err = deserialized.FromJSON(serialized)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
assertSerialization(deserialized, "C", t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert()
|
//noinspection GoBoolExpressions
|
||||||
|
func assertSerialization(m *Map, txt string, t *testing.T) {
|
||||||
json, err := m.ToJSON()
|
if actualValue := m.Keys(); false ||
|
||||||
assert()
|
actualValue[0].(string) != "a" ||
|
||||||
|
actualValue[1].(string) != "b" ||
|
||||||
err = m.FromJSON(json)
|
actualValue[2].(string) != "c" ||
|
||||||
assert()
|
actualValue[3].(string) != "d" ||
|
||||||
|
actualValue[4].(string) != "e" {
|
||||||
|
t.Errorf("[%s] Got %v expected %v", txt, actualValue, "[a,b,c,d,e]")
|
||||||
|
}
|
||||||
|
if actualValue := m.Values(); false ||
|
||||||
|
actualValue[0].(string) != "1" ||
|
||||||
|
actualValue[1].(string) != "2" ||
|
||||||
|
actualValue[2].(string) != "3" ||
|
||||||
|
actualValue[3].(string) != "4" ||
|
||||||
|
actualValue[4].(string) != "5" {
|
||||||
|
t.Errorf("[%s] Got %v expected %v", txt, actualValue, "[1,2,3,4,5]")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Size(), 5; actualValue != expectedValue {
|
||||||
|
t.Errorf("[%s] Got %v expected %v", txt, actualValue, expectedValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func benchmarkGet(b *testing.B, m *Map, size int) {
|
func benchmarkGet(b *testing.B, m *Map, size int) {
|
||||||
|
@ -11,12 +11,12 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Map)(nil)
|
var _ containers.JSONDeserializer = (*Map)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the map.
|
||||||
func (m *Map) ToJSON() ([]byte, error) {
|
func (m *Map) ToJSON() ([]byte, error) {
|
||||||
return m.tree.ToJSON()
|
return m.tree.ToJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the map from the input JSON representation.
|
||||||
func (m *Map) FromJSON(data []byte) error {
|
func (m *Map) FromJSON(data []byte) error {
|
||||||
return m.tree.FromJSON(data)
|
return m.tree.FromJSON(data)
|
||||||
}
|
}
|
||||||
|
@ -441,34 +441,52 @@ func TestMapIteratorLast(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMapSerialization(t *testing.T) {
|
func TestMapSerialization(t *testing.T) {
|
||||||
m := NewWithStringComparator()
|
for i := 0; i < 10; i++ {
|
||||||
m.Put("a", "1")
|
original := NewWithStringComparator()
|
||||||
m.Put("b", "2")
|
original.Put("d", "4")
|
||||||
m.Put("c", "3")
|
original.Put("e", "5")
|
||||||
|
original.Put("c", "3")
|
||||||
|
original.Put("b", "2")
|
||||||
|
original.Put("a", "1")
|
||||||
|
|
||||||
var err error
|
assertSerialization(original, "A", t)
|
||||||
assert := func() {
|
|
||||||
if actualValue := m.Keys(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" {
|
serialized, err := original.ToJSON()
|
||||||
t.Errorf("Got %v expected %v", actualValue, "[a,b,c]")
|
|
||||||
}
|
|
||||||
if actualValue := m.Values(); actualValue[0].(string) != "1" || actualValue[1].(string) != "2" || actualValue[2].(string) != "3" {
|
|
||||||
t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
|
|
||||||
}
|
|
||||||
if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue {
|
|
||||||
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Got error %v", err)
|
t.Errorf("Got error %v", err)
|
||||||
}
|
}
|
||||||
|
assertSerialization(original, "B", t)
|
||||||
|
|
||||||
|
deserialized := NewWithStringComparator()
|
||||||
|
err = deserialized.FromJSON(serialized)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Got error %v", err)
|
||||||
|
}
|
||||||
|
assertSerialization(deserialized, "C", t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert()
|
//noinspection GoBoolExpressions
|
||||||
|
func assertSerialization(m *Map, txt string, t *testing.T) {
|
||||||
json, err := m.ToJSON()
|
if actualValue := m.Keys(); false ||
|
||||||
assert()
|
actualValue[0].(string) != "a" ||
|
||||||
|
actualValue[1].(string) != "b" ||
|
||||||
err = m.FromJSON(json)
|
actualValue[2].(string) != "c" ||
|
||||||
assert()
|
actualValue[3].(string) != "d" ||
|
||||||
|
actualValue[4].(string) != "e" {
|
||||||
|
t.Errorf("[%s] Got %v expected %v", txt, actualValue, "[a,b,c,d,e]")
|
||||||
|
}
|
||||||
|
if actualValue := m.Values(); false ||
|
||||||
|
actualValue[0].(string) != "1" ||
|
||||||
|
actualValue[1].(string) != "2" ||
|
||||||
|
actualValue[2].(string) != "3" ||
|
||||||
|
actualValue[3].(string) != "4" ||
|
||||||
|
actualValue[4].(string) != "5" {
|
||||||
|
t.Errorf("[%s] Got %v expected %v", txt, actualValue, "[1,2,3,4,5]")
|
||||||
|
}
|
||||||
|
if actualValue, expectedValue := m.Size(), 5; actualValue != expectedValue {
|
||||||
|
t.Errorf("[%s] Got %v expected %v", txt, actualValue, expectedValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func benchmarkGet(b *testing.B, m *Map, size int) {
|
func benchmarkGet(b *testing.B, m *Map, size int) {
|
||||||
|
@ -14,12 +14,12 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Set)(nil)
|
var _ containers.JSONDeserializer = (*Set)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the set.
|
||||||
func (set *Set) ToJSON() ([]byte, error) {
|
func (set *Set) ToJSON() ([]byte, error) {
|
||||||
return json.Marshal(set.Values())
|
return json.Marshal(set.Values())
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the set from the input JSON representation.
|
||||||
func (set *Set) FromJSON(data []byte) error {
|
func (set *Set) FromJSON(data []byte) error {
|
||||||
elements := []interface{}{}
|
elements := []interface{}{}
|
||||||
err := json.Unmarshal(data, &elements)
|
err := json.Unmarshal(data, &elements)
|
||||||
|
@ -20,7 +20,7 @@ type Iterator struct {
|
|||||||
|
|
||||||
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
// Iterator returns a stateful iterator whose values can be fetched by an index.
|
||||||
func (set *Set) Iterator() Iterator {
|
func (set *Set) Iterator() Iterator {
|
||||||
return Iterator{iterator: set.list.Iterator()}
|
return Iterator{iterator: set.ordering.Iterator()}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
// Next moves the iterator to the next element and returns true if there was a next element in the container.
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package linkedhashset implements a set that preserves insertion-order and is backed a hash tables to store values and doubly-linked list to store ordering.
|
// Package linkedhashset is a set that preserves insertion-order.
|
||||||
|
//
|
||||||
|
// It is backed by a hash table to store values and doubly-linked list to store ordering.
|
||||||
//
|
//
|
||||||
// Note that insertion-order is not affected if an element is re-inserted into the set.
|
// Note that insertion-order is not affected if an element is re-inserted into the set.
|
||||||
//
|
//
|
||||||
@ -24,8 +26,8 @@ func assertSetImplementation() {
|
|||||||
|
|
||||||
// Set holds elements in go's native map
|
// Set holds elements in go's native map
|
||||||
type Set struct {
|
type Set struct {
|
||||||
items map[interface{}]struct{}
|
table map[interface{}]struct{}
|
||||||
list *doublylinkedlist.List
|
ordering *doublylinkedlist.List
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemExists = struct{}{}
|
var itemExists = struct{}{}
|
||||||
@ -33,8 +35,8 @@ var itemExists = struct{}{}
|
|||||||
// New instantiates a new empty set and adds the passed values, if any, to the set
|
// New instantiates a new empty set and adds the passed values, if any, to the set
|
||||||
func New(values ...interface{}) *Set {
|
func New(values ...interface{}) *Set {
|
||||||
set := &Set{
|
set := &Set{
|
||||||
items: make(map[interface{}]struct{}),
|
table: make(map[interface{}]struct{}),
|
||||||
list: doublylinkedlist.New(),
|
ordering: doublylinkedlist.New(),
|
||||||
}
|
}
|
||||||
if len(values) > 0 {
|
if len(values) > 0 {
|
||||||
set.Add(values...)
|
set.Add(values...)
|
||||||
@ -46,13 +48,10 @@ func New(values ...interface{}) *Set {
|
|||||||
// Note that insertion-order is not affected if an element is re-inserted into the set.
|
// Note that insertion-order is not affected if an element is re-inserted into the set.
|
||||||
func (set *Set) Add(items ...interface{}) {
|
func (set *Set) Add(items ...interface{}) {
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
|
if _, contains := set.table[item]; !contains {
|
||||||
if _, contains := set.items[item]; contains {
|
set.table[item] = itemExists
|
||||||
continue
|
set.ordering.Append(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
set.items[item] = itemExists
|
|
||||||
set.list.Append(item)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,14 +59,11 @@ func (set *Set) Add(items ...interface{}) {
|
|||||||
// Slow operation, worst-case O(n^2).
|
// Slow operation, worst-case O(n^2).
|
||||||
func (set *Set) Remove(items ...interface{}) {
|
func (set *Set) Remove(items ...interface{}) {
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
|
if _, contains := set.table[item]; contains {
|
||||||
if _, contains := set.items[item]; !contains {
|
delete(set.table, item)
|
||||||
continue
|
index := set.ordering.IndexOf(item)
|
||||||
|
set.ordering.Remove(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(set.items, item)
|
|
||||||
index := set.list.IndexOf(item)
|
|
||||||
set.list.Remove(index)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +72,7 @@ func (set *Set) Remove(items ...interface{}) {
|
|||||||
// Returns true if no arguments are passed at all, i.e. set is always superset of empty set.
|
// Returns true if no arguments are passed at all, i.e. set is always superset of empty set.
|
||||||
func (set *Set) Contains(items ...interface{}) bool {
|
func (set *Set) Contains(items ...interface{}) bool {
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
if _, contains := set.items[item]; !contains {
|
if _, contains := set.table[item]; !contains {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,13 +86,13 @@ func (set *Set) Empty() bool {
|
|||||||
|
|
||||||
// Size returns number of elements within the set.
|
// Size returns number of elements within the set.
|
||||||
func (set *Set) Size() int {
|
func (set *Set) Size() int {
|
||||||
return set.list.Size()
|
return set.ordering.Size()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear clears all values in the set.
|
// Clear clears all values in the set.
|
||||||
func (set *Set) Clear() {
|
func (set *Set) Clear() {
|
||||||
set.items = make(map[interface{}]struct{})
|
set.table = make(map[interface{}]struct{})
|
||||||
set.list.Clear()
|
set.ordering.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values returns all items in the set.
|
// Values returns all items in the set.
|
||||||
|
@ -14,12 +14,12 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Set)(nil)
|
var _ containers.JSONDeserializer = (*Set)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the set.
|
||||||
func (set *Set) ToJSON() ([]byte, error) {
|
func (set *Set) ToJSON() ([]byte, error) {
|
||||||
return json.Marshal(set.Values())
|
return json.Marshal(set.Values())
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the set from the input JSON representation.
|
||||||
func (set *Set) FromJSON(data []byte) error {
|
func (set *Set) FromJSON(data []byte) error {
|
||||||
elements := []interface{}{}
|
elements := []interface{}{}
|
||||||
err := json.Unmarshal(data, &elements)
|
err := json.Unmarshal(data, &elements)
|
||||||
|
@ -14,12 +14,12 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Set)(nil)
|
var _ containers.JSONDeserializer = (*Set)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the set.
|
||||||
func (set *Set) ToJSON() ([]byte, error) {
|
func (set *Set) ToJSON() ([]byte, error) {
|
||||||
return json.Marshal(set.Values())
|
return json.Marshal(set.Values())
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the set from the input JSON representation.
|
||||||
func (set *Set) FromJSON(data []byte) error {
|
func (set *Set) FromJSON(data []byte) error {
|
||||||
elements := []interface{}{}
|
elements := []interface{}{}
|
||||||
err := json.Unmarshal(data, &elements)
|
err := json.Unmarshal(data, &elements)
|
||||||
|
@ -11,12 +11,12 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Stack)(nil)
|
var _ containers.JSONDeserializer = (*Stack)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the stack.
|
||||||
func (stack *Stack) ToJSON() ([]byte, error) {
|
func (stack *Stack) ToJSON() ([]byte, error) {
|
||||||
return stack.list.ToJSON()
|
return stack.list.ToJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the stack from the input JSON representation.
|
||||||
func (stack *Stack) FromJSON(data []byte) error {
|
func (stack *Stack) FromJSON(data []byte) error {
|
||||||
return stack.list.FromJSON(data)
|
return stack.list.FromJSON(data)
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,12 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Stack)(nil)
|
var _ containers.JSONDeserializer = (*Stack)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the stack.
|
||||||
func (stack *Stack) ToJSON() ([]byte, error) {
|
func (stack *Stack) ToJSON() ([]byte, error) {
|
||||||
return stack.list.ToJSON()
|
return stack.list.ToJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the stack from the input JSON representation.
|
||||||
func (stack *Stack) FromJSON(data []byte) error {
|
func (stack *Stack) FromJSON(data []byte) error {
|
||||||
return stack.list.FromJSON(data)
|
return stack.list.FromJSON(data)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Tree)(nil)
|
var _ containers.JSONDeserializer = (*Tree)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the tree.
|
||||||
func (tree *Tree) ToJSON() ([]byte, error) {
|
func (tree *Tree) ToJSON() ([]byte, error) {
|
||||||
elements := make(map[string]interface{})
|
elements := make(map[string]interface{})
|
||||||
it := tree.Iterator()
|
it := tree.Iterator()
|
||||||
@ -25,7 +25,7 @@ func (tree *Tree) ToJSON() ([]byte, error) {
|
|||||||
return json.Marshal(&elements)
|
return json.Marshal(&elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the tree from the input JSON representation.
|
||||||
func (tree *Tree) FromJSON(data []byte) error {
|
func (tree *Tree) FromJSON(data []byte) error {
|
||||||
elements := make(map[string]interface{})
|
elements := make(map[string]interface{})
|
||||||
err := json.Unmarshal(data, &elements)
|
err := json.Unmarshal(data, &elements)
|
||||||
|
@ -11,12 +11,12 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Heap)(nil)
|
var _ containers.JSONDeserializer = (*Heap)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the heap.
|
||||||
func (heap *Heap) ToJSON() ([]byte, error) {
|
func (heap *Heap) ToJSON() ([]byte, error) {
|
||||||
return heap.list.ToJSON()
|
return heap.list.ToJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the heap from the input JSON representation.
|
||||||
func (heap *Heap) FromJSON(data []byte) error {
|
func (heap *Heap) FromJSON(data []byte) error {
|
||||||
return heap.list.FromJSON(data)
|
return heap.list.FromJSON(data)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Tree)(nil)
|
var _ containers.JSONDeserializer = (*Tree)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the tree.
|
||||||
func (tree *Tree) ToJSON() ([]byte, error) {
|
func (tree *Tree) ToJSON() ([]byte, error) {
|
||||||
elements := make(map[string]interface{})
|
elements := make(map[string]interface{})
|
||||||
it := tree.Iterator()
|
it := tree.Iterator()
|
||||||
@ -25,7 +25,7 @@ func (tree *Tree) ToJSON() ([]byte, error) {
|
|||||||
return json.Marshal(&elements)
|
return json.Marshal(&elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the tree from the input JSON representation.
|
||||||
func (tree *Tree) FromJSON(data []byte) error {
|
func (tree *Tree) FromJSON(data []byte) error {
|
||||||
elements := make(map[string]interface{})
|
elements := make(map[string]interface{})
|
||||||
err := json.Unmarshal(data, &elements)
|
err := json.Unmarshal(data, &elements)
|
||||||
|
@ -15,7 +15,7 @@ func assertSerializationImplementation() {
|
|||||||
var _ containers.JSONDeserializer = (*Tree)(nil)
|
var _ containers.JSONDeserializer = (*Tree)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToJSON outputs the JSON representation of list's elements.
|
// ToJSON outputs the JSON representation of the tree.
|
||||||
func (tree *Tree) ToJSON() ([]byte, error) {
|
func (tree *Tree) ToJSON() ([]byte, error) {
|
||||||
elements := make(map[string]interface{})
|
elements := make(map[string]interface{})
|
||||||
it := tree.Iterator()
|
it := tree.Iterator()
|
||||||
@ -25,7 +25,7 @@ func (tree *Tree) ToJSON() ([]byte, error) {
|
|||||||
return json.Marshal(&elements)
|
return json.Marshal(&elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromJSON populates list's elements from the input JSON representation.
|
// FromJSON populates the tree from the input JSON representation.
|
||||||
func (tree *Tree) FromJSON(data []byte) error {
|
func (tree *Tree) FromJSON(data []byte) error {
|
||||||
elements := make(map[string]interface{})
|
elements := make(map[string]interface{})
|
||||||
err := json.Unmarshal(data, &elements)
|
err := json.Unmarshal(data, &elements)
|
||||||
|
Loading…
Reference in New Issue
Block a user