Generics migration (#237)

* Generics migration

This attempts to migrate this library in the least invasive way by preserving as
much of the original API as possible. It does not change the tests in a
meaningful way nor does it attempt to upgrade any logic that can be simplified
or improved with generics. This is purely an API migration, and still requires a
lot of additional work to be fully ready.

* Fix a few broken tests around serialization

* Add v2 suffix

* Temporarily change mod name for testing

* Rename module to /v2
master v2.0.0-alpha
Paul Chesnais 4 months ago committed by GitHub
parent 10d6c5b4f2
commit 14f714261f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -13,24 +13,39 @@
// Serialization provides serializers (marshalers) and deserializers (unmarshalers).
package containers
import "github.com/emirpasic/gods/utils"
import (
"cmp"
"slices"
"github.com/emirpasic/gods/v2/utils"
)
// Container is base interface that all data structures implement.
type Container interface {
type Container[T any] interface {
Empty() bool
Size() int
Clear()
Values() []interface{}
Values() []T
String() string
}
// GetSortedValues returns sorted container's elements with respect to the passed comparator.
// Does not affect the ordering of elements within the container.
func GetSortedValues(container Container, comparator utils.Comparator) []interface{} {
func GetSortedValues[T cmp.Ordered](container Container[T]) []T {
values := container.Values()
if len(values) < 2 {
return values
}
slices.Sort(values)
return values
}
// GetSortedValuesFunc is the equivalent of GetSortedValues for containers of values that are not ordered.
func GetSortedValuesFunc[T any](container Container[T], comparator utils.Comparator[T]) []T {
values := container.Values()
if len(values) < 2 {
return values
}
utils.Sort(values, comparator)
slices.SortFunc(values, comparator)
return values
}

@ -7,34 +7,34 @@
package containers
import (
"cmp"
"fmt"
"github.com/emirpasic/gods/utils"
"strings"
"testing"
)
// For testing purposes
type ContainerTest struct {
values []interface{}
type ContainerTest[T any] struct {
values []T
}
func (container ContainerTest) Empty() bool {
func (container ContainerTest[T]) Empty() bool {
return len(container.values) == 0
}
func (container ContainerTest) Size() int {
func (container ContainerTest[T]) Size() int {
return len(container.values)
}
func (container ContainerTest) Clear() {
container.values = []interface{}{}
func (container ContainerTest[T]) Clear() {
container.values = []T{}
}
func (container ContainerTest) Values() []interface{} {
func (container ContainerTest[T]) Values() []T {
return container.values
}
func (container ContainerTest) String() string {
func (container ContainerTest[T]) String() string {
str := "ContainerTest\n"
var values []string
for _, value := range container.values {
@ -45,24 +45,32 @@ func (container ContainerTest) String() string {
}
func TestGetSortedValuesInts(t *testing.T) {
container := ContainerTest{}
GetSortedValues(container, utils.IntComparator)
container.values = []interface{}{5, 1, 3, 2, 4}
values := GetSortedValues(container, utils.IntComparator)
container := ContainerTest[int]{}
GetSortedValues(container)
container.values = []int{5, 1, 3, 2, 4}
values := GetSortedValues(container)
for i := 1; i < container.Size(); i++ {
if values[i-1].(int) > values[i].(int) {
if values[i-1] > values[i] {
t.Errorf("Not sorted!")
}
}
}
func TestGetSortedValuesStrings(t *testing.T) {
container := ContainerTest{}
GetSortedValues(container, utils.StringComparator)
container.values = []interface{}{"g", "a", "d", "e", "f", "c", "b"}
values := GetSortedValues(container, utils.StringComparator)
type NotInt struct {
i int
}
func TestGetSortedValuesNotInts(t *testing.T) {
container := ContainerTest[NotInt]{}
GetSortedValuesFunc(container, func(x, y NotInt) int {
return cmp.Compare(x.i, y.i)
})
container.values = []NotInt{{5}, {1}, {3}, {2}, {4}}
values := GetSortedValuesFunc(container, func(x, y NotInt) int {
return cmp.Compare(x.i, y.i)
})
for i := 1; i < container.Size(); i++ {
if values[i-1].(string) > values[i].(string) {
if values[i-1].i > values[i].i {
t.Errorf("Not sorted!")
}
}

@ -5,9 +5,9 @@
package containers
// EnumerableWithIndex provides functions for ordered containers whose values can be fetched by an index.
type EnumerableWithIndex interface {
type EnumerableWithIndex[T any] interface {
// Each calls the given function once for each element, passing that element's index and value.
Each(func(index int, value interface{}))
Each(func(index int, value T))
// Map invokes the given function once for each element and returns a
// container containing the values returned by the given function.
@ -18,22 +18,22 @@ type EnumerableWithIndex interface {
// Any passes each element of the container to the given function and
// returns true if the function ever returns true for any element.
Any(func(index int, value interface{}) bool) bool
Any(func(index int, value T) bool) bool
// All passes each element of the container to the given function and
// returns true if the function returns true for all elements.
All(func(index int, value interface{}) bool) bool
All(func(index int, value T) bool) bool
// Find passes each element of the container to the given function and returns
// the first (index,value) for which the function is true or -1,nil otherwise
// if no element matches the criteria.
Find(func(index int, value interface{}) bool) (int, interface{})
Find(func(index int, value T) bool) (int, T)
}
// EnumerableWithKey provides functions for ordered containers whose values whose elements are key/value pairs.
type EnumerableWithKey interface {
type EnumerableWithKey[K, V any] interface {
// Each calls the given function once for each element, passing that element's key and value.
Each(func(key interface{}, value interface{}))
Each(func(key K, value V))
// 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.
@ -44,14 +44,14 @@ type EnumerableWithKey interface {
// Any passes each element of the container to the given function and
// returns true if the function ever returns true for any element.
Any(func(key interface{}, value interface{}) bool) bool
Any(func(key K, value V) bool) bool
// All passes each element of the container to the given function and
// returns true if the function returns true for all elements.
All(func(key interface{}, value interface{}) bool) bool
All(func(key K, value V) bool) bool
// 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.
Find(func(key interface{}, value interface{}) bool) (interface{}, interface{})
Find(func(key K, value V) bool) (K, V)
}

@ -5,7 +5,7 @@
package containers
// IteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index.
type IteratorWithIndex interface {
type IteratorWithIndex[T any] interface {
// 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 index and value can be retrieved by Index() and Value().
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
@ -14,7 +14,7 @@ type IteratorWithIndex interface {
// Value returns the current element's value.
// Does not modify the state of the iterator.
Value() interface{}
Value() T
// Index returns the current element's index.
// Does not modify the state of the iterator.
@ -33,11 +33,11 @@ type IteratorWithIndex interface {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
NextTo(func(index int, value interface{}) bool) bool
NextTo(func(index int, value T) bool) bool
}
// IteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs.
type IteratorWithKey interface {
type IteratorWithKey[K, V any] interface {
// 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.
@ -46,11 +46,11 @@ type IteratorWithKey interface {
// Value returns the current element's value.
// Does not modify the state of the iterator.
Value() interface{}
Value() V
// Key returns the current element's key.
// Does not modify the state of the iterator.
Key() interface{}
Key() K
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
@ -65,19 +65,19 @@ type IteratorWithKey interface {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
NextTo(func(key interface{}, value interface{}) bool) bool
NextTo(func(key K, value V) bool) bool
}
// ReverseIteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index.
//
// Essentially it is the same as IteratorWithIndex, but provides additional:
//
// Prev() function to enable traversal in reverse
// # Prev() function to enable traversal in reverse
//
// Last() function to move the iterator to the last element.
//
// End() function to move the iterator past the last element (one-past-the-end).
type ReverseIteratorWithIndex interface {
type ReverseIteratorWithIndex[T any] interface {
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
@ -96,19 +96,19 @@ type ReverseIteratorWithIndex interface {
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
PrevTo(func(index int, value interface{}) bool) bool
PrevTo(func(index int, value T) bool) bool
IteratorWithIndex
IteratorWithIndex[T]
}
// ReverseIteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs.
//
// Essentially it is the same as IteratorWithKey, but provides additional:
//
// Prev() function to enable traversal in reverse
// # Prev() function to enable traversal in reverse
//
// Last() function to move the iterator to the last element.
type ReverseIteratorWithKey interface {
type ReverseIteratorWithKey[K, V any] interface {
// 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.
@ -127,7 +127,7 @@ type ReverseIteratorWithKey interface {
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
PrevTo(func(key interface{}, value interface{}) bool) bool
PrevTo(func(key K, value V) bool) bool
IteratorWithKey
IteratorWithKey[K, V]
}

@ -5,16 +5,17 @@
package main
import (
"github.com/emirpasic/gods/lists/arraylist"
"github.com/emirpasic/gods/utils"
"cmp"
"github.com/emirpasic/gods/v2/lists/arraylist"
)
// ArrayListExample to demonstrate basic usage of ArrayList
func main() {
list := arraylist.New()
list := arraylist.New[string]()
list.Add("a") // ["a"]
list.Add("c", "b") // ["a","c","b"]
list.Sort(utils.StringComparator) // ["a","b","c"]
list.Sort(cmp.Compare[string]) // ["a","b","c"]
_, _ = list.Get(0) // "a",true
_, _ = list.Get(100) // nil,false
_ = list.Contains("a", "b", "c") // true

@ -4,11 +4,11 @@
package main
import aq "github.com/emirpasic/gods/queues/arrayqueue"
import aq "github.com/emirpasic/gods/v2/queues/arrayqueue"
// ArrayQueueExample to demonstrate basic usage of ArrayQueue
func main() {
queue := aq.New() // empty
queue := aq.New[int]() // empty
queue.Enqueue(1) // 1
queue.Enqueue(2) // 1, 2
_ = queue.Values() // 1, 2 (FIFO order)

@ -4,20 +4,20 @@
package main
import "github.com/emirpasic/gods/stacks/arraystack"
import "github.com/emirpasic/gods/v2/stacks/arraystack"
// ArrayStackExample to demonstrate basic usage of ArrayStack
func main() {
stack := arraystack.New() // empty
stack.Push(1) // 1
stack.Push(2) // 1, 2
stack.Values() // 2, 1 (LIFO order)
_, _ = stack.Peek() // 2,true
_, _ = stack.Pop() // 2, true
_, _ = stack.Pop() // 1, true
_, _ = stack.Pop() // nil, false (nothing to pop)
stack.Push(1) // 1
stack.Clear() // empty
stack.Empty() // true
stack.Size() // 0
stack := arraystack.New[int]() // empty
stack.Push(1) // 1
stack.Push(2) // 1, 2
stack.Values() // 2, 1 (LIFO order)
_, _ = stack.Peek() // 2,true
_, _ = stack.Pop() // 2, true
_, _ = stack.Pop() // 1, true
_, _ = stack.Pop() // nil, false (nothing to pop)
stack.Push(1) // 1
stack.Clear() // empty
stack.Empty() // true
stack.Size() // 0
}

@ -6,12 +6,13 @@ package main
import (
"fmt"
avl "github.com/emirpasic/gods/trees/avltree"
avl "github.com/emirpasic/gods/v2/trees/avltree"
)
// AVLTreeExample to demonstrate basic usage of AVLTree
func main() {
tree := avl.NewWithIntComparator() // empty(keys are of type int)
tree := avl.New[int, string]() // empty(keys are of type int)
tree.Put(1, "x") // 1->x
tree.Put(2, "b") // 1->x, 2->b (in order)

@ -5,32 +5,33 @@
package main
import (
"github.com/emirpasic/gods/trees/binaryheap"
"github.com/emirpasic/gods/utils"
"cmp"
"github.com/emirpasic/gods/v2/trees/binaryheap"
)
// BinaryHeapExample to demonstrate basic usage of BinaryHeap
func main() {
// Min-heap
heap := binaryheap.NewWithIntComparator() // empty (min-heap)
heap.Push(2) // 2
heap.Push(3) // 2, 3
heap.Push(1) // 1, 3, 2
heap.Values() // 1, 3, 2
_, _ = heap.Peek() // 1,true
_, _ = heap.Pop() // 1, true
_, _ = heap.Pop() // 2, true
_, _ = heap.Pop() // 3, true
_, _ = heap.Pop() // nil, false (nothing to pop)
heap.Push(1) // 1
heap.Clear() // empty
heap.Empty() // true
heap.Size() // 0
heap := binaryheap.New[int]() // empty (min-heap)
heap.Push(2) // 2
heap.Push(3) // 2, 3
heap.Push(1) // 1, 3, 2
heap.Values() // 1, 3, 2
_, _ = heap.Peek() // 1,true
_, _ = heap.Pop() // 1, true
_, _ = heap.Pop() // 2, true
_, _ = heap.Pop() // 3, true
_, _ = heap.Pop() // nil, false (nothing to pop)
heap.Push(1) // 1
heap.Clear() // empty
heap.Empty() // true
heap.Size() // 0
// Max-heap
inverseIntComparator := func(a, b interface{}) int {
return -utils.IntComparator(a, b)
inverseIntComparator := func(a, b int) int {
return -cmp.Compare(a, b)
}
heap = binaryheap.NewWith(inverseIntComparator) // empty (min-heap)
heap.Push(2) // 2

@ -6,12 +6,13 @@ package main
import (
"fmt"
"github.com/emirpasic/gods/trees/btree"
"github.com/emirpasic/gods/v2/trees/btree"
)
// BTreeExample to demonstrate basic usage of BTree
func main() {
tree := btree.NewWithIntComparator(3) // empty (keys are of type int)
tree := btree.New[int, string](3) // empty (keys are of type int)
tree.Put(1, "x") // 1->x
tree.Put(2, "b") // 1->x, 2->b (in order)

@ -4,23 +4,23 @@
package main
import cb "github.com/emirpasic/gods/queues/circularbuffer"
import cb "github.com/emirpasic/gods/v2/queues/circularbuffer"
// CircularBufferExample to demonstrate basic usage of CircularBuffer
func main() {
queue := cb.New(3) // empty (max size is 3)
queue.Enqueue(1) // 1
queue.Enqueue(2) // 1, 2
queue.Enqueue(3) // 1, 2, 3
_ = queue.Values() // 1, 2, 3
queue.Enqueue(3) // 4, 2, 3
_, _ = queue.Peek() // 4,true
_, _ = queue.Dequeue() // 4, true
_, _ = queue.Dequeue() // 2, true
_, _ = queue.Dequeue() // 3, true
_, _ = queue.Dequeue() // nil, false (nothing to deque)
queue.Enqueue(1) // 1
queue.Clear() // empty
queue.Empty() // true
_ = queue.Size() // 0
queue := cb.New[int](3) // empty (max size is 3)
queue.Enqueue(1) // 1
queue.Enqueue(2) // 1, 2
queue.Enqueue(3) // 1, 2, 3
_ = queue.Values() // 1, 2, 3
queue.Enqueue(3) // 4, 2, 3
_, _ = queue.Peek() // 4,true
_, _ = queue.Dequeue() // 4, true
_, _ = queue.Dequeue() // 2, true
_, _ = queue.Dequeue() // 3, true
_, _ = queue.Dequeue() // nil, false (nothing to deque)
queue.Enqueue(1) // 1
queue.Clear() // empty
queue.Empty() // true
_ = queue.Size() // 0
}

@ -6,7 +6,8 @@ package main
import (
"fmt"
"github.com/emirpasic/gods/sets/treeset"
"github.com/emirpasic/gods/v2/sets/treeset"
)
// User model (id and name)
@ -16,16 +17,12 @@ type User struct {
}
// Comparator function (sort by IDs)
func byID(a, b interface{}) int {
// Type assertion, program will panic if this is not respected
c1 := a.(User)
c2 := b.(User)
func byID(a, b User) int {
switch {
case c1.id > c2.id:
case a.id > b.id:
return 1
case c1.id < c2.id:
case a.id < b.id:
return -1
default:
return 0

@ -5,17 +5,18 @@
package main
import (
dll "github.com/emirpasic/gods/lists/doublylinkedlist"
"github.com/emirpasic/gods/utils"
"cmp"
dll "github.com/emirpasic/gods/v2/lists/doublylinkedlist"
)
// DoublyLinkedListExample to demonstrate basic usage of DoublyLinkedList
func main() {
list := dll.New()
list := dll.New[string]()
list.Add("a") // ["a"]
list.Append("b") // ["a","b"] (same as Add())
list.Prepend("c") // ["c","a","b"]
list.Sort(utils.StringComparator) // ["a","b","c"]
list.Sort(cmp.Compare[string]) // ["a","b","c"]
_, _ = list.Get(0) // "a",true
_, _ = list.Get(100) // nil,false
_ = list.Contains("a", "b", "c") // true

@ -6,12 +6,13 @@ package main
import (
"fmt"
"github.com/emirpasic/gods/sets/treeset"
"github.com/emirpasic/gods/v2/sets/treeset"
)
func printSet(txt string, set *treeset.Set) {
func printSet(txt string, set *treeset.Set[int]) {
fmt.Print(txt, "[ ")
set.Each(func(index int, value interface{}) {
set.Each(func(index int, value int) {
fmt.Print(value, " ")
})
fmt.Println("]")
@ -19,41 +20,41 @@ func printSet(txt string, set *treeset.Set) {
// EnumerableWithIndexExample to demonstrate basic usage of EnumerableWithIndex
func main() {
set := treeset.NewWithIntComparator()
set := treeset.New[int]()
set.Add(2, 3, 4, 2, 5, 6, 7, 8)
printSet("Initial", set) // [ 2 3 4 5 6 7 8 ]
even := set.Select(func(index int, value interface{}) bool {
return value.(int)%2 == 0
even := set.Select(func(index int, value int) bool {
return value%2 == 0
})
printSet("Even numbers", even) // [ 2 4 6 8 ]
foundIndex, foundValue := set.Find(func(index int, value interface{}) bool {
return value.(int)%2 == 0 && value.(int)%3 == 0
foundIndex, foundValue := set.Find(func(index int, value int) bool {
return value%2 == 0 && value%3 == 0
})
if foundIndex != -1 {
fmt.Println("Number divisible by 2 and 3 found is", foundValue, "at index", foundIndex) // value: 6, index: 4
}
square := set.Map(func(index int, value interface{}) interface{} {
return value.(int) * value.(int)
square := set.Map(func(index int, value int) int {
return value * value
})
printSet("Numbers squared", square) // [ 4 9 16 25 36 49 64 ]
bigger := set.Any(func(index int, value interface{}) bool {
return value.(int) > 5
bigger := set.Any(func(index int, value int) bool {
return value > 5
})
fmt.Println("Set contains a number bigger than 5 is ", bigger) // true
positive := set.All(func(index int, value interface{}) bool {
return value.(int) > 0
positive := set.All(func(index int, value int) bool {
return value > 0
})
fmt.Println("All numbers are positive is", positive) // true
evenNumbersSquared := set.Select(func(index int, value interface{}) bool {
return value.(int)%2 == 0
}).Map(func(index int, value interface{}) interface{} {
return value.(int) * value.(int)
evenNumbersSquared := set.Select(func(index int, value int) bool {
return value%2 == 0
}).Map(func(index int, value int) int {
return value * value
})
printSet("Chaining", evenNumbersSquared) // [ 4 16 36 64 ]
}

@ -6,12 +6,13 @@ package main
import (
"fmt"
"github.com/emirpasic/gods/maps/treemap"
"github.com/emirpasic/gods/v2/maps/treemap"
)
func printMap(txt string, m *treemap.Map) {
func printMap(txt string, m *treemap.Map[string, int]) {
fmt.Print(txt, " { ")
m.Each(func(key interface{}, value interface{}) {
m.Each(func(key string, value int) {
fmt.Print(key, ":", value, " ")
})
fmt.Println("}")
@ -19,7 +20,7 @@ func printMap(txt string, m *treemap.Map) {
// EunumerableWithKeyExample to demonstrate basic usage of EunumerableWithKey
func main() {
m := treemap.NewWithStringComparator()
m := treemap.New[string, int]()
m.Put("g", 7)
m.Put("f", 6)
m.Put("e", 5)
@ -29,37 +30,37 @@ func main() {
m.Put("a", 1)
printMap("Initial", m) // { a:1 b:2 c:3 d:4 e:5 f:6 g:7 }
even := m.Select(func(key interface{}, value interface{}) bool {
return value.(int)%2 == 0
even := m.Select(func(key string, value int) bool {
return value%2 == 0
})
printMap("Elements with even values", even) // { b:2 d:4 f:6 }
foundKey, foundValue := m.Find(func(key interface{}, value interface{}) bool {
return value.(int)%2 == 0 && value.(int)%3 == 0
foundKey, foundValue := m.Find(func(key string, value int) bool {
return value%2 == 0 && value%3 == 0
})
if foundKey != nil {
if foundKey != "" {
fmt.Println("Element with value divisible by 2 and 3 found is", foundValue, "with key", foundKey) // value: 6, index: 4
}
square := m.Map(func(key interface{}, value interface{}) (interface{}, interface{}) {
return key.(string) + key.(string), value.(int) * value.(int)
square := m.Map(func(key string, value int) (string, int) {
return key + key, value * value
})
printMap("Elements' values squared and letters duplicated", square) // { aa:1 bb:4 cc:9 dd:16 ee:25 ff:36 gg:49 }
bigger := m.Any(func(key interface{}, value interface{}) bool {
return value.(int) > 5
bigger := m.Any(func(key string, value int) bool {
return value > 5
})
fmt.Println("Map contains element whose value is bigger than 5 is", bigger) // true
positive := m.All(func(key interface{}, value interface{}) bool {
return value.(int) > 0
positive := m.All(func(key string, value int) bool {
return value > 0
})
fmt.Println("All map's elements have positive values is", positive) // true
evenNumbersSquared := m.Select(func(key interface{}, value interface{}) bool {
return value.(int)%2 == 0
}).Map(func(key interface{}, value interface{}) (interface{}, interface{}) {
return key, value.(int) * value.(int)
evenNumbersSquared := m.Select(func(key string, value int) bool {
return value%2 == 0
}).Map(func(key string, value int) (string, int) {
return key, value * value
})
printMap("Chaining", evenNumbersSquared) // { b:4 d:16 f:36 }
}

@ -1,17 +0,0 @@
// 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/utils"
// SortExample to demonstrate basic usage of basic sort
func main() {
strings := []interface{}{} // []
strings = append(strings, "d") // ["d"]
strings = append(strings, "a") // ["d","a"]
strings = append(strings, "b") // ["d","a",b"
strings = append(strings, "c") // ["d","a",b","c"]
utils.Sort(strings, utils.StringComparator) // ["a","b","c","d"]
}

@ -4,22 +4,22 @@
package main
import "github.com/emirpasic/gods/maps/hashbidimap"
import "github.com/emirpasic/gods/v2/maps/hashbidimap"
// HashBidiMapExample to demonstrate basic usage of HashMap
func main() {
m := hashbidimap.New() // empty
m.Put(1, "x") // 1->x
m.Put(3, "b") // 1->x, 3->b (random order)
m.Put(1, "a") // 1->a, 3->b (random order)
m.Put(2, "b") // 1->a, 2->b (random order)
_, _ = m.GetKey("a") // 1, true
_, _ = m.Get(2) // b, true
_, _ = m.Get(3) // nil, false
_ = m.Values() // []interface {}{"a", "b"} (random order)
_ = m.Keys() // []interface {}{1, 2} (random order)
m.Remove(1) // 2->b
m.Clear() // empty
m.Empty() // true
m.Size() // 0
m := hashbidimap.New[int, string]() // empty
m.Put(1, "x") // 1->x
m.Put(3, "b") // 1->x, 3->b (random order)
m.Put(1, "a") // 1->a, 3->b (random order)
m.Put(2, "b") // 1->a, 2->b (random order)
_, _ = m.GetKey("a") // 1, true
_, _ = m.Get(2) // b, true
_, _ = m.Get(3) // nil, false
_ = m.Values() // []interface {}{"a", "b"} (random order)
_ = m.Keys() // []interface {}{1, 2} (random order)
m.Remove(1) // 2->b
m.Clear() // empty
m.Empty() // true
m.Size() // 0
}

@ -4,20 +4,20 @@
package main
import "github.com/emirpasic/gods/maps/hashmap"
import "github.com/emirpasic/gods/v2/maps/hashmap"
// HashMapExample to demonstrate basic usage of HashMap
func main() {
m := hashmap.New() // empty
m.Put(1, "x") // 1->x
m.Put(2, "b") // 2->b, 1->x (random order)
m.Put(1, "a") // 2->b, 1->a (random order)
_, _ = m.Get(2) // b, true
_, _ = m.Get(3) // nil, false
_ = m.Values() // []interface {}{"b", "a"} (random order)
_ = m.Keys() // []interface {}{1, 2} (random order)
m.Remove(1) // 2->b
m.Clear() // empty
m.Empty() // true
m.Size() // 0
m := hashmap.New[int, string]() // empty
m.Put(1, "x") // 1->x
m.Put(2, "b") // 2->b, 1->x (random order)
m.Put(1, "a") // 2->b, 1->a (random order)
_, _ = m.Get(2) // b, true
_, _ = m.Get(3) // nil, false
_ = m.Values() // []interface {}{"b", "a"} (random order)
_ = m.Keys() // []interface {}{1, 2} (random order)
m.Remove(1) // 2->b
m.Clear() // empty
m.Empty() // true
m.Size() // 0
}

@ -4,20 +4,20 @@
package main
import "github.com/emirpasic/gods/sets/hashset"
import "github.com/emirpasic/gods/v2/sets/hashset"
// HashSetExample to demonstrate basic usage of HashSet
func main() {
set := hashset.New() // empty (keys are of type int)
set.Add(1) // 1
set.Add(2, 2, 3, 4, 5) // 3, 1, 2, 4, 5 (random order, duplicates ignored)
set.Remove(4) // 5, 3, 2, 1 (random order)
set.Remove(2, 3) // 1, 5 (random order)
set.Contains(1) // true
set.Contains(1, 5) // true
set.Contains(1, 6) // false
_ = set.Values() // []int{5,1} (random order)
set.Clear() // empty
set.Empty() // true
set.Size() // 0
set := hashset.New[int]() // empty (keys are of type int)
set.Add(1) // 1
set.Add(2, 2, 3, 4, 5) // 3, 1, 2, 4, 5 (random order, duplicates ignored)
set.Remove(4) // 5, 3, 2, 1 (random order)
set.Remove(2, 3) // 1, 5 (random order)
set.Contains(1) // true
set.Contains(1, 5) // true
set.Contains(1, 6) // false
_ = set.Values() // []int{5,1} (random order)
set.Clear() // empty
set.Empty() // true
set.Size() // 0
}

@ -6,13 +6,14 @@ package main
import (
"fmt"
"github.com/emirpasic/gods/sets/treeset"
"strings"
"github.com/emirpasic/gods/v2/sets/treeset"
)
// IteratorWithIndexExample to demonstrate basic usage of IteratorWithIndex
func main() {
set := treeset.NewWithStringComparator()
set := treeset.New[string]()
set.Add("a", "b", "c")
it := set.Iterator()
@ -51,8 +52,8 @@ func main() {
}
// Seek element starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
it.Begin()

@ -6,13 +6,14 @@ package main
import (
"fmt"
"github.com/emirpasic/gods/maps/treemap"
"strings"
"github.com/emirpasic/gods/v2/maps/treemap"
)
// IteratorWithKeyExample to demonstrate basic usage of IteratorWithKey
func main() {
m := treemap.NewWithIntComparator()
m := treemap.New[int, string]()
m.Put(0, "a")
m.Put(1, "b")
m.Put(2, "c")
@ -53,8 +54,8 @@ func main() {
}
// Seek key-value pair whose value starts with "b"
seek := func(key interface{}, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(key int, value string) bool {
return strings.HasSuffix(value, "b")
}
it.Begin()

@ -4,20 +4,20 @@
package main
import "github.com/emirpasic/gods/maps/linkedhashmap"
import "github.com/emirpasic/gods/v2/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
m := linkedhashmap.New[int, string]() // 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
}

@ -4,20 +4,20 @@
package main
import "github.com/emirpasic/gods/sets/linkedhashset"
import "github.com/emirpasic/gods/v2/sets/linkedhashset"
// LinkedHashSetExample to demonstrate basic usage of LinkedHashSet
func main() {
set := linkedhashset.New() // empty
set.Add(5) // 5
set.Add(4, 4, 3, 2, 1) // 5, 4, 3, 2, 1 (in insertion-order, duplicates ignored)
set.Remove(4) // 5, 3, 2, 1 (in insertion-order)
set.Remove(2, 3) // 5, 1 (in insertion-order)
set.Contains(1) // true
set.Contains(1, 5) // true
set.Contains(1, 6) // false
_ = set.Values() // []int{5, 1} (in insertion-order)
set.Clear() // empty
set.Empty() // true
set.Size() // 0
set := linkedhashset.New[int]() // empty
set.Add(5) // 5
set.Add(4, 4, 3, 2, 1) // 5, 4, 3, 2, 1 (in insertion-order, duplicates ignored)
set.Remove(4) // 5, 3, 2, 1 (in insertion-order)
set.Remove(2, 3) // 5, 1 (in insertion-order)
set.Contains(1) // true
set.Contains(1, 5) // true
set.Contains(1, 6) // false
_ = set.Values() // []int{5, 1} (in insertion-order)
set.Clear() // empty
set.Empty() // true
set.Size() // 0
}

@ -4,20 +4,20 @@
package main
import llq "github.com/emirpasic/gods/queues/linkedlistqueue"
import llq "github.com/emirpasic/gods/v2/queues/linkedlistqueue"
// LinkedListQueueExample to demonstrate basic usage of LinkedListQueue
func main() {
queue := llq.New() // empty
queue.Enqueue(1) // 1
queue.Enqueue(2) // 1, 2
_ = queue.Values() // 1, 2 (FIFO order)
_, _ = queue.Peek() // 1,true
_, _ = queue.Dequeue() // 1, true
_, _ = queue.Dequeue() // 2, true
_, _ = queue.Dequeue() // nil, false (nothing to deque)
queue.Enqueue(1) // 1
queue.Clear() // empty
queue.Empty() // true
_ = queue.Size() // 0
queue := llq.New[int]() // empty
queue.Enqueue(1) // 1
queue.Enqueue(2) // 1, 2
_ = queue.Values() // 1, 2 (FIFO order)
_, _ = queue.Peek() // 1,true
_, _ = queue.Dequeue() // 1, true
_, _ = queue.Dequeue() // 2, true
_, _ = queue.Dequeue() // nil, false (nothing to deque)
queue.Enqueue(1) // 1
queue.Clear() // empty
queue.Empty() // true
_ = queue.Size() // 0
}

@ -4,20 +4,20 @@
package main
import lls "github.com/emirpasic/gods/stacks/linkedliststack"
import lls "github.com/emirpasic/gods/v2/stacks/linkedliststack"
// LinkedListStackExample to demonstrate basic usage of LinkedListStack
func main() {
stack := lls.New() // empty
stack.Push(1) // 1
stack.Push(2) // 1, 2
stack.Values() // 2, 1 (LIFO order)
_, _ = stack.Peek() // 2,true
_, _ = stack.Pop() // 2, true
_, _ = stack.Pop() // 1, true
_, _ = stack.Pop() // nil, false (nothing to pop)
stack.Push(1) // 1
stack.Clear() // empty
stack.Empty() // true
stack.Size() // 0
stack := lls.New[int]() // empty
stack.Push(1) // 1
stack.Push(2) // 1, 2
stack.Values() // 2, 1 (LIFO order)
_, _ = stack.Peek() // 2,true
_, _ = stack.Pop() // 2, true
_, _ = stack.Pop() // 1, true
_, _ = stack.Pop() // nil, false (nothing to pop)
stack.Push(1) // 1
stack.Clear() // empty
stack.Empty() // true
stack.Size() // 0
}

@ -5,8 +5,9 @@
package main
import (
pq "github.com/emirpasic/gods/queues/priorityqueue"
"github.com/emirpasic/gods/utils"
"cmp"
pq "github.com/emirpasic/gods/v2/queues/priorityqueue"
)
// Element is an entry in the priority queue
@ -16,10 +17,8 @@ type Element struct {
}
// Comparator function (sort by element's priority value in descending order)
func byPriority(a, b interface{}) int {
priorityA := a.(Element).priority
priorityB := b.(Element).priority
return -utils.IntComparator(priorityA, priorityB) // "-" descending order
func byPriority(a, b Element) int {
return -cmp.Compare(a.priority, b.priority) // "-" descending order
}
// PriorityQueueExample to demonstrate basic usage of BinaryHeap

@ -6,12 +6,13 @@ package main
import (
"fmt"
rbt "github.com/emirpasic/gods/trees/redblacktree"
rbt "github.com/emirpasic/gods/v2/trees/redblacktree"
)
// RedBlackTreeExample to demonstrate basic usage of RedBlackTree
func main() {
tree := rbt.NewWithIntComparator() // empty(keys are of type int)
tree := rbt.New[int, string]() // empty(keys are of type int)
tree.Put(1, "x") // 1->x
tree.Put(2, "b") // 1->x, 2->b (in order)

@ -6,53 +6,54 @@ package redblacktreeextended
import (
"fmt"
rbt "github.com/emirpasic/gods/trees/redblacktree"
rbt "github.com/emirpasic/gods/v2/trees/redblacktree"
)
// RedBlackTreeExtended to demonstrate how to extend a RedBlackTree to include new functions
type RedBlackTreeExtended struct {
*rbt.Tree
type RedBlackTreeExtended[K comparable, V any] struct {
*rbt.Tree[K, V]
}
// GetMin gets the min value and flag if found
func (tree *RedBlackTreeExtended) GetMin() (value interface{}, found bool) {
func (tree *RedBlackTreeExtended[K, V]) GetMin() (value V, found bool) {
node, found := tree.getMinFromNode(tree.Root)
if node != nil {
if found {
return node.Value, found
}
return nil, false
return value, false
}
// GetMax gets the max value and flag if found
func (tree *RedBlackTreeExtended) GetMax() (value interface{}, found bool) {
func (tree *RedBlackTreeExtended[K, V]) GetMax() (value V, found bool) {
node, found := tree.getMaxFromNode(tree.Root)
if node != nil {
if found {
return node.Value, found
}
return nil, false
return value, false
}
// RemoveMin removes the min value and flag if found
func (tree *RedBlackTreeExtended) RemoveMin() (value interface{}, deleted bool) {
func (tree *RedBlackTreeExtended[K, V]) RemoveMin() (value V, deleted bool) {
node, found := tree.getMinFromNode(tree.Root)
if found {
tree.Remove(node.Key)
return node.Value, found
}
return nil, false
return value, false
}
// RemoveMax removes the max value and flag if found
func (tree *RedBlackTreeExtended) RemoveMax() (value interface{}, deleted bool) {
func (tree *RedBlackTreeExtended[K, V]) RemoveMax() (value V, deleted bool) {
node, found := tree.getMaxFromNode(tree.Root)
if found {
tree.Remove(node.Key)
return node.Value, found
}
return nil, false
return value, false
}
func (tree *RedBlackTreeExtended) getMinFromNode(node *rbt.Node) (foundNode *rbt.Node, found bool) {
func (tree *RedBlackTreeExtended[K, V]) getMinFromNode(node *rbt.Node[K, V]) (foundNode *rbt.Node[K, V], found bool) {
if node == nil {
return nil, false
}
@ -62,7 +63,7 @@ func (tree *RedBlackTreeExtended) getMinFromNode(node *rbt.Node) (foundNode *rbt
return tree.getMinFromNode(node.Left)
}
func (tree *RedBlackTreeExtended) getMaxFromNode(node *rbt.Node) (foundNode *rbt.Node, found bool) {
func (tree *RedBlackTreeExtended[K, V]) getMaxFromNode(node *rbt.Node[K, V]) (foundNode *rbt.Node[K, V], found bool) {
if node == nil {
return nil, false
}
@ -72,7 +73,7 @@ func (tree *RedBlackTreeExtended) getMaxFromNode(node *rbt.Node) (foundNode *rbt
return tree.getMaxFromNode(node.Right)
}
func print(tree *RedBlackTreeExtended) {
func print(tree *RedBlackTreeExtended[int, string]) {
max, _ := tree.GetMax()
min, _ := tree.GetMin()
fmt.Printf("Value for max key: %v \n", max)
@ -82,7 +83,7 @@ func print(tree *RedBlackTreeExtended) {
// RedBlackTreeExtendedExample main method on how to use the custom red-black tree above
func main() {
tree := RedBlackTreeExtended{rbt.NewWithIntComparator()}
tree := RedBlackTreeExtended[int, string]{rbt.New[int, string]()}
tree.Put(1, "a") // 1->x (in order)
tree.Put(2, "b") // 1->x, 2->b (in order)

@ -2,13 +2,14 @@ package serialization
import (
"fmt"
"github.com/emirpasic/gods/lists/arraylist"
"github.com/emirpasic/gods/maps/hashmap"
"github.com/emirpasic/gods/v2/lists/arraylist"
"github.com/emirpasic/gods/v2/maps/hashmap"
)
// ListSerializationExample demonstrates how to serialize and deserialize lists to and from JSON
func ListSerializationExample() {
list := arraylist.New()
list := arraylist.New[string]()
list.Add("a", "b", "c")
// Serialization (marshalling)
@ -29,7 +30,7 @@ func ListSerializationExample() {
// MapSerializationExample demonstrates how to serialize and deserialize maps to and from JSON
func MapSerializationExample() {
m := hashmap.New()
m := hashmap.New[string, string]()
m.Put("a", "1")
m.Put("b", "2")
m.Put("c", "3")

@ -5,17 +5,18 @@
package main
import (
sll "github.com/emirpasic/gods/lists/singlylinkedlist"
"github.com/emirpasic/gods/utils"
"cmp"
sll "github.com/emirpasic/gods/v2/lists/singlylinkedlist"
)
// SinglyLinkedListExample to demonstrate basic usage of SinglyLinkedList
func main() {
list := sll.New()
list := sll.New[string]()
list.Add("a") // ["a"]
list.Append("b") // ["a","b"] (same as Add())
list.Prepend("c") // ["c","a","b"]
list.Sort(utils.StringComparator) // ["a","b","c"]
list.Sort(cmp.Compare[string]) // ["a","b","c"]
_, _ = list.Get(0) // "a",true
_, _ = list.Get(100) // nil,false
_ = list.Contains("a", "b", "c") // true

@ -5,13 +5,12 @@
package main
import (
"github.com/emirpasic/gods/maps/treebidimap"
"github.com/emirpasic/gods/utils"
"github.com/emirpasic/gods/v2/maps/treebidimap"
)
// TreeBidiMapExample to demonstrate basic usage of TreeBidiMap
func main() {
m := treebidimap.NewWith(utils.IntComparator, utils.StringComparator)
m := treebidimap.New[int, string]()
m.Put(1, "x") // 1->x
m.Put(3, "b") // 1->x, 3->b (ordered)
m.Put(1, "a") // 1->a, 3->b (ordered)

@ -4,20 +4,20 @@
package main
import "github.com/emirpasic/gods/maps/treemap"
import "github.com/emirpasic/gods/v2/maps/treemap"
// TreeMapExample to demonstrate basic usage of TreeMap
func main() {
m := treemap.NewWithIntComparator() // empty (keys are of type int)
m.Put(1, "x") // 1->x
m.Put(2, "b") // 1->x, 2->b (in order)
m.Put(1, "a") // 1->a, 2->b (in order)
_, _ = m.Get(2) // b, true
_, _ = m.Get(3) // nil, false
_ = m.Values() // []interface {}{"a", "b"} (in order)
_ = m.Keys() // []interface {}{1, 2} (in order)
m.Remove(1) // 2->b
m.Clear() // empty
m.Empty() // true
m.Size() // 0
m := treemap.New[int, string]() // empty
m.Put(1, "x") // 1->x
m.Put(2, "b") // 1->x, 2->b (in order)
m.Put(1, "a") // 1->a, 2->b (in order)
_, _ = m.Get(2) // b, true
_, _ = m.Get(3) // nil, false
_ = m.Values() // []interface {}{"a", "b"} (in order)
_ = m.Keys() // []interface {}{1, 2} (in order)
m.Remove(1) // 2->b
m.Clear() // empty
m.Empty() // true
m.Size() // 0
}

@ -4,20 +4,20 @@
package main
import "github.com/emirpasic/gods/sets/treeset"
import "github.com/emirpasic/gods/v2/sets/treeset"
// TreeSetExample to demonstrate basic usage of TreeSet
func main() {
set := treeset.NewWithIntComparator() // empty
set.Add(1) // 1
set.Add(2, 2, 3, 4, 5) // 1, 2, 3, 4, 5 (in order, duplicates ignored)
set.Remove(4) // 1, 2, 3, 5 (in order)
set.Remove(2, 3) // 1, 5 (in order)
set.Contains(1) // true
set.Contains(1, 5) // true
set.Contains(1, 6) // false
_ = set.Values() // []int{1,5} (in order)
set.Clear() // empty
set.Empty() // true
set.Size() // 0
set := treeset.New[int]() // empty
set.Add(1) // 1
set.Add(2, 2, 3, 4, 5) // 1, 2, 3, 4, 5 (in order, duplicates ignored)
set.Remove(4) // 1, 2, 3, 5 (in order)
set.Remove(2, 3) // 1, 5 (in order)
set.Contains(1) // true
set.Contains(1, 5) // true
set.Contains(1, 6) // false
_ = set.Values() // []int{1,5} (in order)
set.Clear() // empty
set.Empty() // true
set.Size() // 0
}

@ -1,3 +1,3 @@
module github.com/emirpasic/gods
module github.com/emirpasic/gods/v2
go 1.2
go 1.21

@ -0,0 +1,2 @@
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=

@ -11,18 +11,19 @@ package arraylist
import (
"fmt"
"slices"
"strings"
"github.com/emirpasic/gods/lists"
"github.com/emirpasic/gods/utils"
"github.com/emirpasic/gods/v2/lists"
"github.com/emirpasic/gods/v2/utils"
)
// Assert List implementation
var _ lists.List = (*List)(nil)
var _ lists.List[int] = (*List[int])(nil)
// List holds the elements in a slice
type List struct {
elements []interface{}
type List[T comparable] struct {
elements []T
size int
}
@ -32,8 +33,8 @@ const (
)
// New instantiates a new list and adds the passed values, if any, to the list
func New(values ...interface{}) *List {
list := &List{}
func New[T comparable](values ...T) *List[T] {
list := &List[T]{}
if len(values) > 0 {
list.Add(values...)
}
@ -41,7 +42,7 @@ func New(values ...interface{}) *List {
}
// Add appends a value at the end of the list
func (list *List) Add(values ...interface{}) {
func (list *List[T]) Add(values ...T) {
list.growBy(len(values))
for _, value := range values {
list.elements[list.size] = value
@ -51,23 +52,24 @@ func (list *List) Add(values ...interface{}) {
// Get returns the element at index.
// Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false.
func (list *List) Get(index int) (interface{}, bool) {
func (list *List[T]) Get(index int) (T, bool) {
if !list.withinRange(index) {
return nil, false
var t T
return t, false
}
return list.elements[index], true
}
// Remove removes the element at the given index from the list.
func (list *List) Remove(index int) {
func (list *List[T]) Remove(index int) {
if !list.withinRange(index) {
return
}
list.elements[index] = nil // cleanup reference
clear(list.elements[index : index+1])
copy(list.elements[index:], list.elements[index+1:list.size]) // shift to the left by one (slow operation, need ways to optimize this)
list.size--
@ -78,7 +80,7 @@ func (list *List) Remove(index int) {
// All elements have to be present in the set for the method to return true.
// Performance time complexity of n^2.
// Returns true if no arguments are passed at all, i.e. set is always super-set of empty set.
func (list *List) Contains(values ...interface{}) bool {
func (list *List[T]) Contains(values ...T) bool {
for _, searchValue := range values {
found := false
@ -96,14 +98,14 @@ func (list *List) Contains(values ...interface{}) bool {
}
// Values returns all elements in the list.
func (list *List) Values() []interface{} {
newElements := make([]interface{}, list.size, list.size)
func (list *List[T]) Values() []T {
newElements := make([]T, list.size, list.size)
copy(newElements, list.elements[:list.size])
return newElements
}
//IndexOf returns index of provided element
func (list *List) IndexOf(value interface{}) int {
// IndexOf returns index of provided element
func (list *List[T]) IndexOf(value T) int {
if list.size == 0 {
return -1
}
@ -116,31 +118,31 @@ func (list *List) IndexOf(value interface{}) int {
}
// Empty returns true if list does not contain any elements.
func (list *List) Empty() bool {
func (list *List[T]) Empty() bool {
return list.size == 0
}
// Size returns number of elements within the list.
func (list *List) Size() int {
func (list *List[T]) Size() int {
return list.size
}
// Clear removes all elements from the list.
func (list *List) Clear() {
func (list *List[T]) Clear() {
list.size = 0
list.elements = []interface{}{}
list.elements = []T{}
}
// Sort sorts values (in-place) using.
func (list *List) Sort(comparator utils.Comparator) {
func (list *List[T]) Sort(comparator utils.Comparator[T]) {
if len(list.elements) < 2 {
return
}
utils.Sort(list.elements[:list.size], comparator)
slices.SortFunc(list.elements[:list.size], comparator)
}
// Swap swaps the two values at the specified positions.
func (list *List) Swap(i, j int) {
func (list *List[T]) Swap(i, j int) {
if list.withinRange(i) && list.withinRange(j) {
list.elements[i], list.elements[j] = list.elements[j], list.elements[i]
}
@ -149,7 +151,7 @@ func (list *List) Swap(i, j int) {
// Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right.
// Does not do anything if position is negative or bigger than list's size
// Note: position equal to list's size is valid, i.e. append.
func (list *List) Insert(index int, values ...interface{}) {
func (list *List[T]) Insert(index int, values ...T) {
if !list.withinRange(index) {
// Append
@ -169,7 +171,7 @@ func (list *List) Insert(index int, values ...interface{}) {
// Set the value at specified index
// Does not do anything if position is negative or bigger than list's size
// Note: position equal to list's size is valid, i.e. append.
func (list *List) Set(index int, value interface{}) {
func (list *List[T]) Set(index int, value T) {
if !list.withinRange(index) {
// Append
@ -183,9 +185,9 @@ func (list *List) Set(index int, value interface{}) {
}
// String returns a string representation of container
func (list *List) String() string {
func (list *List[T]) String() string {
str := "ArrayList\n"
values := []string{}
values := make([]string, 0, list.size)
for _, value := range list.elements[:list.size] {
values = append(values, fmt.Sprintf("%v", value))
}
@ -194,18 +196,18 @@ func (list *List) String() string {
}
// Check that the index is within bounds of the list
func (list *List) withinRange(index int) bool {
func (list *List[T]) withinRange(index int) bool {
return index >= 0 && index < list.size
}
func (list *List) resize(cap int) {
newElements := make([]interface{}, cap, cap)
func (list *List[T]) resize(cap int) {
newElements := make([]T, cap, cap)
copy(newElements, list.elements)
list.elements = newElements
}
// Expand the array if necessary, i.e. capacity will be reached if we add n elements
func (list *List) growBy(n int) {
func (list *List[T]) growBy(n int) {
// When capacity is reached, grow by a factor of growthFactor and add number of elements
currentCapacity := cap(list.elements)
if list.size+n >= currentCapacity {
@ -215,7 +217,7 @@ func (list *List) growBy(n int) {
}
// Shrink the array if necessary, i.e. when size is shrinkFactor percent of current capacity
func (list *List) shrink() {
func (list *List[T]) shrink() {
if shrinkFactor == 0.0 {
return
}

@ -5,21 +5,21 @@
package arraylist
import (
"cmp"
"encoding/json"
"fmt"
"github.com/emirpasic/gods/utils"
"slices"
"strings"
"testing"
)
func TestListNew(t *testing.T) {
list1 := New()
list1 := New[int]()
if actualValue := list1.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
list2 := New(1, "b")
list2 := New[int](1, 2)
if actualValue := list2.Size(); actualValue != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
@ -29,17 +29,17 @@ func TestListNew(t *testing.T) {
t.Errorf("Got %v expected %v", actualValue, 1)
}
if actualValue, ok := list2.Get(1); actualValue != "b" || !ok {
t.Errorf("Got %v expected %v", actualValue, "b")
if actualValue, ok := list2.Get(1); actualValue != 2 || !ok {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if actualValue, ok := list2.Get(2); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
if actualValue, ok := list2.Get(2); actualValue != 0 || ok {
t.Errorf("Got %v expected %v", actualValue, 0)
}
}
func TestListAdd(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue := list.Empty(); actualValue != false {
@ -54,7 +54,7 @@ func TestListAdd(t *testing.T) {
}
func TestListIndexOf(t *testing.T) {
list := New()
list := New[string]()
expectedIndex := -1
if index := list.IndexOf("a"); index != expectedIndex {
@ -81,12 +81,12 @@ func TestListIndexOf(t *testing.T) {
}
func TestListRemove(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
list.Remove(2)
if actualValue, ok := list.Get(2); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
if actualValue, ok := list.Get(2); actualValue != "" || ok {
t.Errorf("Got %v expected %v", actualValue, "")
}
list.Remove(1)
list.Remove(0)
@ -100,7 +100,7 @@ func TestListRemove(t *testing.T) {
}
func TestListGet(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue, ok := list.Get(0); actualValue != "a" || !ok {
@ -112,8 +112,8 @@ func TestListGet(t *testing.T) {
if actualValue, ok := list.Get(2); actualValue != "c" || !ok {
t.Errorf("Got %v expected %v", actualValue, "c")
}
if actualValue, ok := list.Get(3); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
if actualValue, ok := list.Get(3); actualValue != "" || ok {
t.Errorf("Got %v expected %v", actualValue, "")
}
list.Remove(0)
if actualValue, ok := list.Get(0); actualValue != "b" || !ok {
@ -122,7 +122,7 @@ func TestListGet(t *testing.T) {
}
func TestListSwap(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
list.Swap(0, 1)
@ -132,21 +132,21 @@ func TestListSwap(t *testing.T) {
}
func TestListSort(t *testing.T) {
list := New()
list.Sort(utils.StringComparator)
list := New[string]()
list.Sort(cmp.Compare[string])
list.Add("e", "f", "g", "a", "b", "c", "d")
list.Sort(utils.StringComparator)
list.Sort(cmp.Compare[string])
for i := 1; i < list.Size(); i++ {
a, _ := list.Get(i - 1)
b, _ := list.Get(i)
if a.(string) > b.(string) {
if a > b {
t.Errorf("Not sorted! %s > %s", a, b)
}
}
}
func TestListClear(t *testing.T) {
list := New()
list := New[string]()
list.Add("e", "f", "g", "a", "b", "c", "d")
list.Clear()
if actualValue := list.Empty(); actualValue != true {
@ -158,13 +158,13 @@ func TestListClear(t *testing.T) {
}
func TestListContains(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue := list.Contains("a"); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
if actualValue := list.Contains(nil); actualValue != false {
if actualValue := list.Contains(""); actualValue != false {
t.Errorf("Got %v expected %v", actualValue, false)
}
if actualValue := list.Contains("a", "b", "c"); actualValue != true {
@ -183,16 +183,16 @@ func TestListContains(t *testing.T) {
}
func TestListValues(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
if actualValue, expectedValue := list.Values(), []string{"a", "b", "c"}; !slices.Equal(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestListInsert(t *testing.T) {
list := New()
list := New[string]()
list.Insert(0, "b", "c")
list.Insert(0, "a")
list.Insert(10, "x") // ignore
@ -203,13 +203,13 @@ func TestListInsert(t *testing.T) {
if actualValue := list.Size(); actualValue != 4 {
t.Errorf("Got %v expected %v", actualValue, 4)
}
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", list.Values()...), "abcd"; actualValue != expectedValue {
if actualValue, expectedValue := strings.Join(list.Values(), ""), "abcd"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestListSet(t *testing.T) {
list := New()
list := New[string]()
list.Set(0, "a")
list.Set(1, "b")
if actualValue := list.Size(); actualValue != 2 {
@ -224,15 +224,15 @@ func TestListSet(t *testing.T) {
if actualValue := list.Size(); actualValue != 3 {
t.Errorf("Got %v expected %v", actualValue, 3)
}
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abbc"; actualValue != expectedValue {
if actualValue, expectedValue := list.Values(), []string{"a", "bb", "c"}; !slices.Equal(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestListEach(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
list.Each(func(index int, value interface{}) {
list.Each(func(index int, value string) {
switch index {
case 0:
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
@ -253,10 +253,10 @@ func TestListEach(t *testing.T) {
}
func TestListMap(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
mappedList := list.Map(func(index int, value interface{}) interface{} {
return "mapped: " + value.(string)
mappedList := list.Map(func(index int, value string) string {
return "mapped: " + value
})
if actualValue, _ := mappedList.Get(0); actualValue != "mapped: a" {
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
@ -273,10 +273,10 @@ func TestListMap(t *testing.T) {
}
func TestListSelect(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
selectedList := list.Select(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "b"
selectedList := list.Select(func(index int, value string) bool {
return value >= "a" && value <= "b"
})
if actualValue, _ := selectedList.Get(0); actualValue != "a" {
t.Errorf("Got %v expected %v", actualValue, "value: a")
@ -290,60 +290,60 @@ func TestListSelect(t *testing.T) {
}
func TestListAny(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
any := list.Any(func(index int, value interface{}) bool {
return value.(string) == "c"
any := list.Any(func(index int, value string) bool {
return value == "c"
})
if any != true {
t.Errorf("Got %v expected %v", any, true)
}
any = list.Any(func(index int, value interface{}) bool {
return value.(string) == "x"
any = list.Any(func(index int, value string) bool {
return value == "x"
})
if any != false {
t.Errorf("Got %v expected %v", any, false)
}
}
func TestListAll(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
all := list.All(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "c"
all := list.All(func(index int, value string) bool {
return value >= "a" && value <= "c"
})
if all != true {
t.Errorf("Got %v expected %v", all, true)
}
all = list.All(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "b"
all = list.All(func(index int, value string) bool {
return value >= "a" && value <= "b"
})
if all != false {
t.Errorf("Got %v expected %v", all, false)
}
}
func TestListFind(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
foundIndex, foundValue := list.Find(func(index int, value interface{}) bool {
return value.(string) == "c"
foundIndex, foundValue := list.Find(func(index int, value string) bool {
return value == "c"
})
if foundValue != "c" || foundIndex != 2 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, "c", 2)
}
foundIndex, foundValue = list.Find(func(index int, value interface{}) bool {
return value.(string) == "x"
foundIndex, foundValue = list.Find(func(index int, value string) bool {
return value == "x"
})
if foundValue != nil || foundIndex != -1 {
if foundValue != "" || foundIndex != -1 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, nil, nil)
}
}
func TestListChaining(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
chainedList := list.Select(func(index int, value interface{}) bool {
return value.(string) > "a"
}).Map(func(index int, value interface{}) interface{} {
return value.(string) + value.(string)
chainedList := list.Select(func(index int, value string) bool {
return value > "a"
}).Map(func(index int, value string) string {
return value + value
})
if chainedList.Size() != 2 {
t.Errorf("Got %v expected %v", chainedList.Size(), 2)
@ -357,7 +357,7 @@ func TestListChaining(t *testing.T) {
}
func TestListIteratorNextOnEmpty(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
for it.Next() {
t.Errorf("Shouldn't iterate on empty list")
@ -365,7 +365,7 @@ func TestListIteratorNextOnEmpty(t *testing.T) {
}
func TestListIteratorNext(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
it := list.Iterator()
count := 0
@ -396,7 +396,7 @@ func TestListIteratorNext(t *testing.T) {
}
func TestListIteratorPrevOnEmpty(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
for it.Prev() {
t.Errorf("Shouldn't iterate on empty list")
@ -404,7 +404,7 @@ func TestListIteratorPrevOnEmpty(t *testing.T) {
}
func TestListIteratorPrev(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
it := list.Iterator()
for it.Next() {
@ -437,7 +437,7 @@ func TestListIteratorPrev(t *testing.T) {
}
func TestListIteratorBegin(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
it.Begin()
list.Add("a", "b", "c")
@ -451,7 +451,7 @@ func TestListIteratorBegin(t *testing.T) {
}
func TestListIteratorEnd(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
if index := it.Index(); index != -1 {
@ -476,7 +476,7 @@ func TestListIteratorEnd(t *testing.T) {
}
func TestListIteratorFirst(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -491,7 +491,7 @@ func TestListIteratorFirst(t *testing.T) {
}
func TestListIteratorLast(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -507,13 +507,13 @@ func TestListIteratorLast(t *testing.T) {
func TestListIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// NextTo (empty)
{
list := New()
list := New[string]()
it := list.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
@ -522,7 +522,7 @@ func TestListIteratorNextTo(t *testing.T) {
// NextTo (not found)
{
list := New()
list := New[string]()
list.Add("xx", "yy")
it := list.Iterator()
for it.NextTo(seek) {
@ -532,20 +532,20 @@ func TestListIteratorNextTo(t *testing.T) {
// NextTo (found)
{
list := New()
list := New[string]()
list.Add("aa", "bb", "cc")
it := list.Iterator()
it.Begin()
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 2 || value.(string) != "cc" {
if index, value := it.Index(), it.Value(); index != 2 || value != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
@ -556,13 +556,13 @@ func TestListIteratorNextTo(t *testing.T) {
func TestListIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// PrevTo (empty)
{
list := New()
list := New[string]()
it := list.Iterator()
it.End()
for it.PrevTo(seek) {
@ -572,7 +572,7 @@ func TestListIteratorPrevTo(t *testing.T) {
// PrevTo (not found)
{
list := New()
list := New[string]()
list.Add("xx", "yy")
it := list.Iterator()
it.End()
@ -583,20 +583,20 @@ func TestListIteratorPrevTo(t *testing.T) {
// PrevTo (found)
{
list := New()
list := New[string]()
list.Add("aa", "bb", "cc")
it := list.Iterator()
it.End()
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 0 || value.(string) != "aa" {
if index, value := it.Index(), it.Value(); index != 0 || value != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
@ -606,12 +606,12 @@ func TestListIteratorPrevTo(t *testing.T) {
}
func TestListSerialization(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
var err error
assert := func() {
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
if actualValue, expectedValue := list.Values(), []string{"a", "b", "c"}; !slices.Equal(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, expectedValue := list.Size(), 3; actualValue != expectedValue {
@ -630,26 +630,27 @@ func TestListSerialization(t *testing.T) {
err = list.FromJSON(bytes)
assert()
bytes, err = json.Marshal([]interface{}{"a", "b", "c", list})
bytes, err = json.Marshal([]any{"a", "b", "c", list})
if err != nil {
t.Errorf("Got error %v", err)
}
err = json.Unmarshal([]byte(`[1,2,3]`), &list)
err = json.Unmarshal([]byte(`["a","b","c"]`), &list)
if err != nil {
t.Errorf("Got error %v", err)
}
assert()
}
func TestListString(t *testing.T) {
c := New()
c := New[int]()
c.Add(1)
if !strings.HasPrefix(c.String(), "ArrayList") {
t.Errorf("String should start with container name")
}
}
func benchmarkGet(b *testing.B, list *List, size int) {
func benchmarkGet(b *testing.B, list *List[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
list.Get(n)
@ -657,7 +658,7 @@ func benchmarkGet(b *testing.B, list *List, size int) {
}
}
func benchmarkAdd(b *testing.B, list *List, size int) {
func benchmarkAdd(b *testing.B, list *List[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
list.Add(n)
@ -665,7 +666,7 @@ func benchmarkAdd(b *testing.B, list *List, size int) {
}
}
func benchmarkRemove(b *testing.B, list *List, size int) {
func benchmarkRemove(b *testing.B, list *List[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
list.Remove(n)
@ -676,7 +677,7 @@ func benchmarkRemove(b *testing.B, list *List, size int) {
func BenchmarkArrayListGet100(b *testing.B) {
b.StopTimer()
size := 100
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -687,7 +688,7 @@ func BenchmarkArrayListGet100(b *testing.B) {
func BenchmarkArrayListGet1000(b *testing.B) {
b.StopTimer()
size := 1000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -698,7 +699,7 @@ func BenchmarkArrayListGet1000(b *testing.B) {
func BenchmarkArrayListGet10000(b *testing.B) {
b.StopTimer()
size := 10000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -709,7 +710,7 @@ func BenchmarkArrayListGet10000(b *testing.B) {
func BenchmarkArrayListGet100000(b *testing.B) {
b.StopTimer()
size := 100000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -720,7 +721,7 @@ func BenchmarkArrayListGet100000(b *testing.B) {
func BenchmarkArrayListAdd100(b *testing.B) {
b.StopTimer()
size := 100
list := New()
list := New[int]()
b.StartTimer()
benchmarkAdd(b, list, size)
}
@ -728,7 +729,7 @@ func BenchmarkArrayListAdd100(b *testing.B) {
func BenchmarkArrayListAdd1000(b *testing.B) {
b.StopTimer()
size := 1000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -739,7 +740,7 @@ func BenchmarkArrayListAdd1000(b *testing.B) {
func BenchmarkArrayListAdd10000(b *testing.B) {
b.StopTimer()
size := 10000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -750,7 +751,7 @@ func BenchmarkArrayListAdd10000(b *testing.B) {
func BenchmarkArrayListAdd100000(b *testing.B) {
b.StopTimer()
size := 100000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -761,7 +762,7 @@ func BenchmarkArrayListAdd100000(b *testing.B) {
func BenchmarkArrayListRemove100(b *testing.B) {
b.StopTimer()
size := 100
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -772,7 +773,7 @@ func BenchmarkArrayListRemove100(b *testing.B) {
func BenchmarkArrayListRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -783,7 +784,7 @@ func BenchmarkArrayListRemove1000(b *testing.B) {
func BenchmarkArrayListRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -794,7 +795,7 @@ func BenchmarkArrayListRemove10000(b *testing.B) {
func BenchmarkArrayListRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}

@ -4,13 +4,13 @@
package arraylist
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Enumerable implementation
var _ containers.EnumerableWithIndex = (*List)(nil)
var _ containers.EnumerableWithIndex[int] = (*List[int])(nil)
// Each calls the given function once for each element, passing that element's index and value.
func (list *List) Each(f func(index int, value interface{})) {
func (list *List[T]) Each(f func(index int, value T)) {
iterator := list.Iterator()
for iterator.Next() {
f(iterator.Index(), iterator.Value())
@ -19,8 +19,8 @@ func (list *List) Each(f func(index int, value interface{})) {
// Map invokes the given function once for each element and returns a
// container containing the values returned by the given function.
func (list *List) Map(f func(index int, value interface{}) interface{}) *List {
newList := &List{}
func (list *List[T]) Map(f func(index int, value T) T) *List[T] {
newList := &List[T]{}
iterator := list.Iterator()
for iterator.Next() {
newList.Add(f(iterator.Index(), iterator.Value()))
@ -29,8 +29,8 @@ func (list *List) Map(f func(index int, value interface{}) interface{}) *List {
}
// Select returns a new container containing all elements for which the given function returns a true value.
func (list *List) Select(f func(index int, value interface{}) bool) *List {
newList := &List{}
func (list *List[T]) Select(f func(index int, value T) bool) *List[T] {
newList := &List[T]{}
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
@ -42,7 +42,7 @@ func (list *List) Select(f func(index int, value interface{}) bool) *List {
// Any passes each element of the collection to the given function and
// returns true if the function ever returns true for any element.
func (list *List) Any(f func(index int, value interface{}) bool) bool {
func (list *List[T]) Any(f func(index int, value T) bool) bool {
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
@ -54,7 +54,7 @@ func (list *List) Any(f func(index int, value interface{}) bool) bool {
// All passes each element of the collection to the given function and
// returns true if the function returns true for all elements.
func (list *List) All(f func(index int, value interface{}) bool) bool {
func (list *List[T]) All(f func(index int, value T) bool) bool {
iterator := list.Iterator()
for iterator.Next() {
if !f(iterator.Index(), iterator.Value()) {
@ -67,12 +67,13 @@ func (list *List) All(f func(index int, value interface{}) bool) bool {
// Find passes each element of the container to the given function and returns
// the first (index,value) for which the function is true or -1,nil otherwise
// if no element matches the criteria.
func (list *List) Find(f func(index int, value interface{}) bool) (int, interface{}) {
func (list *List[T]) Find(f func(index int, value T) bool) (int, T) {
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
return iterator.Index(), iterator.Value()
}
}
return -1, nil
var t T
return -1, t
}

@ -4,27 +4,27 @@
package arraylist
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Iterator implementation
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator holding the iterator's state
type Iterator struct {
list *List
type Iterator[T comparable] struct {
list *List[T]
index int
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (list *List) Iterator() Iterator {
return Iterator{list: list, index: -1}
func (list *List[T]) Iterator() *Iterator[T] {
return &Iterator[T]{list: list, index: -1}
}
// 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 index and value can be retrieved by Index() 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 {
func (iterator *Iterator[T]) Next() bool {
if iterator.index < iterator.list.size {
iterator.index++
}
@ -34,7 +34,7 @@ func (iterator *Iterator) Next() bool {
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Prev() bool {
func (iterator *Iterator[T]) Prev() bool {
if iterator.index >= 0 {
iterator.index--
}
@ -43,32 +43,32 @@ func (iterator *Iterator) Prev() bool {
// Value returns the current element's value.
// Does not modify the state of the iterator.
func (iterator *Iterator) Value() interface{} {
func (iterator *Iterator[T]) Value() T {
return iterator.list.elements[iterator.index]
}
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
func (iterator *Iterator[T]) Index() int {
return iterator.index
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
func (iterator *Iterator[T]) Begin() {
iterator.index = -1
}
// 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() {
func (iterator *Iterator[T]) End() {
iterator.index = iterator.list.size
}
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
func (iterator *Iterator[T]) First() bool {
iterator.Begin()
return iterator.Next()
}
@ -76,7 +76,7 @@ func (iterator *Iterator) First() bool {
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Last() bool {
func (iterator *Iterator[T]) Last() bool {
iterator.End()
return iterator.Prev()
}
@ -85,7 +85,7 @@ func (iterator *Iterator) Last() bool {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) NextTo(f func(index int, value T) bool) bool {
for iterator.Next() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
@ -99,7 +99,7 @@ func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) PrevTo(f func(index int, value T) bool) bool {
for iterator.Prev() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {

@ -6,20 +6,21 @@ package arraylist
import (
"encoding/json"
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*List)(nil)
var _ containers.JSONDeserializer = (*List)(nil)
var _ containers.JSONSerializer = (*List[int])(nil)
var _ containers.JSONDeserializer = (*List[int])(nil)
// ToJSON outputs the JSON representation of list's elements.
func (list *List) ToJSON() ([]byte, error) {
func (list *List[T]) ToJSON() ([]byte, error) {
return json.Marshal(list.elements[:list.size])
}
// FromJSON populates list's elements from the input JSON representation.
func (list *List) FromJSON(data []byte) error {
func (list *List[T]) FromJSON(data []byte) error {
err := json.Unmarshal(data, &list.elements)
if err == nil {
list.size = len(list.elements)
@ -28,11 +29,11 @@ func (list *List) FromJSON(data []byte) error {
}
// UnmarshalJSON @implements json.Unmarshaler
func (list *List) UnmarshalJSON(bytes []byte) error {
func (list *List[T]) UnmarshalJSON(bytes []byte) error {
return list.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (list *List) MarshalJSON() ([]byte, error) {
func (list *List[T]) MarshalJSON() ([]byte, error) {
return list.ToJSON()
}

@ -11,31 +11,32 @@ package doublylinkedlist
import (
"fmt"
"slices"
"strings"
"github.com/emirpasic/gods/lists"
"github.com/emirpasic/gods/utils"
"github.com/emirpasic/gods/v2/lists"
"github.com/emirpasic/gods/v2/utils"
)
// Assert List implementation
var _ lists.List = (*List)(nil)
var _ lists.List[any] = (*List[any])(nil)
// List holds the elements, where each element points to the next and previous element
type List struct {
first *element
last *element
type List[T comparable] struct {
first *element[T]
last *element[T]
size int
}
type element struct {
value interface{}
prev *element
next *element
type element[T comparable] struct {
value T
prev *element[T]
next *element[T]
}
// New instantiates a new list and adds the passed values, if any, to the list
func New(values ...interface{}) *List {
list := &List{}
func New[T comparable](values ...T) *List[T] {
list := &List[T]{}
if len(values) > 0 {
list.Add(values...)
}
@ -43,9 +44,9 @@ func New(values ...interface{}) *List {
}
// Add appends a value (one or more) at the end of the list (same as Append())
func (list *List) Add(values ...interface{}) {
func (list *List[T]) Add(values ...T) {
for _, value := range values {
newElement := &element{value: value, prev: list.last}
newElement := &element[T]{value: value, prev: list.last}
if list.size == 0 {
list.first = newElement
list.last = newElement
@ -58,15 +59,15 @@ func (list *List) Add(values ...interface{}) {
}
// Append appends a value (one or more) at the end of the list (same as Add())
func (list *List) Append(values ...interface{}) {
func (list *List[T]) Append(values ...T) {
list.Add(values...)
}
// Prepend prepends a values (or more)
func (list *List) Prepend(values ...interface{}) {
func (list *List[T]) Prepend(values ...T) {
// in reverse to keep passed order i.e. ["c","d"] -> Prepend(["a","b"]) -> ["a","b","c",d"]
for v := len(values) - 1; v >= 0; v-- {
newElement := &element{value: values[v], next: list.first}
newElement := &element[T]{value: values[v], next: list.first}
if list.size == 0 {
list.first = newElement
list.last = newElement
@ -80,10 +81,11 @@ func (list *List) Prepend(values ...interface{}) {
// Get returns the element at index.
// Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false.
func (list *List) Get(index int) (interface{}, bool) {
func (list *List[T]) Get(index int) (T, bool) {
if !list.withinRange(index) {
return nil, false
var t T
return t, false
}
// determine traveral direction, last to first or first to last
@ -100,7 +102,7 @@ func (list *List) Get(index int) (interface{}, bool) {
}
// Remove removes the element at the given index from the list.
func (list *List) Remove(index int) {
func (list *List[T]) Remove(index int) {
if !list.withinRange(index) {
return
@ -111,7 +113,7 @@ func (list *List) Remove(index int) {
return
}
var element *element
var element *element[T]
// determine traversal direction, last to first or first to last
if list.size-index < index {
element = list.last
@ -145,7 +147,7 @@ func (list *List) Remove(index int) {
// All values have to be present in the set for the method to return true.
// Performance time complexity of n^2.
// Returns true if no arguments are passed at all, i.e. set is always super-set of empty set.
func (list *List) Contains(values ...interface{}) bool {
func (list *List[T]) Contains(values ...T) bool {
if len(values) == 0 {
return true
@ -169,8 +171,8 @@ func (list *List) Contains(values ...interface{}) bool {
}
// Values returns all elements in the list.
func (list *List) Values() []interface{} {
values := make([]interface{}, list.size, list.size)
func (list *List[T]) Values() []T {
values := make([]T, list.size, list.size)
for e, element := 0, list.first; element != nil; e, element = e+1, element.next {
values[e] = element.value
}
@ -178,7 +180,7 @@ func (list *List) Values() []interface{} {
}
// IndexOf returns index of provided element
func (list *List) IndexOf(value interface{}) int {
func (list *List[T]) IndexOf(value T) int {
if list.size == 0 {
return -1
}
@ -191,31 +193,31 @@ func (list *List) IndexOf(value interface{}) int {
}
// Empty returns true if list does not contain any elements.
func (list *List) Empty() bool {
func (list *List[T]) Empty() bool {
return list.size == 0
}
// Size returns number of elements within the list.
func (list *List) Size() int {
func (list *List[T]) Size() int {
return list.size
}
// Clear removes all elements from the list.
func (list *List) Clear() {
func (list *List[T]) Clear() {
list.size = 0
list.first = nil
list.last = nil
}
// Sort sorts values (in-place) using.
func (list *List) Sort(comparator utils.Comparator) {
func (list *List[T]) Sort(comparator utils.Comparator[T]) {
if list.size < 2 {
return
}
values := list.Values()
utils.Sort(values, comparator)
slices.SortFunc(values, comparator)
list.Clear()
@ -224,9 +226,9 @@ func (list *List) Sort(comparator utils.Comparator) {
}
// Swap swaps values of two elements at the given indices.
func (list *List) Swap(i, j int) {
func (list *List[T]) Swap(i, j int) {
if list.withinRange(i) && list.withinRange(j) && i != j {
var element1, element2 *element
var element1, element2 *element[T]
for e, currentElement := 0, list.first; element1 == nil || element2 == nil; e, currentElement = e+1, currentElement.next {
switch e {
case i:
@ -242,7 +244,7 @@ func (list *List) Swap(i, j int) {
// Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right.
// Does not do anything if position is negative or bigger than list's size
// Note: position equal to list's size is valid, i.e. append.
func (list *List) Insert(index int, values ...interface{}) {
func (list *List[T]) Insert(index int, values ...T) {
if !list.withinRange(index) {
// Append
@ -252,8 +254,8 @@ func (list *List) Insert(index int, values ...interface{}) {
return
}
var beforeElement *element
var foundElement *element
var beforeElement *element[T]
var foundElement *element[T]
// determine traversal direction, last to first or first to last
if list.size-index < index {
foundElement = list.last
@ -271,7 +273,7 @@ func (list *List) Insert(index int, values ...interface{}) {
if foundElement == list.first {
oldNextElement := list.first
for i, value := range values {
newElement := &element{value: value}
newElement := &element[T]{value: value}
if i == 0 {
list.first = newElement
} else {
@ -285,7 +287,7 @@ func (list *List) Insert(index int, values ...interface{}) {
} else {
oldNextElement := beforeElement.next
for _, value := range values {
newElement := &element{value: value}
newElement := &element[T]{value: value}
newElement.prev = beforeElement
beforeElement.next = newElement
beforeElement = newElement
@ -300,7 +302,7 @@ func (list *List) Insert(index int, values ...interface{}) {
// Set value at specified index position
// Does not do anything if position is negative or bigger than list's size
// Note: position equal to list's size is valid, i.e. append.
func (list *List) Set(index int, value interface{}) {
func (list *List[T]) Set(index int, value T) {
if !list.withinRange(index) {
// Append
@ -310,7 +312,7 @@ func (list *List) Set(index int, value interface{}) {
return
}
var foundElement *element
var foundElement *element[T]
// determine traversal direction, last to first or first to last
if list.size-index < index {
foundElement = list.last
@ -329,7 +331,7 @@ func (list *List) Set(index int, value interface{}) {
}
// String returns a string representation of container
func (list *List) String() string {
func (list *List[T]) String() string {
str := "DoublyLinkedList\n"
values := []string{}
for element := list.first; element != nil; element = element.next {
@ -340,6 +342,6 @@ func (list *List) String() string {
}
// Check that the index is within bounds of the list
func (list *List) withinRange(index int) bool {
func (list *List[T]) withinRange(index int) bool {
return index >= 0 && index < list.size
}

@ -5,22 +5,21 @@
package doublylinkedlist
import (
"cmp"
"encoding/json"
"fmt"
"slices"
"strings"
"testing"
"github.com/emirpasic/gods/utils"
)
func TestListNew(t *testing.T) {
list1 := New()
list1 := New[int]()
if actualValue := list1.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
list2 := New(1, "b")
list2 := New[int](1, 2)
if actualValue := list2.Size(); actualValue != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
@ -30,17 +29,17 @@ func TestListNew(t *testing.T) {
t.Errorf("Got %v expected %v", actualValue, 1)
}
if actualValue, ok := list2.Get(1); actualValue != "b" || !ok {
t.Errorf("Got %v expected %v", actualValue, "b")
if actualValue, ok := list2.Get(1); actualValue != 2 || !ok {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if actualValue, ok := list2.Get(2); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
if actualValue, ok := list2.Get(2); actualValue != 0 || ok {
t.Errorf("Got %v expected %v", actualValue, 0)
}
}
func TestListAdd(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue := list.Empty(); actualValue != false {
@ -55,7 +54,7 @@ func TestListAdd(t *testing.T) {
}
func TestListAppendAndPrepend(t *testing.T) {
list := New()
list := New[string]()
list.Add("b")
list.Prepend("a")
list.Append("c")
@ -77,12 +76,12 @@ func TestListAppendAndPrepend(t *testing.T) {
}
func TestListRemove(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
list.Remove(2)
if actualValue, ok := list.Get(2); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
if actualValue, ok := list.Get(2); actualValue != "" || ok {
t.Errorf("Got %v expected %v", actualValue, "")
}
list.Remove(1)
list.Remove(0)
@ -96,7 +95,7 @@ func TestListRemove(t *testing.T) {
}
func TestListGet(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue, ok := list.Get(0); actualValue != "a" || !ok {
@ -108,8 +107,8 @@ func TestListGet(t *testing.T) {
if actualValue, ok := list.Get(2); actualValue != "c" || !ok {
t.Errorf("Got %v expected %v", actualValue, "c")
}
if actualValue, ok := list.Get(3); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
if actualValue, ok := list.Get(3); actualValue != "" || ok {
t.Errorf("Got %v expected %v", actualValue, "")
}
list.Remove(0)
if actualValue, ok := list.Get(0); actualValue != "b" || !ok {
@ -118,31 +117,31 @@ func TestListGet(t *testing.T) {
}
func TestListSwap(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
list.Swap(0, 1)
if actualValue, ok := list.Get(0); actualValue != "b" || !ok {
t.Errorf("Got %v expected %v", actualValue, "c")
t.Errorf("Got %v expected %v", actualValue, "b")
}
}
func TestListSort(t *testing.T) {
list := New()
list.Sort(utils.StringComparator)
list := New[string]()
list.Sort(cmp.Compare[string])
list.Add("e", "f", "g", "a", "b", "c", "d")
list.Sort(utils.StringComparator)
list.Sort(cmp.Compare[string])
for i := 1; i < list.Size(); i++ {
a, _ := list.Get(i - 1)
b, _ := list.Get(i)
if a.(string) > b.(string) {
if a > b {
t.Errorf("Not sorted! %s > %s", a, b)
}
}
}
func TestListClear(t *testing.T) {
list := New()
list := New[string]()
list.Add("e", "f", "g", "a", "b", "c", "d")
list.Clear()
if actualValue := list.Empty(); actualValue != true {
@ -154,12 +153,15 @@ func TestListClear(t *testing.T) {
}
func TestListContains(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue := list.Contains("a"); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
if actualValue := list.Contains(""); actualValue != false {
t.Errorf("Got %v expected %v", actualValue, false)
}
if actualValue := list.Contains("a", "b", "c"); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
@ -176,43 +178,16 @@ func TestListContains(t *testing.T) {
}
func TestListValues(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
if actualValue, expectedValue := list.Values(), []string{"a", "b", "c"}; !slices.Equal(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestListIndexOf(t *testing.T) {
list := New()
expectedIndex := -1
if index := list.IndexOf("a"); index != expectedIndex {
t.Errorf("Got %v expected %v", index, expectedIndex)
}
list.Add("a")
list.Add("b", "c")
expectedIndex = 0
if index := list.IndexOf("a"); index != expectedIndex {
t.Errorf("Got %v expected %v", index, expectedIndex)
}
expectedIndex = 1
if index := list.IndexOf("b"); index != expectedIndex {
t.Errorf("Got %v expected %v", index, expectedIndex)
}
expectedIndex = 2
if index := list.IndexOf("c"); index != expectedIndex {
t.Errorf("Got %v expected %v", index, expectedIndex)
}
}
func TestListInsert(t *testing.T) {
list := New()
list := New[string]()
list.Insert(0, "b", "c", "d")
list.Insert(0, "a")
list.Insert(10, "x") // ignore
@ -223,20 +198,20 @@ func TestListInsert(t *testing.T) {
if actualValue := list.Size(); actualValue != 5 {
t.Errorf("Got %v expected %v", actualValue, 5)
}
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s%s", list.Values()...), "abcdg"; actualValue != expectedValue {
if actualValue, expectedValue := strings.Join(list.Values(), ""), "abcdg"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
list.Insert(4, "e", "f") // last to first traversal
if actualValue := list.Size(); actualValue != 7 {
t.Errorf("Got %v expected %v", actualValue, 7)
}
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s%s%s%s", list.Values()...), "abcdefg"; actualValue != expectedValue {
if actualValue, expectedValue := strings.Join(list.Values(), ""), "abcdefg"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestListSet(t *testing.T) {
list := New()
list := New[string]()
list.Set(0, "a")
list.Set(1, "b")
if actualValue := list.Size(); actualValue != 2 {
@ -251,20 +226,15 @@ func TestListSet(t *testing.T) {
if actualValue := list.Size(); actualValue != 3 {
t.Errorf("Got %v expected %v", actualValue, 3)
}
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abbc"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
list.Set(2, "cc") // last to first traversal
list.Set(0, "aa") // first to last traversal
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "aabbcc"; actualValue != expectedValue {
if actualValue, expectedValue := list.Values(), []string{"a", "bb", "c"}; !slices.Equal(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestListEach(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
list.Each(func(index int, value interface{}) {
list.Each(func(index int, value string) {
switch index {
case 0:
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
@ -285,10 +255,10 @@ func TestListEach(t *testing.T) {
}
func TestListMap(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
mappedList := list.Map(func(index int, value interface{}) interface{} {
return "mapped: " + value.(string)
mappedList := list.Map(func(index int, value string) string {
return "mapped: " + value
})
if actualValue, _ := mappedList.Get(0); actualValue != "mapped: a" {
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
@ -305,10 +275,10 @@ func TestListMap(t *testing.T) {
}
func TestListSelect(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
selectedList := list.Select(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "b"
selectedList := list.Select(func(index int, value string) bool {
return value >= "a" && value <= "b"
})
if actualValue, _ := selectedList.Get(0); actualValue != "a" {
t.Errorf("Got %v expected %v", actualValue, "value: a")
@ -322,60 +292,60 @@ func TestListSelect(t *testing.T) {
}
func TestListAny(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
any := list.Any(func(index int, value interface{}) bool {
return value.(string) == "c"
any := list.Any(func(index int, value string) bool {
return value == "c"
})
if any != true {
t.Errorf("Got %v expected %v", any, true)
}
any = list.Any(func(index int, value interface{}) bool {
return value.(string) == "x"
any = list.Any(func(index int, value string) bool {
return value == "x"
})
if any != false {
t.Errorf("Got %v expected %v", any, false)
}
}
func TestListAll(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
all := list.All(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "c"
all := list.All(func(index int, value string) bool {
return value >= "a" && value <= "c"
})
if all != true {
t.Errorf("Got %v expected %v", all, true)
}
all = list.All(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "b"
all = list.All(func(index int, value string) bool {
return value >= "a" && value <= "b"
})
if all != false {
t.Errorf("Got %v expected %v", all, false)
}
}
func TestListFind(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
foundIndex, foundValue := list.Find(func(index int, value interface{}) bool {
return value.(string) == "c"
foundIndex, foundValue := list.Find(func(index int, value string) bool {
return value == "c"
})
if foundValue != "c" || foundIndex != 2 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, "c", 2)
}
foundIndex, foundValue = list.Find(func(index int, value interface{}) bool {
return value.(string) == "x"
foundIndex, foundValue = list.Find(func(index int, value string) bool {
return value == "x"
})
if foundValue != nil || foundIndex != -1 {
if foundValue != "" || foundIndex != -1 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, nil, nil)
}
}
func TestListChaining(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
chainedList := list.Select(func(index int, value interface{}) bool {
return value.(string) > "a"
}).Map(func(index int, value interface{}) interface{} {
return value.(string) + value.(string)
chainedList := list.Select(func(index int, value string) bool {
return value > "a"
}).Map(func(index int, value string) string {
return value + value
})
if chainedList.Size() != 2 {
t.Errorf("Got %v expected %v", chainedList.Size(), 2)
@ -389,7 +359,7 @@ func TestListChaining(t *testing.T) {
}
func TestListIteratorNextOnEmpty(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
for it.Next() {
t.Errorf("Shouldn't iterate on empty list")
@ -397,7 +367,7 @@ func TestListIteratorNextOnEmpty(t *testing.T) {
}
func TestListIteratorNext(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
it := list.Iterator()
count := 0
@ -428,7 +398,7 @@ func TestListIteratorNext(t *testing.T) {
}
func TestListIteratorPrevOnEmpty(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
for it.Prev() {
t.Errorf("Shouldn't iterate on empty list")
@ -436,7 +406,7 @@ func TestListIteratorPrevOnEmpty(t *testing.T) {
}
func TestListIteratorPrev(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
it := list.Iterator()
for it.Next() {
@ -469,7 +439,7 @@ func TestListIteratorPrev(t *testing.T) {
}
func TestListIteratorBegin(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
it.Begin()
list.Add("a", "b", "c")
@ -483,7 +453,7 @@ func TestListIteratorBegin(t *testing.T) {
}
func TestListIteratorEnd(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
if index := it.Index(); index != -1 {
@ -508,7 +478,7 @@ func TestListIteratorEnd(t *testing.T) {
}
func TestListIteratorFirst(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -523,7 +493,7 @@ func TestListIteratorFirst(t *testing.T) {
}
func TestListIteratorLast(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -539,13 +509,13 @@ func TestListIteratorLast(t *testing.T) {
func TestListIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// NextTo (empty)
{
list := New()
list := New[string]()
it := list.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
@ -554,7 +524,7 @@ func TestListIteratorNextTo(t *testing.T) {
// NextTo (not found)
{
list := New()
list := New[string]()
list.Add("xx", "yy")
it := list.Iterator()
for it.NextTo(seek) {
@ -564,20 +534,20 @@ func TestListIteratorNextTo(t *testing.T) {
// NextTo (found)
{
list := New()
list := New[string]()
list.Add("aa", "bb", "cc")
it := list.Iterator()
it.Begin()
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 2 || value.(string) != "cc" {
if index, value := it.Index(), it.Value(); index != 2 || value != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
@ -588,13 +558,13 @@ func TestListIteratorNextTo(t *testing.T) {
func TestListIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// PrevTo (empty)
{
list := New()
list := New[string]()
it := list.Iterator()
it.End()
for it.PrevTo(seek) {
@ -604,7 +574,7 @@ func TestListIteratorPrevTo(t *testing.T) {
// PrevTo (not found)
{
list := New()
list := New[string]()
list.Add("xx", "yy")
it := list.Iterator()
it.End()
@ -615,20 +585,20 @@ func TestListIteratorPrevTo(t *testing.T) {
// PrevTo (found)
{
list := New()
list := New[string]()
list.Add("aa", "bb", "cc")
it := list.Iterator()
it.End()
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 0 || value.(string) != "aa" {
if index, value := it.Index(), it.Value(); index != 0 || value != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
@ -638,12 +608,12 @@ func TestListIteratorPrevTo(t *testing.T) {
}
func TestListSerialization(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
var err error
assert := func() {
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
if actualValue, expectedValue := list.Values(), []string{"a", "b", "c"}; !slices.Equal(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, expectedValue := list.Size(), 3; actualValue != expectedValue {
@ -662,26 +632,27 @@ func TestListSerialization(t *testing.T) {
err = list.FromJSON(bytes)
assert()
bytes, err = json.Marshal([]interface{}{"a", "b", "c", list})
bytes, err = json.Marshal([]any{"a", "b", "c", list})
if err != nil {
t.Errorf("Got error %v", err)
}
err = json.Unmarshal([]byte(`[1,2,3]`), &list)
err = json.Unmarshal([]byte(`["a","b","c"]`), &list)
if err != nil {
t.Errorf("Got error %v", err)
}
assert()
}
func TestListString(t *testing.T) {
c := New()
c := New[int]()
c.Add(1)
if !strings.HasPrefix(c.String(), "DoublyLinkedList") {
t.Errorf("String should start with container name")
}
}
func benchmarkGet(b *testing.B, list *List, size int) {
func benchmarkGet(b *testing.B, list *List[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
list.Get(n)
@ -689,7 +660,7 @@ func benchmarkGet(b *testing.B, list *List, size int) {
}
}
func benchmarkAdd(b *testing.B, list *List, size int) {
func benchmarkAdd(b *testing.B, list *List[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
list.Add(n)
@ -697,7 +668,7 @@ func benchmarkAdd(b *testing.B, list *List, size int) {
}
}
func benchmarkRemove(b *testing.B, list *List, size int) {
func benchmarkRemove(b *testing.B, list *List[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
list.Remove(n)
@ -708,7 +679,7 @@ func benchmarkRemove(b *testing.B, list *List, size int) {
func BenchmarkDoublyLinkedListGet100(b *testing.B) {
b.StopTimer()
size := 100
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -719,7 +690,7 @@ func BenchmarkDoublyLinkedListGet100(b *testing.B) {
func BenchmarkDoublyLinkedListGet1000(b *testing.B) {
b.StopTimer()
size := 1000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -730,7 +701,7 @@ func BenchmarkDoublyLinkedListGet1000(b *testing.B) {
func BenchmarkDoublyLinkedListGet10000(b *testing.B) {
b.StopTimer()
size := 10000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -741,7 +712,7 @@ func BenchmarkDoublyLinkedListGet10000(b *testing.B) {
func BenchmarkDoublyLinkedListGet100000(b *testing.B) {
b.StopTimer()
size := 100000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -752,7 +723,7 @@ func BenchmarkDoublyLinkedListGet100000(b *testing.B) {
func BenchmarkDoublyLinkedListAdd100(b *testing.B) {
b.StopTimer()
size := 100
list := New()
list := New[int]()
b.StartTimer()
benchmarkAdd(b, list, size)
}
@ -760,7 +731,7 @@ func BenchmarkDoublyLinkedListAdd100(b *testing.B) {
func BenchmarkDoublyLinkedListAdd1000(b *testing.B) {
b.StopTimer()
size := 1000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -771,7 +742,7 @@ func BenchmarkDoublyLinkedListAdd1000(b *testing.B) {
func BenchmarkDoublyLinkedListAdd10000(b *testing.B) {
b.StopTimer()
size := 10000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -782,7 +753,7 @@ func BenchmarkDoublyLinkedListAdd10000(b *testing.B) {
func BenchmarkDoublyLinkedListAdd100000(b *testing.B) {
b.StopTimer()
size := 100000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -793,7 +764,7 @@ func BenchmarkDoublyLinkedListAdd100000(b *testing.B) {
func BenchmarkDoublyLinkedListRemove100(b *testing.B) {
b.StopTimer()
size := 100
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -804,7 +775,7 @@ func BenchmarkDoublyLinkedListRemove100(b *testing.B) {
func BenchmarkDoublyLinkedListRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -815,7 +786,7 @@ func BenchmarkDoublyLinkedListRemove1000(b *testing.B) {
func BenchmarkDoublyLinkedListRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -826,7 +797,7 @@ func BenchmarkDoublyLinkedListRemove10000(b *testing.B) {
func BenchmarkDoublyLinkedListRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}

@ -4,13 +4,13 @@
package doublylinkedlist
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Enumerable implementation
var _ containers.EnumerableWithIndex = (*List)(nil)
var _ containers.EnumerableWithIndex[int] = (*List[int])(nil)
// Each calls the given function once for each element, passing that element's index and value.
func (list *List) Each(f func(index int, value interface{})) {
func (list *List[T]) Each(f func(index int, value T)) {
iterator := list.Iterator()
for iterator.Next() {
f(iterator.Index(), iterator.Value())
@ -19,8 +19,8 @@ func (list *List) Each(f func(index int, value interface{})) {
// Map invokes the given function once for each element and returns a
// container containing the values returned by the given function.
func (list *List) Map(f func(index int, value interface{}) interface{}) *List {
newList := &List{}
func (list *List[T]) Map(f func(index int, value T) T) *List[T] {
newList := &List[T]{}
iterator := list.Iterator()
for iterator.Next() {
newList.Add(f(iterator.Index(), iterator.Value()))
@ -29,8 +29,8 @@ func (list *List) Map(f func(index int, value interface{}) interface{}) *List {
}
// Select returns a new container containing all elements for which the given function returns a true value.
func (list *List) Select(f func(index int, value interface{}) bool) *List {
newList := &List{}
func (list *List[T]) Select(f func(index int, value T) bool) *List[T] {
newList := &List[T]{}
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
@ -42,7 +42,7 @@ func (list *List) Select(f func(index int, value interface{}) bool) *List {
// Any passes each element of the container to the given function and
// returns true if the function ever returns true for any element.
func (list *List) Any(f func(index int, value interface{}) bool) bool {
func (list *List[T]) Any(f func(index int, value T) bool) bool {
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
@ -54,7 +54,7 @@ func (list *List) Any(f func(index int, value interface{}) bool) bool {
// All passes each element of the container to the given function and
// returns true if the function returns true for all elements.
func (list *List) All(f func(index int, value interface{}) bool) bool {
func (list *List[T]) All(f func(index int, value T) bool) bool {
iterator := list.Iterator()
for iterator.Next() {
if !f(iterator.Index(), iterator.Value()) {
@ -67,12 +67,13 @@ func (list *List) All(f func(index int, value interface{}) bool) bool {
// Find passes each element of the container to the given function and returns
// the first (index,value) for which the function is true or -1,nil otherwise
// if no element matches the criteria.
func (list *List) Find(f func(index int, value interface{}) bool) (index int, value interface{}) {
func (list *List[T]) Find(f func(index int, value T) bool) (index int, value T) {
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
return iterator.Index(), iterator.Value()
}
}
return -1, nil
var t T
return -1, t
}

@ -4,28 +4,28 @@
package doublylinkedlist
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Iterator implementation
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator holding the iterator's state
type Iterator struct {
list *List
type Iterator[T comparable] struct {
list *List[T]
index int
element *element
element *element[T]
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (list *List) Iterator() Iterator {
return Iterator{list: list, index: -1, element: nil}
func (list *List[T]) Iterator() Iterator[T] {
return Iterator[T]{list: list, index: -1, element: nil}
}
// 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 index and value can be retrieved by Index() 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 {
func (iterator *Iterator[T]) Next() bool {
if iterator.index < iterator.list.size {
iterator.index++
}
@ -44,7 +44,7 @@ func (iterator *Iterator) Next() bool {
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Prev() bool {
func (iterator *Iterator[T]) Prev() bool {
if iterator.index >= 0 {
iterator.index--
}
@ -62,26 +62,26 @@ func (iterator *Iterator) Prev() bool {
// Value returns the current element's value.
// Does not modify the state of the iterator.
func (iterator *Iterator) Value() interface{} {
func (iterator *Iterator[T]) Value() T {
return iterator.element.value
}
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
func (iterator *Iterator[T]) Index() int {
return iterator.index
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
func (iterator *Iterator[T]) Begin() {
iterator.index = -1
iterator.element = nil
}
// 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() {
func (iterator *Iterator[T]) End() {
iterator.index = iterator.list.size
iterator.element = iterator.list.last
}
@ -89,7 +89,7 @@ func (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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
func (iterator *Iterator[T]) First() bool {
iterator.Begin()
return iterator.Next()
}
@ -97,7 +97,7 @@ func (iterator *Iterator) First() bool {
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Last() bool {
func (iterator *Iterator[T]) Last() bool {
iterator.End()
return iterator.Prev()
}
@ -106,7 +106,7 @@ func (iterator *Iterator) Last() bool {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) NextTo(f func(index int, value T) bool) bool {
for iterator.Next() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
@ -120,7 +120,7 @@ func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) PrevTo(f func(index int, value T) bool) bool {
for iterator.Prev() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {

@ -6,21 +6,22 @@ package doublylinkedlist
import (
"encoding/json"
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*List)(nil)
var _ containers.JSONDeserializer = (*List)(nil)
var _ containers.JSONSerializer = (*List[int])(nil)
var _ containers.JSONDeserializer = (*List[int])(nil)
// ToJSON outputs the JSON representation of list's elements.
func (list *List) ToJSON() ([]byte, error) {
func (list *List[T]) ToJSON() ([]byte, error) {
return json.Marshal(list.Values())
}
// FromJSON populates list's elements from the input JSON representation.
func (list *List) FromJSON(data []byte) error {
elements := []interface{}{}
func (list *List[T]) FromJSON(data []byte) error {
var elements []T
err := json.Unmarshal(data, &elements)
if err == nil {
list.Clear()
@ -30,11 +31,11 @@ func (list *List) FromJSON(data []byte) error {
}
// UnmarshalJSON @implements json.Unmarshaler
func (list *List) UnmarshalJSON(bytes []byte) error {
func (list *List[T]) UnmarshalJSON(bytes []byte) error {
return list.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (list *List) MarshalJSON() ([]byte, error) {
func (list *List[T]) MarshalJSON() ([]byte, error) {
return list.ToJSON()
}

@ -10,22 +10,22 @@
package lists
import (
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/utils"
"github.com/emirpasic/gods/v2/containers"
"github.com/emirpasic/gods/v2/utils"
)
// List interface that all lists implement
type List interface {
Get(index int) (interface{}, bool)
type List[T comparable] interface {
Get(index int) (T, bool)
Remove(index int)
Add(values ...interface{})
Contains(values ...interface{}) bool
Sort(comparator utils.Comparator)
Add(values ...T)
Contains(values ...T) bool
Sort(comparator utils.Comparator[T])
Swap(index1, index2 int)
Insert(index int, values ...interface{})
Set(index int, value interface{})
Insert(index int, values ...T)
Set(index int, value T)
containers.Container
containers.Container[T]
// Empty() bool
// Size() int
// Clear()

@ -4,13 +4,13 @@
package singlylinkedlist
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Enumerable implementation
var _ containers.EnumerableWithIndex = (*List)(nil)
var _ containers.EnumerableWithIndex[int] = (*List[int])(nil)
// Each calls the given function once for each element, passing that element's index and value.
func (list *List) Each(f func(index int, value interface{})) {
func (list *List[T]) Each(f func(index int, value T)) {
iterator := list.Iterator()
for iterator.Next() {
f(iterator.Index(), iterator.Value())
@ -19,8 +19,8 @@ func (list *List) Each(f func(index int, value interface{})) {
// Map invokes the given function once for each element and returns a
// container containing the values returned by the given function.
func (list *List) Map(f func(index int, value interface{}) interface{}) *List {
newList := &List{}
func (list *List[T]) Map(f func(index int, value T) T) *List[T] {
newList := &List[T]{}
iterator := list.Iterator()
for iterator.Next() {
newList.Add(f(iterator.Index(), iterator.Value()))
@ -29,8 +29,8 @@ func (list *List) Map(f func(index int, value interface{}) interface{}) *List {
}
// Select returns a new container containing all elements for which the given function returns a true value.
func (list *List) Select(f func(index int, value interface{}) bool) *List {
newList := &List{}
func (list *List[T]) Select(f func(index int, value T) bool) *List[T] {
newList := &List[T]{}
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
@ -42,7 +42,7 @@ func (list *List) Select(f func(index int, value interface{}) bool) *List {
// Any passes each element of the container to the given function and
// returns true if the function ever returns true for any element.
func (list *List) Any(f func(index int, value interface{}) bool) bool {
func (list *List[T]) Any(f func(index int, value T) bool) bool {
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
@ -54,7 +54,7 @@ func (list *List) Any(f func(index int, value interface{}) bool) bool {
// All passes each element of the container to the given function and
// returns true if the function returns true for all elements.
func (list *List) All(f func(index int, value interface{}) bool) bool {
func (list *List[T]) All(f func(index int, value T) bool) bool {
iterator := list.Iterator()
for iterator.Next() {
if !f(iterator.Index(), iterator.Value()) {
@ -67,12 +67,12 @@ func (list *List) All(f func(index int, value interface{}) bool) bool {
// Find passes each element of the container to the given function and returns
// the first (index,value) for which the function is true or -1,nil otherwise
// if no element matches the criteria.
func (list *List) Find(f func(index int, value interface{}) bool) (index int, value interface{}) {
func (list *List[T]) Find(f func(index int, value T) bool) (index int, value T) {
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
return iterator.Index(), iterator.Value()
}
}
return -1, nil
return -1, value
}

@ -4,28 +4,28 @@
package singlylinkedlist
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Iterator implementation
var _ containers.IteratorWithIndex = (*Iterator)(nil)
var _ containers.IteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator holding the iterator's state
type Iterator struct {
list *List
type Iterator[T comparable] struct {
list *List[T]
index int
element *element
element *element[T]
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (list *List) Iterator() Iterator {
return Iterator{list: list, index: -1, element: nil}
func (list *List[T]) Iterator() *Iterator[T] {
return &Iterator[T]{list: list, index: -1, element: nil}
}
// 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 index and value can be retrieved by Index() 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 {
func (iterator *Iterator[T]) Next() bool {
if iterator.index < iterator.list.size {
iterator.index++
}
@ -43,19 +43,19 @@ func (iterator *Iterator) Next() bool {
// Value returns the current element's value.
// Does not modify the state of the iterator.
func (iterator *Iterator) Value() interface{} {
func (iterator *Iterator[T]) Value() T {
return iterator.element.value
}
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
func (iterator *Iterator[T]) Index() int {
return iterator.index
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
func (iterator *Iterator[T]) Begin() {
iterator.index = -1
iterator.element = nil
}
@ -63,7 +63,7 @@ func (iterator *Iterator) Begin() {
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
func (iterator *Iterator[T]) First() bool {
iterator.Begin()
return iterator.Next()
}
@ -72,7 +72,7 @@ func (iterator *Iterator) First() bool {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) NextTo(f func(index int, value T) bool) bool {
for iterator.Next() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {

@ -6,21 +6,22 @@ package singlylinkedlist
import (
"encoding/json"
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*List)(nil)
var _ containers.JSONDeserializer = (*List)(nil)
var _ containers.JSONSerializer = (*List[int])(nil)
var _ containers.JSONDeserializer = (*List[int])(nil)
// ToJSON outputs the JSON representation of list's elements.
func (list *List) ToJSON() ([]byte, error) {
func (list *List[T]) ToJSON() ([]byte, error) {
return json.Marshal(list.Values())
}
// FromJSON populates list's elements from the input JSON representation.
func (list *List) FromJSON(data []byte) error {
elements := []interface{}{}
func (list *List[T]) FromJSON(data []byte) error {
var elements []T
err := json.Unmarshal(data, &elements)
if err == nil {
list.Clear()
@ -30,11 +31,11 @@ func (list *List) FromJSON(data []byte) error {
}
// UnmarshalJSON @implements json.Unmarshaler
func (list *List) UnmarshalJSON(bytes []byte) error {
func (list *List[T]) UnmarshalJSON(bytes []byte) error {
return list.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (list *List) MarshalJSON() ([]byte, error) {
func (list *List[T]) MarshalJSON() ([]byte, error) {
return list.ToJSON()
}

@ -11,30 +11,31 @@ package singlylinkedlist
import (
"fmt"
"slices"
"strings"
"github.com/emirpasic/gods/lists"
"github.com/emirpasic/gods/utils"
"github.com/emirpasic/gods/v2/lists"
"github.com/emirpasic/gods/v2/utils"
)
// Assert List implementation
var _ lists.List = (*List)(nil)
var _ lists.List[int] = (*List[int])(nil)
// List holds the elements, where each element points to the next element
type List struct {
first *element
last *element
type List[T comparable] struct {
first *element[T]
last *element[T]
size int
}
type element struct {
value interface{}
next *element
type element[T comparable] struct {
value T
next *element[T]
}
// New instantiates a new list and adds the passed values, if any, to the list
func New(values ...interface{}) *List {
list := &List{}
func New[T comparable](values ...T) *List[T] {
list := &List[T]{}
if len(values) > 0 {
list.Add(values...)
}
@ -42,9 +43,9 @@ func New(values ...interface{}) *List {
}
// Add appends a value (one or more) at the end of the list (same as Append())
func (list *List) Add(values ...interface{}) {
func (list *List[T]) Add(values ...T) {
for _, value := range values {
newElement := &element{value: value}
newElement := &element[T]{value: value}
if list.size == 0 {
list.first = newElement
list.last = newElement
@ -57,15 +58,15 @@ func (list *List) Add(values ...interface{}) {
}
// Append appends a value (one or more) at the end of the list (same as Add())
func (list *List) Append(values ...interface{}) {
func (list *List[T]) Append(values ...T) {
list.Add(values...)
}
// Prepend prepends a values (or more)
func (list *List) Prepend(values ...interface{}) {
func (list *List[T]) Prepend(values ...T) {
// in reverse to keep passed order i.e. ["c","d"] -> Prepend(["a","b"]) -> ["a","b","c",d"]
for v := len(values) - 1; v >= 0; v-- {
newElement := &element{value: values[v], next: list.first}
newElement := &element[T]{value: values[v], next: list.first}
list.first = newElement
if list.size == 0 {
list.last = newElement
@ -76,10 +77,11 @@ func (list *List) Prepend(values ...interface{}) {
// Get returns the element at index.
// Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false.
func (list *List) Get(index int) (interface{}, bool) {
func (list *List[T]) Get(index int) (T, bool) {
if !list.withinRange(index) {
return nil, false
var t T
return t, false
}
element := list.first
@ -90,7 +92,7 @@ func (list *List) Get(index int) (interface{}, bool) {
}
// Remove removes the element at the given index from the list.
func (list *List) Remove(index int) {
func (list *List[T]) Remove(index int) {
if !list.withinRange(index) {
return
@ -101,7 +103,7 @@ func (list *List) Remove(index int) {
return
}
var beforeElement *element
var beforeElement *element[T]
element := list.first
for e := 0; e != index; e, element = e+1, element.next {
beforeElement = element
@ -126,7 +128,7 @@ func (list *List) Remove(index int) {
// All values have to be present in the set for the method to return true.
// Performance time complexity of n^2.
// Returns true if no arguments are passed at all, i.e. set is always super-set of empty set.
func (list *List) Contains(values ...interface{}) bool {
func (list *List[T]) Contains(values ...T) bool {
if len(values) == 0 {
return true
@ -150,16 +152,16 @@ func (list *List) Contains(values ...interface{}) bool {
}
// Values returns all elements in the list.
func (list *List) Values() []interface{} {
values := make([]interface{}, list.size, list.size)
func (list *List[T]) Values() []T {
values := make([]T, list.size, list.size)
for e, element := 0, list.first; element != nil; e, element = e+1, element.next {
values[e] = element.value
}
return values
}
//IndexOf returns index of provided element
func (list *List) IndexOf(value interface{}) int {
// IndexOf returns index of provided element
func (list *List[T]) IndexOf(value T) int {
if list.size == 0 {
return -1
}
@ -172,31 +174,31 @@ func (list *List) IndexOf(value interface{}) int {
}
// Empty returns true if list does not contain any elements.
func (list *List) Empty() bool {
func (list *List[T]) Empty() bool {
return list.size == 0
}
// Size returns number of elements within the list.
func (list *List) Size() int {
func (list *List[T]) Size() int {
return list.size
}
// Clear removes all elements from the list.
func (list *List) Clear() {
func (list *List[T]) Clear() {
list.size = 0
list.first = nil
list.last = nil
}
// Sort sort values (in-place) using.
func (list *List) Sort(comparator utils.Comparator) {
func (list *List[T]) Sort(comparator utils.Comparator[T]) {
if list.size < 2 {
return
}
values := list.Values()
utils.Sort(values, comparator)
slices.SortFunc(values, comparator)
list.Clear()
@ -205,9 +207,9 @@ func (list *List) Sort(comparator utils.Comparator) {
}
// Swap swaps values of two elements at the given indices.
func (list *List) Swap(i, j int) {
func (list *List[T]) Swap(i, j int) {
if list.withinRange(i) && list.withinRange(j) && i != j {
var element1, element2 *element
var element1, element2 *element[T]
for e, currentElement := 0, list.first; element1 == nil || element2 == nil; e, currentElement = e+1, currentElement.next {
switch e {
case i:
@ -223,7 +225,7 @@ func (list *List) Swap(i, j int) {
// Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right.
// Does not do anything if position is negative or bigger than list's size
// Note: position equal to list's size is valid, i.e. append.
func (list *List) Insert(index int, values ...interface{}) {
func (list *List[T]) Insert(index int, values ...T) {
if !list.withinRange(index) {
// Append
@ -235,7 +237,7 @@ func (list *List) Insert(index int, values ...interface{}) {
list.size += len(values)
var beforeElement *element
var beforeElement *element[T]
foundElement := list.first
for e := 0; e != index; e, foundElement = e+1, foundElement.next {
beforeElement = foundElement
@ -244,7 +246,7 @@ func (list *List) Insert(index int, values ...interface{}) {
if foundElement == list.first {
oldNextElement := list.first
for i, value := range values {
newElement := &element{value: value}
newElement := &element[T]{value: value}
if i == 0 {
list.first = newElement
} else {
@ -256,7 +258,7 @@ func (list *List) Insert(index int, values ...interface{}) {
} else {
oldNextElement := beforeElement.next
for _, value := range values {
newElement := &element{value: value}
newElement := &element[T]{value: value}
beforeElement.next = newElement
beforeElement = newElement
}
@ -267,7 +269,7 @@ func (list *List) Insert(index int, values ...interface{}) {
// Set value at specified index
// Does not do anything if position is negative or bigger than list's size
// Note: position equal to list's size is valid, i.e. append.
func (list *List) Set(index int, value interface{}) {
func (list *List[T]) Set(index int, value T) {
if !list.withinRange(index) {
// Append
@ -285,7 +287,7 @@ func (list *List) Set(index int, value interface{}) {
}
// String returns a string representation of container
func (list *List) String() string {
func (list *List[T]) String() string {
str := "SinglyLinkedList\n"
values := []string{}
for element := list.first; element != nil; element = element.next {
@ -296,6 +298,6 @@ func (list *List) String() string {
}
// Check that the index is within bounds of the list
func (list *List) withinRange(index int) bool {
func (list *List[T]) withinRange(index int) bool {
return index >= 0 && index < list.size
}

@ -5,22 +5,21 @@
package singlylinkedlist
import (
"cmp"
"encoding/json"
"fmt"
"slices"
"strings"
"testing"
"github.com/emirpasic/gods/utils"
)
func TestListNew(t *testing.T) {
list1 := New()
list1 := New[int]()
if actualValue := list1.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
list2 := New(1, "b")
list2 := New[int](1, 2)
if actualValue := list2.Size(); actualValue != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
@ -30,17 +29,17 @@ func TestListNew(t *testing.T) {
t.Errorf("Got %v expected %v", actualValue, 1)
}
if actualValue, ok := list2.Get(1); actualValue != "b" || !ok {
t.Errorf("Got %v expected %v", actualValue, "b")
if actualValue, ok := list2.Get(1); actualValue != 2 || !ok {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if actualValue, ok := list2.Get(2); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
if actualValue, ok := list2.Get(2); actualValue != 0 || ok {
t.Errorf("Got %v expected %v", actualValue, 0)
}
}
func TestListAdd(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue := list.Empty(); actualValue != false {
@ -55,7 +54,7 @@ func TestListAdd(t *testing.T) {
}
func TestListAppendAndPrepend(t *testing.T) {
list := New()
list := New[string]()
list.Add("b")
list.Prepend("a")
list.Append("c")
@ -77,12 +76,12 @@ func TestListAppendAndPrepend(t *testing.T) {
}
func TestListRemove(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
list.Remove(2)
if actualValue, ok := list.Get(2); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
if actualValue, ok := list.Get(2); actualValue != "" || ok {
t.Errorf("Got %v expected %v", actualValue, "")
}
list.Remove(1)
list.Remove(0)
@ -96,7 +95,7 @@ func TestListRemove(t *testing.T) {
}
func TestListGet(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue, ok := list.Get(0); actualValue != "a" || !ok {
@ -108,8 +107,8 @@ func TestListGet(t *testing.T) {
if actualValue, ok := list.Get(2); actualValue != "c" || !ok {
t.Errorf("Got %v expected %v", actualValue, "c")
}
if actualValue, ok := list.Get(3); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
if actualValue, ok := list.Get(3); actualValue != "" || ok {
t.Errorf("Got %v expected %v", actualValue, "")
}
list.Remove(0)
if actualValue, ok := list.Get(0); actualValue != "b" || !ok {
@ -118,31 +117,31 @@ func TestListGet(t *testing.T) {
}
func TestListSwap(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
list.Swap(0, 1)
if actualValue, ok := list.Get(0); actualValue != "b" || !ok {
t.Errorf("Got %v expected %v", actualValue, "c")
t.Errorf("Got %v expected %v", actualValue, "b")
}
}
func TestListSort(t *testing.T) {
list := New()
list.Sort(utils.StringComparator)
list := New[string]()
list.Sort(cmp.Compare[string])
list.Add("e", "f", "g", "a", "b", "c", "d")
list.Sort(utils.StringComparator)
list.Sort(cmp.Compare[string])
for i := 1; i < list.Size(); i++ {
a, _ := list.Get(i - 1)
b, _ := list.Get(i)
if a.(string) > b.(string) {
if a > b {
t.Errorf("Not sorted! %s > %s", a, b)
}
}
}
func TestListClear(t *testing.T) {
list := New()
list := New[string]()
list.Add("e", "f", "g", "a", "b", "c", "d")
list.Clear()
if actualValue := list.Empty(); actualValue != true {
@ -154,12 +153,15 @@ func TestListClear(t *testing.T) {
}
func TestListContains(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue := list.Contains("a"); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
if actualValue := list.Contains(""); actualValue != false {
t.Errorf("Got %v expected %v", actualValue, false)
}
if actualValue := list.Contains("a", "b", "c"); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
@ -176,16 +178,16 @@ func TestListContains(t *testing.T) {
}
func TestListValues(t *testing.T) {
list := New()
list := New[string]()
list.Add("a")
list.Add("b", "c")
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
if actualValue, expectedValue := list.Values(), []string{"a", "b", "c"}; !slices.Equal(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestListIndexOf(t *testing.T) {
list := New()
list := New[string]()
expectedIndex := -1
if index := list.IndexOf("a"); index != expectedIndex {
@ -212,7 +214,7 @@ func TestListIndexOf(t *testing.T) {
}
func TestListInsert(t *testing.T) {
list := New()
list := New[string]()
list.Insert(0, "b", "c")
list.Insert(0, "a")
list.Insert(10, "x") // ignore
@ -223,13 +225,13 @@ func TestListInsert(t *testing.T) {
if actualValue := list.Size(); actualValue != 4 {
t.Errorf("Got %v expected %v", actualValue, 4)
}
if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s", list.Values()...), "abcd"; actualValue != expectedValue {
if actualValue, expectedValue := strings.Join(list.Values(), ""), "abcd"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestListSet(t *testing.T) {
list := New()
list := New[string]()
list.Set(0, "a")
list.Set(1, "b")
if actualValue := list.Size(); actualValue != 2 {
@ -244,15 +246,15 @@ func TestListSet(t *testing.T) {
if actualValue := list.Size(); actualValue != 3 {
t.Errorf("Got %v expected %v", actualValue, 3)
}
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abbc"; actualValue != expectedValue {
if actualValue, expectedValue := list.Values(), []string{"a", "bb", "c"}; !slices.Equal(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestListEach(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
list.Each(func(index int, value interface{}) {
list.Each(func(index int, value string) {
switch index {
case 0:
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
@ -273,10 +275,10 @@ func TestListEach(t *testing.T) {
}
func TestListMap(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
mappedList := list.Map(func(index int, value interface{}) interface{} {
return "mapped: " + value.(string)
mappedList := list.Map(func(index int, value string) string {
return "mapped: " + value
})
if actualValue, _ := mappedList.Get(0); actualValue != "mapped: a" {
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
@ -293,10 +295,10 @@ func TestListMap(t *testing.T) {
}
func TestListSelect(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
selectedList := list.Select(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "b"
selectedList := list.Select(func(index int, value string) bool {
return value >= "a" && value <= "b"
})
if actualValue, _ := selectedList.Get(0); actualValue != "a" {
t.Errorf("Got %v expected %v", actualValue, "value: a")
@ -310,60 +312,60 @@ func TestListSelect(t *testing.T) {
}
func TestListAny(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
any := list.Any(func(index int, value interface{}) bool {
return value.(string) == "c"
any := list.Any(func(index int, value string) bool {
return value == "c"
})
if any != true {
t.Errorf("Got %v expected %v", any, true)
}
any = list.Any(func(index int, value interface{}) bool {
return value.(string) == "x"
any = list.Any(func(index int, value string) bool {
return value == "x"
})
if any != false {
t.Errorf("Got %v expected %v", any, false)
}
}
func TestListAll(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
all := list.All(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "c"
all := list.All(func(index int, value string) bool {
return value >= "a" && value <= "c"
})
if all != true {
t.Errorf("Got %v expected %v", all, true)
}
all = list.All(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "b"
all = list.All(func(index int, value string) bool {
return value >= "a" && value <= "b"
})
if all != false {
t.Errorf("Got %v expected %v", all, false)
}
}
func TestListFind(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
foundIndex, foundValue := list.Find(func(index int, value interface{}) bool {
return value.(string) == "c"
foundIndex, foundValue := list.Find(func(index int, value string) bool {
return value == "c"
})
if foundValue != "c" || foundIndex != 2 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, "c", 2)
}
foundIndex, foundValue = list.Find(func(index int, value interface{}) bool {
return value.(string) == "x"
foundIndex, foundValue = list.Find(func(index int, value string) bool {
return value == "x"
})
if foundValue != nil || foundIndex != -1 {
if foundValue != "" || foundIndex != -1 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, nil, nil)
}
}
func TestListChaining(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
chainedList := list.Select(func(index int, value interface{}) bool {
return value.(string) > "a"
}).Map(func(index int, value interface{}) interface{} {
return value.(string) + value.(string)
chainedList := list.Select(func(index int, value string) bool {
return value > "a"
}).Map(func(index int, value string) string {
return value + value
})
if chainedList.Size() != 2 {
t.Errorf("Got %v expected %v", chainedList.Size(), 2)
@ -377,7 +379,7 @@ func TestListChaining(t *testing.T) {
}
func TestListIteratorNextOnEmpty(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
for it.Next() {
t.Errorf("Shouldn't iterate on empty list")
@ -385,7 +387,7 @@ func TestListIteratorNextOnEmpty(t *testing.T) {
}
func TestListIteratorNext(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
it := list.Iterator()
count := 0
@ -416,7 +418,7 @@ func TestListIteratorNext(t *testing.T) {
}
func TestListIteratorBegin(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
it.Begin()
list.Add("a", "b", "c")
@ -430,7 +432,7 @@ func TestListIteratorBegin(t *testing.T) {
}
func TestListIteratorFirst(t *testing.T) {
list := New()
list := New[string]()
it := list.Iterator()
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -446,13 +448,13 @@ func TestListIteratorFirst(t *testing.T) {
func TestListIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// NextTo (empty)
{
list := New()
list := New[string]()
it := list.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
@ -461,7 +463,7 @@ func TestListIteratorNextTo(t *testing.T) {
// NextTo (not found)
{
list := New()
list := New[string]()
list.Add("xx", "yy")
it := list.Iterator()
for it.NextTo(seek) {
@ -471,20 +473,20 @@ func TestListIteratorNextTo(t *testing.T) {
// NextTo (found)
{
list := New()
list := New[string]()
list.Add("aa", "bb", "cc")
it := list.Iterator()
it.Begin()
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 2 || value.(string) != "cc" {
if index, value := it.Index(), it.Value(); index != 2 || value != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
@ -494,12 +496,12 @@ func TestListIteratorNextTo(t *testing.T) {
}
func TestListSerialization(t *testing.T) {
list := New()
list := New[string]()
list.Add("a", "b", "c")
var err error
assert := func() {
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", list.Values()...), "abc"; actualValue != expectedValue {
if actualValue, expectedValue := list.Values(), []string{"a", "b", "c"}; !slices.Equal(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, expectedValue := list.Size(), 3; actualValue != expectedValue {
@ -518,26 +520,27 @@ func TestListSerialization(t *testing.T) {
err = list.FromJSON(bytes)
assert()
bytes, err = json.Marshal([]interface{}{"a", "b", "c", list})
bytes, err = json.Marshal([]any{"a", "b", "c", list})
if err != nil {
t.Errorf("Got error %v", err)
}
err = json.Unmarshal([]byte(`[1,2,3]`), &list)
err = json.Unmarshal([]byte(`["a","b","c"]`), &list)
if err != nil {
t.Errorf("Got error %v", err)
}
assert()
}
func TestListString(t *testing.T) {
c := New()
c := New[int]()
c.Add(1)
if !strings.HasPrefix(c.String(), "SinglyLinkedList") {
t.Errorf("String should start with container name")
}
}
func benchmarkGet(b *testing.B, list *List, size int) {
func benchmarkGet(b *testing.B, list *List[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
list.Get(n)
@ -545,7 +548,7 @@ func benchmarkGet(b *testing.B, list *List, size int) {
}
}
func benchmarkAdd(b *testing.B, list *List, size int) {
func benchmarkAdd(b *testing.B, list *List[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
list.Add(n)
@ -553,7 +556,7 @@ func benchmarkAdd(b *testing.B, list *List, size int) {
}
}
func benchmarkRemove(b *testing.B, list *List, size int) {
func benchmarkRemove(b *testing.B, list *List[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
list.Remove(n)
@ -564,7 +567,7 @@ func benchmarkRemove(b *testing.B, list *List, size int) {
func BenchmarkSinglyLinkedListGet100(b *testing.B) {
b.StopTimer()
size := 100
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -575,7 +578,7 @@ func BenchmarkSinglyLinkedListGet100(b *testing.B) {
func BenchmarkSinglyLinkedListGet1000(b *testing.B) {
b.StopTimer()
size := 1000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -586,7 +589,7 @@ func BenchmarkSinglyLinkedListGet1000(b *testing.B) {
func BenchmarkSinglyLinkedListGet10000(b *testing.B) {
b.StopTimer()
size := 10000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -597,7 +600,7 @@ func BenchmarkSinglyLinkedListGet10000(b *testing.B) {
func BenchmarkSinglyLinkedListGet100000(b *testing.B) {
b.StopTimer()
size := 100000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -608,7 +611,7 @@ func BenchmarkSinglyLinkedListGet100000(b *testing.B) {
func BenchmarkSinglyLinkedListAdd100(b *testing.B) {
b.StopTimer()
size := 100
list := New()
list := New[int]()
b.StartTimer()
benchmarkAdd(b, list, size)
}
@ -616,7 +619,7 @@ func BenchmarkSinglyLinkedListAdd100(b *testing.B) {
func BenchmarkSinglyLinkedListAdd1000(b *testing.B) {
b.StopTimer()
size := 1000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -627,7 +630,7 @@ func BenchmarkSinglyLinkedListAdd1000(b *testing.B) {
func BenchmarkSinglyLinkedListAdd10000(b *testing.B) {
b.StopTimer()
size := 10000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -638,7 +641,7 @@ func BenchmarkSinglyLinkedListAdd10000(b *testing.B) {
func BenchmarkSinglyLinkedListAdd100000(b *testing.B) {
b.StopTimer()
size := 100000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -649,7 +652,7 @@ func BenchmarkSinglyLinkedListAdd100000(b *testing.B) {
func BenchmarkSinglyLinkedListRemove100(b *testing.B) {
b.StopTimer()
size := 100
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -660,7 +663,7 @@ func BenchmarkSinglyLinkedListRemove100(b *testing.B) {
func BenchmarkSinglyLinkedListRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -671,7 +674,7 @@ func BenchmarkSinglyLinkedListRemove1000(b *testing.B) {
func BenchmarkSinglyLinkedListRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}
@ -682,7 +685,7 @@ func BenchmarkSinglyLinkedListRemove10000(b *testing.B) {
func BenchmarkSinglyLinkedListRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
list := New()
list := New[int]()
for n := 0; n < size; n++ {
list.Add(n)
}

@ -17,26 +17,27 @@ package hashbidimap
import (
"fmt"
"github.com/emirpasic/gods/maps"
"github.com/emirpasic/gods/maps/hashmap"
"github.com/emirpasic/gods/v2/maps"
"github.com/emirpasic/gods/v2/maps/hashmap"
)
// Assert Map implementation
var _ maps.BidiMap = (*Map)(nil)
var _ maps.BidiMap[string, int] = (*Map[string, int])(nil)
// Map holds the elements in two hashmaps.
type Map struct {
forwardMap hashmap.Map
inverseMap hashmap.Map
type Map[K, V comparable] struct {
forwardMap hashmap.Map[K, V]
inverseMap hashmap.Map[V, K]
}
// New instantiates a bidirectional map.
func New() *Map {
return &Map{*hashmap.New(), *hashmap.New()}
func New[K, V comparable]() *Map[K, V] {
return &Map[K, V]{*hashmap.New[K, V](), *hashmap.New[V, K]()}
}
// Put inserts element into the map.
func (m *Map) Put(key interface{}, value interface{}) {
func (m *Map[K, V]) Put(key K, value V) {
if valueByKey, ok := m.forwardMap.Get(key); ok {
m.inverseMap.Remove(valueByKey)
}
@ -49,18 +50,18 @@ func (m *Map) Put(key interface{}, value interface{}) {
// Get searches the element 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) {
func (m *Map[K, V]) Get(key K) (value V, found bool) {
return m.forwardMap.Get(key)
}
// GetKey searches the element in the map by value and returns its key or nil if value is not found in map.
// Second return parameter is true if value was found, otherwise false.
func (m *Map) GetKey(value interface{}) (key interface{}, found bool) {
func (m *Map[K, V]) GetKey(value V) (key K, found bool) {
return m.inverseMap.Get(value)
}
// Remove removes the element from the map by key.
func (m *Map) Remove(key interface{}) {
func (m *Map[K, V]) Remove(key K) {
if value, found := m.forwardMap.Get(key); found {
m.forwardMap.Remove(key)
m.inverseMap.Remove(value)
@ -68,33 +69,33 @@ func (m *Map) Remove(key interface{}) {
}
// Empty returns true if map does not contain any elements
func (m *Map) Empty() bool {
func (m *Map[K, V]) Empty() bool {
return m.Size() == 0
}
// Size returns number of elements in the map.
func (m *Map) Size() int {
func (m *Map[K, V]) Size() int {
return m.forwardMap.Size()
}
// Keys returns all keys (random order).
func (m *Map) Keys() []interface{} {
func (m *Map[K, V]) Keys() []K {
return m.forwardMap.Keys()
}
// Values returns all values (random order).
func (m *Map) Values() []interface{} {
func (m *Map[K, V]) Values() []V {
return m.inverseMap.Keys()
}
// Clear removes all elements from the map.
func (m *Map) Clear() {
func (m *Map[K, V]) Clear() {
m.forwardMap.Clear()
m.inverseMap.Clear()
}
// String returns a string representation of container
func (m *Map) String() string {
func (m *Map[K, V]) String() string {
str := "HashBidiMap\n"
str += fmt.Sprintf("%v", m.forwardMap)
return str

@ -6,13 +6,14 @@ package hashbidimap
import (
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/emirpasic/gods/v2/testutils"
)
func TestMapPut(t *testing.T) {
m := New()
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -25,12 +26,8 @@ func TestMapPut(t *testing.T) {
if actualValue := m.Size(); actualValue != 7 {
t.Errorf("Got %v expected %v", actualValue, 7)
}
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d", "e", "f", "g"}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, m.Keys(), []int{1, 2, 3, 4, 5, 6, 7})
testutils.SameElements(t, m.Values(), []string{"a", "b", "c", "d", "e", "f", "g"})
// key,expectedValue,expectedFound
tests1 := [][]interface{}{
@ -41,12 +38,12 @@ func TestMapPut(t *testing.T) {
{5, "e", true},
{6, "f", true},
{7, "g", true},
{8, nil, false},
{8, "", false},
}
for _, test := range tests1 {
// retrievals
actualValue, actualFound := m.Get(test[0])
actualValue, actualFound := m.Get(test[0].(int))
if actualValue != test[1] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[1])
}
@ -54,7 +51,7 @@ func TestMapPut(t *testing.T) {
}
func TestMapRemove(t *testing.T) {
m := New()
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -70,13 +67,9 @@ func TestMapRemove(t *testing.T) {
m.Remove(8)
m.Remove(5)
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, m.Keys(), []int{1, 2, 3, 4})
testutils.SameElements(t, m.Values(), []string{"a", "b", "c", "d"})
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d"}; !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)
}
@ -86,14 +79,14 @@ func TestMapRemove(t *testing.T) {
{2, "b", true},
{3, "c", true},
{4, "d", true},
{5, nil, false},
{6, nil, false},
{7, nil, false},
{8, nil, false},
{5, "", false},
{6, "", false},
{7, "", false},
{8, "", false},
}
for _, test := range tests2 {
actualValue, actualFound := m.Get(test[0])
actualValue, actualFound := m.Get(test[0].(int))
if actualValue != test[1] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[1])
}
@ -106,12 +99,8 @@ func TestMapRemove(t *testing.T) {
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)
}
testutils.SameElements(t, m.Keys(), nil)
testutils.SameElements(t, m.Values(), nil)
if actualValue := m.Size(); actualValue != 0 {
t.Errorf("Got %v expected %v", actualValue, 0)
}
@ -121,7 +110,7 @@ func TestMapRemove(t *testing.T) {
}
func TestMapGetKey(t *testing.T) {
m := New()
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -140,12 +129,12 @@ func TestMapGetKey(t *testing.T) {
{5, "e", true},
{6, "f", true},
{7, "g", true},
{nil, "x", false},
{0, "x", false},
}
for _, test := range tests1 {
// retrievals
actualValue, actualFound := m.GetKey(test[1])
actualValue, actualFound := m.GetKey(test[1].(string))
if actualValue != test[0] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[0])
}
@ -153,19 +142,15 @@ func TestMapGetKey(t *testing.T) {
}
func TestMapSerialization(t *testing.T) {
m := New()
m := New[string, float64]()
m.Put("a", 1.0)
m.Put("b", 2.0)
m.Put("c", 3.0)
var err error
assert := func() {
if actualValue, expectedValue := m.Keys(), []interface{}{"a", "b", "c"}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, expectedValue := m.Values(), []interface{}{1.0, 2.0, 3.0}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, m.Keys(), []string{"a", "b", "c"})
testutils.SameElements(t, m.Values(), []float64{1.0, 2.0, 3.0})
if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
@ -194,33 +179,14 @@ func TestMapSerialization(t *testing.T) {
}
func TestMapString(t *testing.T) {
c := New()
c := New[string, int]()
c.Put("a", 1)
if !strings.HasPrefix(c.String(), "HashBidiMap") {
t.Errorf("String should start with container name")
}
}
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
}
func benchmarkGet(b *testing.B, m *Map, size int) {
func benchmarkGet(b *testing.B, m *Map[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Get(n)
@ -228,7 +194,7 @@ func benchmarkGet(b *testing.B, m *Map, size int) {
}
}
func benchmarkPut(b *testing.B, m *Map, size int) {
func benchmarkPut(b *testing.B, m *Map[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Put(n, n)
@ -236,7 +202,7 @@ func benchmarkPut(b *testing.B, m *Map, size int) {
}
}
func benchmarkRemove(b *testing.B, m *Map, size int) {
func benchmarkRemove(b *testing.B, m *Map[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Remove(n)
@ -247,7 +213,7 @@ func benchmarkRemove(b *testing.B, m *Map, size int) {
func BenchmarkHashBidiMapGet100(b *testing.B) {
b.StopTimer()
size := 100
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -258,7 +224,7 @@ func BenchmarkHashBidiMapGet100(b *testing.B) {
func BenchmarkHashBidiMapGet1000(b *testing.B) {
b.StopTimer()
size := 1000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -269,7 +235,7 @@ func BenchmarkHashBidiMapGet1000(b *testing.B) {
func BenchmarkHashBidiMapGet10000(b *testing.B) {
b.StopTimer()
size := 10000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -280,7 +246,7 @@ func BenchmarkHashBidiMapGet10000(b *testing.B) {
func BenchmarkHashBidiMapGet100000(b *testing.B) {
b.StopTimer()
size := 100000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -291,7 +257,7 @@ func BenchmarkHashBidiMapGet100000(b *testing.B) {
func BenchmarkHashBidiMapPut100(b *testing.B) {
b.StopTimer()
size := 100
m := New()
m := New[int, int]()
b.StartTimer()
benchmarkPut(b, m, size)
}
@ -299,7 +265,7 @@ func BenchmarkHashBidiMapPut100(b *testing.B) {
func BenchmarkHashBidiMapPut1000(b *testing.B) {
b.StopTimer()
size := 1000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -310,7 +276,7 @@ func BenchmarkHashBidiMapPut1000(b *testing.B) {
func BenchmarkHashBidiMapPut10000(b *testing.B) {
b.StopTimer()
size := 10000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -321,7 +287,7 @@ func BenchmarkHashBidiMapPut10000(b *testing.B) {
func BenchmarkHashBidiMapPut100000(b *testing.B) {
b.StopTimer()
size := 100000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -332,7 +298,7 @@ func BenchmarkHashBidiMapPut100000(b *testing.B) {
func BenchmarkHashBidiMapRemove100(b *testing.B) {
b.StopTimer()
size := 100
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -343,7 +309,7 @@ func BenchmarkHashBidiMapRemove100(b *testing.B) {
func BenchmarkHashBidiMapRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -354,7 +320,7 @@ func BenchmarkHashBidiMapRemove1000(b *testing.B) {
func BenchmarkHashBidiMapRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -365,7 +331,7 @@ func BenchmarkHashBidiMapRemove10000(b *testing.B) {
func BenchmarkHashBidiMapRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}

@ -6,37 +6,41 @@ package hashbidimap
import (
"encoding/json"
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Map)(nil)
var _ containers.JSONDeserializer = (*Map)(nil)
var _ containers.JSONSerializer = (*Map[string, int])(nil)
var _ containers.JSONDeserializer = (*Map[string, int])(nil)
// ToJSON outputs the JSON representation of the map.
func (m *Map) ToJSON() ([]byte, error) {
func (m *Map[K, V]) ToJSON() ([]byte, error) {
return m.forwardMap.ToJSON()
}
// FromJSON populates the map from the input JSON representation.
func (m *Map) FromJSON(data []byte) error {
elements := make(map[string]interface{})
func (m *Map[K, V]) FromJSON(data []byte) error {
var elements map[K]V
err := json.Unmarshal(data, &elements)
if err == nil {
m.Clear()
for key, value := range elements {
m.Put(key, value)
}
if err != nil {
return err
}
m.Clear()
for k, v := range elements {
m.Put(k, v)
}
return err
return nil
}
// UnmarshalJSON @implements json.Unmarshaler
func (m *Map) UnmarshalJSON(bytes []byte) error {
func (m *Map[K, V]) UnmarshalJSON(bytes []byte) error {
return m.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (m *Map) MarshalJSON() ([]byte, error) {
func (m *Map[K, V]) MarshalJSON() ([]byte, error) {
return m.ToJSON()
}

@ -13,52 +13,53 @@ package hashmap
import (
"fmt"
"github.com/emirpasic/gods/maps"
"github.com/emirpasic/gods/v2/maps"
)
// Assert Map implementation
var _ maps.Map = (*Map)(nil)
var _ maps.Map[string, int] = (*Map[string, int])(nil)
// Map holds the elements in go's native map
type Map struct {
m map[interface{}]interface{}
type Map[K comparable, V any] struct {
m map[K]V
}
// New instantiates a hash map.
func New() *Map {
return &Map{m: make(map[interface{}]interface{})}
func New[K comparable, V any]() *Map[K, V] {
return &Map[K, V]{m: make(map[K]V)}
}
// Put inserts element into the map.
func (m *Map) Put(key interface{}, value interface{}) {
func (m *Map[K, V]) Put(key K, value V) {
m.m[key] = value
}
// Get searches the element 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) {
func (m *Map[K, V]) Get(key K) (value V, found bool) {
value, found = m.m[key]
return
}
// Remove removes the element from the map by key.
func (m *Map) Remove(key interface{}) {
func (m *Map[K, V]) Remove(key K) {
delete(m.m, key)
}
// Empty returns true if map does not contain any elements
func (m *Map) Empty() bool {
func (m *Map[K, V]) Empty() bool {
return m.Size() == 0
}
// Size returns number of elements in the map.
func (m *Map) Size() int {
func (m *Map[K, V]) Size() int {
return len(m.m)
}
// Keys returns all keys (random order).
func (m *Map) Keys() []interface{} {
keys := make([]interface{}, m.Size())
func (m *Map[K, V]) Keys() []K {
keys := make([]K, m.Size())
count := 0
for key := range m.m {
keys[count] = key
@ -68,8 +69,8 @@ func (m *Map) Keys() []interface{} {
}
// Values returns all values (random order).
func (m *Map) Values() []interface{} {
values := make([]interface{}, m.Size())
func (m *Map[K, V]) Values() []V {
values := make([]V, m.Size())
count := 0
for _, value := range m.m {
values[count] = value
@ -79,12 +80,12 @@ func (m *Map) Values() []interface{} {
}
// Clear removes all elements from the map.
func (m *Map) Clear() {
m.m = make(map[interface{}]interface{})
func (m *Map[K, V]) Clear() {
clear(m.m)
}
// String returns a string representation of container
func (m *Map) String() string {
func (m *Map[K, V]) String() string {
str := "HashMap\n"
str += fmt.Sprintf("%v", m.m)
return str

@ -6,13 +6,14 @@ package hashmap
import (
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/emirpasic/gods/v2/testutils"
)
func TestMapPut(t *testing.T) {
m := New()
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -25,12 +26,8 @@ func TestMapPut(t *testing.T) {
if actualValue := m.Size(); actualValue != 7 {
t.Errorf("Got %v expected %v", actualValue, 7)
}
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d", "e", "f", "g"}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, m.Keys(), []int{1, 2, 3, 4, 5, 6, 7})
testutils.SameElements(t, m.Values(), []string{"a", "b", "c", "d", "e", "f", "g"})
// key,expectedValue,expectedFound
tests1 := [][]interface{}{
@ -41,12 +38,12 @@ func TestMapPut(t *testing.T) {
{5, "e", true},
{6, "f", true},
{7, "g", true},
{8, nil, false},
{8, "", false},
}
for _, test := range tests1 {
// retrievals
actualValue, actualFound := m.Get(test[0])
actualValue, actualFound := m.Get(test[0].(int))
if actualValue != test[1] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[1])
}
@ -54,7 +51,7 @@ func TestMapPut(t *testing.T) {
}
func TestMapRemove(t *testing.T) {
m := New()
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -70,13 +67,9 @@ func TestMapRemove(t *testing.T) {
m.Remove(8)
m.Remove(5)
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, m.Keys(), []int{1, 2, 3, 4})
testutils.SameElements(t, m.Values(), []string{"a", "b", "c", "d"})
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d"}; !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)
}
@ -86,14 +79,14 @@ func TestMapRemove(t *testing.T) {
{2, "b", true},
{3, "c", true},
{4, "d", true},
{5, nil, false},
{6, nil, false},
{7, nil, false},
{8, nil, false},
{5, "", false},
{6, "", false},
{7, "", false},
{8, "", false},
}
for _, test := range tests2 {
actualValue, actualFound := m.Get(test[0])
actualValue, actualFound := m.Get(test[0].(int))
if actualValue != test[1] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[1])
}
@ -106,12 +99,8 @@ func TestMapRemove(t *testing.T) {
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)
}
testutils.SameElements(t, m.Keys(), nil)
testutils.SameElements(t, m.Values(), nil)
if actualValue := m.Size(); actualValue != 0 {
t.Errorf("Got %v expected %v", actualValue, 0)
}
@ -121,19 +110,15 @@ func TestMapRemove(t *testing.T) {
}
func TestMapSerialization(t *testing.T) {
m := New()
m := New[string, float64]()
m.Put("a", 1.0)
m.Put("b", 2.0)
m.Put("c", 3.0)
var err error
assert := func() {
if actualValue, expectedValue := m.Keys(), []interface{}{"a", "b", "c"}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, expectedValue := m.Values(), []interface{}{1.0, 2.0, 3.0}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, m.Keys(), []string{"a", "b", "c"})
testutils.SameElements(t, m.Values(), []float64{1.0, 2.0, 3.0})
if actualValue, expectedValue := m.Size(), 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
@ -162,33 +147,14 @@ func TestMapSerialization(t *testing.T) {
}
func TestMapString(t *testing.T) {
c := New()
c := New[string, int]()
c.Put("a", 1)
if !strings.HasPrefix(c.String(), "HashMap") {
t.Errorf("String should start with container name")
}
}
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
}
func benchmarkGet(b *testing.B, m *Map, size int) {
func benchmarkGet(b *testing.B, m *Map[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Get(n)
@ -196,15 +162,15 @@ func benchmarkGet(b *testing.B, m *Map, size int) {
}
}
func benchmarkPut(b *testing.B, m *Map, size int) {
func benchmarkPut(b *testing.B, m *Map[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
}
}
func benchmarkRemove(b *testing.B, m *Map, size int) {
func benchmarkRemove(b *testing.B, m *Map[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Remove(n)
@ -215,9 +181,9 @@ func benchmarkRemove(b *testing.B, m *Map, size int) {
func BenchmarkHashMapGet100(b *testing.B) {
b.StopTimer()
size := 100
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkGet(b, m, size)
@ -226,9 +192,9 @@ func BenchmarkHashMapGet100(b *testing.B) {
func BenchmarkHashMapGet1000(b *testing.B) {
b.StopTimer()
size := 1000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkGet(b, m, size)
@ -237,9 +203,9 @@ func BenchmarkHashMapGet1000(b *testing.B) {
func BenchmarkHashMapGet10000(b *testing.B) {
b.StopTimer()
size := 10000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkGet(b, m, size)
@ -248,9 +214,9 @@ func BenchmarkHashMapGet10000(b *testing.B) {
func BenchmarkHashMapGet100000(b *testing.B) {
b.StopTimer()
size := 100000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkGet(b, m, size)
@ -259,7 +225,7 @@ func BenchmarkHashMapGet100000(b *testing.B) {
func BenchmarkHashMapPut100(b *testing.B) {
b.StopTimer()
size := 100
m := New()
m := New[int, int]()
b.StartTimer()
benchmarkPut(b, m, size)
}
@ -267,9 +233,9 @@ func BenchmarkHashMapPut100(b *testing.B) {
func BenchmarkHashMapPut1000(b *testing.B) {
b.StopTimer()
size := 1000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkPut(b, m, size)
@ -278,9 +244,9 @@ func BenchmarkHashMapPut1000(b *testing.B) {
func BenchmarkHashMapPut10000(b *testing.B) {
b.StopTimer()
size := 10000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkPut(b, m, size)
@ -289,9 +255,9 @@ func BenchmarkHashMapPut10000(b *testing.B) {
func BenchmarkHashMapPut100000(b *testing.B) {
b.StopTimer()
size := 100000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkPut(b, m, size)
@ -300,9 +266,9 @@ func BenchmarkHashMapPut100000(b *testing.B) {
func BenchmarkHashMapRemove100(b *testing.B) {
b.StopTimer()
size := 100
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkRemove(b, m, size)
@ -311,9 +277,9 @@ func BenchmarkHashMapRemove100(b *testing.B) {
func BenchmarkHashMapRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkRemove(b, m, size)
@ -322,9 +288,9 @@ func BenchmarkHashMapRemove1000(b *testing.B) {
func BenchmarkHashMapRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkRemove(b, m, size)
@ -333,9 +299,9 @@ func BenchmarkHashMapRemove10000(b *testing.B) {
func BenchmarkHashMapRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkRemove(b, m, size)

@ -6,42 +6,30 @@ package hashmap
import (
"encoding/json"
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/utils"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Map)(nil)
var _ containers.JSONDeserializer = (*Map)(nil)
var _ containers.JSONSerializer = (*Map[string, int])(nil)
var _ containers.JSONDeserializer = (*Map[string, int])(nil)
// ToJSON outputs the JSON representation of the map.
func (m *Map) ToJSON() ([]byte, error) {
elements := make(map[string]interface{})
for key, value := range m.m {
elements[utils.ToString(key)] = value
}
return json.Marshal(&elements)
func (m *Map[K, V]) ToJSON() ([]byte, error) {
return json.Marshal(m.m)
}
// FromJSON populates the 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.m[key] = value
}
}
return err
func (m *Map[K, V]) FromJSON(data []byte) error {
return json.Unmarshal(data, &m.m)
}
// UnmarshalJSON @implements json.Unmarshaler
func (m *Map) UnmarshalJSON(bytes []byte) error {
func (m *Map[K, V]) UnmarshalJSON(bytes []byte) error {
return m.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (m *Map) MarshalJSON() ([]byte, error) {
func (m *Map[K, V]) MarshalJSON() ([]byte, error) {
return m.ToJSON()
}

@ -4,13 +4,13 @@
package linkedhashmap
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Enumerable implementation
var _ containers.EnumerableWithKey = (*Map)(nil)
var _ containers.EnumerableWithKey[string, int] = (*Map[string, int])(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{})) {
func (m *Map[K, V]) Each(f func(key K, value V)) {
iterator := m.Iterator()
for iterator.Next() {
f(iterator.Key(), iterator.Value())
@ -19,8 +19,8 @@ func (m *Map) Each(f func(key interface{}, value interface{})) {
// 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()
func (m *Map[K, V]) Map(f func(key1 K, value1 V) (K, V)) *Map[K, V] {
newMap := New[K, V]()
iterator := m.Iterator()
for iterator.Next() {
key2, value2 := f(iterator.Key(), iterator.Value())
@ -30,8 +30,8 @@ func (m *Map) Map(f func(key1 interface{}, value1 interface{}) (interface{}, int
}
// 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()
func (m *Map[K, V]) Select(f func(key K, value V) bool) *Map[K, V] {
newMap := New[K, V]()
iterator := m.Iterator()
for iterator.Next() {
if f(iterator.Key(), iterator.Value()) {
@ -43,7 +43,7 @@ func (m *Map) Select(f func(key interface{}, value interface{}) bool) *Map {
// 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 {
func (m *Map[K, V]) Any(f func(key K, value V) bool) bool {
iterator := m.Iterator()
for iterator.Next() {
if f(iterator.Key(), iterator.Value()) {
@ -55,7 +55,7 @@ func (m *Map) Any(f func(key interface{}, value interface{}) bool) bool {
// 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 {
func (m *Map[K, V]) All(f func(key K, value V) bool) bool {
iterator := m.Iterator()
for iterator.Next() {
if !f(iterator.Key(), iterator.Value()) {
@ -68,12 +68,12 @@ func (m *Map) All(f func(key interface{}, value interface{}) bool) bool {
// 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{}) {
func (m *Map[K, V]) Find(f func(key K, value V) bool) (k K, v V) {
iterator := m.Iterator()
for iterator.Next() {
if f(iterator.Key(), iterator.Value()) {
return iterator.Key(), iterator.Value()
}
}
return nil, nil
return k, v
}

@ -5,77 +5,78 @@
package linkedhashmap
import (
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/lists/doublylinkedlist"
"github.com/emirpasic/gods/v2/containers"
"github.com/emirpasic/gods/v2/lists/doublylinkedlist"
)
// Assert Iterator implementation
var _ containers.ReverseIteratorWithKey = (*Iterator)(nil)
var _ containers.ReverseIteratorWithKey[string, int] = (*Iterator[string, int])(nil)
// Iterator holding the iterator's state
type Iterator struct {
iterator doublylinkedlist.Iterator
table map[interface{}]interface{}
type Iterator[K comparable, V any] struct {
iterator doublylinkedlist.Iterator[K]
table map[K]V
}
// Iterator returns a stateful iterator whose elements are key/value pairs.
func (m *Map) Iterator() Iterator {
return Iterator{
func (m *Map[K, V]) Iterator() *Iterator[K, V] {
return &Iterator[K, V]{
iterator: m.ordering.Iterator(),
table: m.table}
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 {
func (iterator *Iterator[K, V]) 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 {
func (iterator *Iterator[K, V]) 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{} {
func (iterator *Iterator[K, V]) Value() V {
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{} {
func (iterator *Iterator[K, V]) Key() K {
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() {
func (iterator *Iterator[K, V]) 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() {
func (iterator *Iterator[K, V]) 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 {
func (iterator *Iterator[K, V]) 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 {
func (iterator *Iterator[K, V]) Last() bool {
return iterator.iterator.Last()
}
@ -83,7 +84,7 @@ func (iterator *Iterator) Last() bool {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(key interface{}, value interface{}) bool) bool {
func (iterator *Iterator[K, V]) NextTo(f func(key K, value V) bool) bool {
for iterator.Next() {
key, value := iterator.Key(), iterator.Value()
if f(key, value) {
@ -97,7 +98,7 @@ func (iterator *Iterator) NextTo(f func(key interface{}, value interface{}) bool
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(key interface{}, value interface{}) bool) bool {
func (iterator *Iterator[K, V]) PrevTo(f func(key K, value V) bool) bool {
for iterator.Prev() {
key, value := iterator.Key(), iterator.Value()
if f(key, value) {

@ -13,31 +13,32 @@ package linkedhashmap
import (
"fmt"
"github.com/emirpasic/gods/lists/doublylinkedlist"
"github.com/emirpasic/gods/maps"
"strings"
"github.com/emirpasic/gods/v2/lists/doublylinkedlist"
"github.com/emirpasic/gods/v2/maps"
)
// Assert Map implementation
var _ maps.Map = (*Map)(nil)
var _ maps.Map[string, int] = (*Map[string, int])(nil)
// Map holds the elements in a regular hash table, and uses doubly-linked list to store key ordering.
type Map struct {
table map[interface{}]interface{}
ordering *doublylinkedlist.List
type Map[K comparable, V any] struct {
table map[K]V
ordering *doublylinkedlist.List[K]
}
// New instantiates a linked-hash-map.
func New() *Map {
return &Map{
table: make(map[interface{}]interface{}),
ordering: doublylinkedlist.New(),
func New[K comparable, V any]() *Map[K, V] {
return &Map[K, V]{
table: make(map[K]V),
ordering: doublylinkedlist.New[K](),
}
}
// 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{}) {
func (m *Map[K, V]) Put(key K, value V) {
if _, contains := m.table[key]; !contains {
m.ordering.Append(key)
}
@ -47,15 +48,14 @@ func (m *Map) Put(key interface{}, value interface{}) {
// 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
func (m *Map[K, V]) Get(key K) (value V, found bool) {
value, found = m.table[key]
return value, found
}
// 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{}) {
func (m *Map[K, V]) Remove(key K) {
if _, contains := m.table[key]; contains {
delete(m.table, key)
index := m.ordering.IndexOf(key)
@ -64,23 +64,23 @@ func (m *Map) Remove(key interface{}) {
}
// Empty returns true if map does not contain any elements
func (m *Map) Empty() bool {
func (m *Map[K, V]) Empty() bool {
return m.Size() == 0
}
// Size returns number of elements in the map.
func (m *Map) Size() int {
func (m *Map[K, V]) Size() int {
return m.ordering.Size()
}
// Keys returns all keys in-order
func (m *Map) Keys() []interface{} {
func (m *Map[K, V]) Keys() []K {
return m.ordering.Values()
}
// Values returns all values in-order based on the key.
func (m *Map) Values() []interface{} {
values := make([]interface{}, m.Size())
func (m *Map[K, V]) Values() []V {
values := make([]V, m.Size())
count := 0
it := m.Iterator()
for it.Next() {
@ -91,13 +91,13 @@ func (m *Map) Values() []interface{} {
}
// Clear removes all elements from the map.
func (m *Map) Clear() {
m.table = make(map[interface{}]interface{})
func (m *Map[K, V]) Clear() {
clear(m.table)
m.ordering.Clear()
}
// String returns a string representation of container
func (m *Map) String() string {
func (m *Map[K, V]) String() string {
str := "LinkedHashMap\nmap["
it := m.Iterator()
for it.Next() {

@ -6,13 +6,14 @@ package linkedhashmap
import (
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/emirpasic/gods/v2/testutils"
)
func TestMapPut(t *testing.T) {
m := New()
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -25,12 +26,8 @@ func TestMapPut(t *testing.T) {
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)
}
testutils.SameElements(t, m.Keys(), []int{1, 2, 3, 4, 5, 6, 7})
testutils.SameElements(t, m.Values(), []string{"a", "b", "c", "d", "e", "f", "g"})
// key,expectedValue,expectedFound
tests1 := [][]interface{}{
@ -41,12 +38,12 @@ func TestMapPut(t *testing.T) {
{5, "e", true},
{6, "f", true},
{7, "g", true},
{8, nil, false},
{8, "", false},
}
for _, test := range tests1 {
// retrievals
actualValue, actualFound := m.Get(test[0])
actualValue, actualFound := m.Get(test[0].(int))
if actualValue != test[1] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[1])
}
@ -54,7 +51,7 @@ func TestMapPut(t *testing.T) {
}
func TestMapRemove(t *testing.T) {
m := New()
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -70,13 +67,9 @@ func TestMapRemove(t *testing.T) {
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)
}
testutils.SameElements(t, m.Keys(), []int{1, 2, 3, 4})
testutils.SameElements(t, m.Values(), []string{"a", "b", "c", "d"})
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)
}
@ -86,14 +79,14 @@ func TestMapRemove(t *testing.T) {
{2, "b", true},
{3, "c", true},
{4, "d", true},
{5, nil, false},
{6, nil, false},
{7, nil, false},
{8, nil, false},
{5, "", false},
{6, "", false},
{7, "", false},
{8, "", false},
}
for _, test := range tests2 {
actualValue, actualFound := m.Get(test[0])
actualValue, actualFound := m.Get(test[0].(int))
if actualValue != test[1] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[1])
}
@ -106,12 +99,8 @@ func TestMapRemove(t *testing.T) {
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)
}
testutils.SameElements(t, m.Keys(), nil)
testutils.SameElements(t, m.Values(), nil)
if actualValue := m.Size(); actualValue != 0 {
t.Errorf("Got %v expected %v", actualValue, 0)
}
@ -120,32 +109,13 @@ func TestMapRemove(t *testing.T) {
}
}
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 := New[string, int]()
m.Put("c", 1)
m.Put("a", 2)
m.Put("b", 3)
count := 0
m.Each(func(key interface{}, value interface{}) {
m.Each(func(key string, value int) {
count++
if actualValue, expectedValue := count, value; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -170,12 +140,12 @@ func TestMapEach(t *testing.T) {
}
func TestMapMap(t *testing.T) {
m := New()
m := New[string, int]()
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)
mappedMap := m.Map(func(key1 string, value1 int) (key2 string, value2 int) {
return key1, value1 * value1
})
if actualValue, _ := mappedMap.Get("c"); actualValue != 9 {
t.Errorf("Got %v expected %v", actualValue, "mapped: c")
@ -192,12 +162,12 @@ func TestMapMap(t *testing.T) {
}
func TestMapSelect(t *testing.T) {
m := New()
m := New[string, int]()
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"
selectedMap := m.Select(func(key string, value int) bool {
return key >= "a" && key <= "b"
})
if actualValue, _ := selectedMap.Get("b"); actualValue != 1 {
t.Errorf("Got %v expected %v", actualValue, "value: a")
@ -211,18 +181,18 @@ func TestMapSelect(t *testing.T) {
}
func TestMapAny(t *testing.T) {
m := New()
m := New[string, int]()
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
any := m.Any(func(key string, value int) bool {
return value == 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
any = m.Any(func(key string, value int) bool {
return value == 4
})
if any != false {
t.Errorf("Got %v expected %v", any, false)
@ -230,18 +200,18 @@ func TestMapAny(t *testing.T) {
}
func TestMapAll(t *testing.T) {
m := New()
m := New[string, int]()
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"
all := m.All(func(key string, value int) bool {
return key >= "a" && key <= "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"
all = m.All(func(key string, value int) bool {
return key >= "a" && key <= "b"
})
if all != false {
t.Errorf("Got %v expected %v", all, false)
@ -249,38 +219,38 @@ func TestMapAll(t *testing.T) {
}
func TestMapFind(t *testing.T) {
m := New()
m := New[string, int]()
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"
foundKey, foundValue := m.Find(func(key string, value int) bool {
return key == "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"
foundKey, foundValue = m.Find(func(key string, value int) bool {
return key == "x"
})
if foundKey != nil || foundValue != nil {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundKey, nil, nil)
if foundKey != "" || foundValue != 0 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundKey, "", 0)
}
}
func TestMapChaining(t *testing.T) {
m := New()
m := New[string, int]()
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)
chainedMap := m.Select(func(key string, value int) bool {
return value > 1
}).Map(func(key string, value int) (string, int) {
return key + key, value * value
})
if actualValue := chainedMap.Size(); actualValue != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if actualValue, found := chainedMap.Get("aa"); actualValue != nil || found {
if actualValue, found := chainedMap.Get("aa"); actualValue != 0 || found {
t.Errorf("Got %v expected %v", actualValue, nil)
}
if actualValue, found := chainedMap.Get("bb"); actualValue != 4 || !found {
@ -292,7 +262,7 @@ func TestMapChaining(t *testing.T) {
}
func TestMapIteratorNextOnEmpty(t *testing.T) {
m := New()
m := New[string, int]()
it := m.Iterator()
it = m.Iterator()
for it.Next() {
@ -301,7 +271,7 @@ func TestMapIteratorNextOnEmpty(t *testing.T) {
}
func TestMapIteratorPrevOnEmpty(t *testing.T) {
m := New()
m := New[string, int]()
it := m.Iterator()
it = m.Iterator()
for it.Prev() {
@ -310,7 +280,7 @@ func TestMapIteratorPrevOnEmpty(t *testing.T) {
}
func TestMapIteratorNext(t *testing.T) {
m := New()
m := New[string, int]()
m.Put("c", 1)
m.Put("a", 2)
m.Put("b", 3)
@ -347,7 +317,7 @@ func TestMapIteratorNext(t *testing.T) {
}
func TestMapIteratorPrev(t *testing.T) {
m := New()
m := New[string, int]()
m.Put("c", 1)
m.Put("a", 2)
m.Put("b", 3)
@ -386,7 +356,7 @@ func TestMapIteratorPrev(t *testing.T) {
}
func TestMapIteratorBegin(t *testing.T) {
m := New()
m := New[int, string]()
it := m.Iterator()
it.Begin()
m.Put(3, "c")
@ -402,7 +372,7 @@ func TestMapIteratorBegin(t *testing.T) {
}
func TestMapIteratorEnd(t *testing.T) {
m := New()
m := New[int, string]()
it := m.Iterator()
m.Put(3, "c")
m.Put(1, "a")
@ -415,7 +385,7 @@ func TestMapIteratorEnd(t *testing.T) {
}
func TestMapIteratorFirst(t *testing.T) {
m := New()
m := New[int, string]()
m.Put(3, "c")
m.Put(1, "a")
m.Put(2, "b")
@ -429,7 +399,7 @@ func TestMapIteratorFirst(t *testing.T) {
}
func TestMapIteratorLast(t *testing.T) {
m := New()
m := New[int, string]()
m.Put(3, "c")
m.Put(1, "a")
m.Put(2, "b")
@ -444,13 +414,13 @@ func TestMapIteratorLast(t *testing.T) {
func TestMapIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index interface{}, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// NextTo (empty)
{
m := New()
m := New[int, string]()
it := m.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty map")
@ -459,7 +429,7 @@ func TestMapIteratorNextTo(t *testing.T) {
// NextTo (not found)
{
m := New()
m := New[int, string]()
m.Put(0, "xx")
m.Put(1, "yy")
it := m.Iterator()
@ -470,7 +440,7 @@ func TestMapIteratorNextTo(t *testing.T) {
// NextTo (found)
{
m := New()
m := New[int, string]()
m.Put(0, "aa")
m.Put(1, "bb")
m.Put(2, "cc")
@ -479,13 +449,13 @@ func TestMapIteratorNextTo(t *testing.T) {
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty map")
}
if index, value := it.Key(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Key(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Key(), it.Value(); index != 2 || value.(string) != "cc" {
if index, value := it.Key(), it.Value(); index != 2 || value != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
@ -496,13 +466,13 @@ func TestMapIteratorNextTo(t *testing.T) {
func TestMapIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index interface{}, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// PrevTo (empty)
{
m := New()
m := New[int, string]()
it := m.Iterator()
it.End()
for it.PrevTo(seek) {
@ -512,7 +482,7 @@ func TestMapIteratorPrevTo(t *testing.T) {
// PrevTo (not found)
{
m := New()
m := New[int, string]()
m.Put(0, "xx")
m.Put(1, "yy")
it := m.Iterator()
@ -524,7 +494,7 @@ func TestMapIteratorPrevTo(t *testing.T) {
// PrevTo (found)
{
m := New()
m := New[int, string]()
m.Put(0, "aa")
m.Put(1, "bb")
m.Put(2, "cc")
@ -533,13 +503,13 @@ func TestMapIteratorPrevTo(t *testing.T) {
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty map")
}
if index, value := it.Key(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Key(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Key(), it.Value(); index != 0 || value.(string) != "aa" {
if index, value := it.Key(), it.Value(); index != 0 || value != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
@ -550,30 +520,36 @@ func TestMapIteratorPrevTo(t *testing.T) {
func TestMapSerialization(t *testing.T) {
for i := 0; i < 10; i++ {
original := New()
original := New[string, string]()
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()
deserialized := New[string, string]()
err = deserialized.FromJSON(serialized)
if err != nil {
t.Errorf("Got error %v", err)
}
assertSerialization(deserialized, "C", t)
if original.Size() != deserialized.Size() {
t.Errorf("Got map of size %d, expected %d", original.Size(), deserialized.Size())
}
original.Each(func(key string, expected string) {
actual, ok := deserialized.Get(key)
if !ok || actual != expected {
t.Errorf("Did not find expected value %v for key %v in deserialied map (got %v)", expected, key, actual)
}
})
}
m := New()
m := New[string, float64]()
m.Put("a", 1.0)
m.Put("b", 2.0)
m.Put("c", 3.0)
@ -590,37 +566,14 @@ func TestMapSerialization(t *testing.T) {
}
func TestMapString(t *testing.T) {
c := New()
c := New[string, int]()
c.Put("a", 1)
if !strings.HasPrefix(c.String(), "LinkedHashMap") {
t.Errorf("String should start with container name")
}
}
//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) {
func benchmarkGet(b *testing.B, m *Map[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Get(n)
@ -628,15 +581,15 @@ func benchmarkGet(b *testing.B, m *Map, size int) {
}
}
func benchmarkPut(b *testing.B, m *Map, size int) {
func benchmarkPut(b *testing.B, m *Map[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
}
}
func benchmarkRemove(b *testing.B, m *Map, size int) {
func benchmarkRemove(b *testing.B, m *Map[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Remove(n)
@ -647,9 +600,9 @@ func benchmarkRemove(b *testing.B, m *Map, size int) {
func BenchmarkTreeMapGet100(b *testing.B) {
b.StopTimer()
size := 100
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkGet(b, m, size)
@ -658,9 +611,9 @@ func BenchmarkTreeMapGet100(b *testing.B) {
func BenchmarkTreeMapGet1000(b *testing.B) {
b.StopTimer()
size := 1000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkGet(b, m, size)
@ -669,9 +622,9 @@ func BenchmarkTreeMapGet1000(b *testing.B) {
func BenchmarkTreeMapGet10000(b *testing.B) {
b.StopTimer()
size := 10000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkGet(b, m, size)
@ -680,9 +633,9 @@ func BenchmarkTreeMapGet10000(b *testing.B) {
func BenchmarkTreeMapGet100000(b *testing.B) {
b.StopTimer()
size := 100000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkGet(b, m, size)
@ -691,7 +644,7 @@ func BenchmarkTreeMapGet100000(b *testing.B) {
func BenchmarkTreeMapPut100(b *testing.B) {
b.StopTimer()
size := 100
m := New()
m := New[int, int]()
b.StartTimer()
benchmarkPut(b, m, size)
}
@ -699,9 +652,9 @@ func BenchmarkTreeMapPut100(b *testing.B) {
func BenchmarkTreeMapPut1000(b *testing.B) {
b.StopTimer()
size := 1000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkPut(b, m, size)
@ -710,9 +663,9 @@ func BenchmarkTreeMapPut1000(b *testing.B) {
func BenchmarkTreeMapPut10000(b *testing.B) {
b.StopTimer()
size := 10000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkPut(b, m, size)
@ -721,9 +674,9 @@ func BenchmarkTreeMapPut10000(b *testing.B) {
func BenchmarkTreeMapPut100000(b *testing.B) {
b.StopTimer()
size := 100000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkPut(b, m, size)
@ -732,9 +685,9 @@ func BenchmarkTreeMapPut100000(b *testing.B) {
func BenchmarkTreeMapRemove100(b *testing.B) {
b.StopTimer()
size := 100
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkRemove(b, m, size)
@ -743,9 +696,9 @@ func BenchmarkTreeMapRemove100(b *testing.B) {
func BenchmarkTreeMapRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkRemove(b, m, size)
@ -754,9 +707,9 @@ func BenchmarkTreeMapRemove1000(b *testing.B) {
func BenchmarkTreeMapRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkRemove(b, m, size)
@ -765,9 +718,9 @@ func BenchmarkTreeMapRemove10000(b *testing.B) {
func BenchmarkTreeMapRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
m := New()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
m.Put(n, n)
}
b.StartTimer()
benchmarkRemove(b, m, size)

@ -6,17 +6,19 @@ package linkedhashmap
import (
"bytes"
"cmp"
"encoding/json"
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/utils"
"slices"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Map)(nil)
var _ containers.JSONDeserializer = (*Map)(nil)
var _ containers.JSONSerializer = (*Map[string, int])(nil)
var _ containers.JSONDeserializer = (*Map[string, int])(nil)
// ToJSON outputs the JSON representation of map.
func (m *Map) ToJSON() ([]byte, error) {
func (m *Map[K, V]) ToJSON() ([]byte, error) {
var b []byte
buf := bytes.NewBuffer(b)
@ -54,7 +56,7 @@ func (m *Map) ToJSON() ([]byte, error) {
}
// FromJSON populates map from the input JSON representation.
//func (m *Map) FromJSON(data []byte) error {
//func (m *Map[K, V]) FromJSON(data []byte) error {
// elements := make(map[string]interface{})
// err := json.Unmarshal(data, &elements)
// if err == nil {
@ -67,46 +69,42 @@ func (m *Map) ToJSON() ([]byte, error) {
//}
// FromJSON populates map from the input JSON representation.
func (m *Map) FromJSON(data []byte) error {
elements := make(map[string]interface{})
func (m *Map[K, V]) FromJSON(data []byte) error {
elements := make(map[K]V)
err := json.Unmarshal(data, &elements)
if err != nil {
return err
}
index := make(map[string]int)
var keys []interface{}
index := make(map[K]int)
var keys []K
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
byIndex := func(key1, key2 K) int {
return cmp.Compare(index[key1], index[key2])
}
utils.Sort(keys, byIndex)
slices.SortFunc(keys, byIndex)
m.Clear()
for _, key := range keys {
m.Put(key, elements[key.(string)])
m.Put(key, elements[key])
}
return nil
}
// UnmarshalJSON @implements json.Unmarshaler
func (m *Map) UnmarshalJSON(bytes []byte) error {
func (m *Map[K, V]) UnmarshalJSON(bytes []byte) error {
return m.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (m *Map) MarshalJSON() ([]byte, error) {
func (m *Map[K, V]) MarshalJSON() ([]byte, error) {
return m.ToJSON()
}

@ -15,16 +15,16 @@
// Reference: https://en.wikipedia.org/wiki/Associative_array
package maps
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Map interface that all maps implement
type Map interface {
Put(key interface{}, value interface{})
Get(key interface{}) (value interface{}, found bool)
Remove(key interface{})
Keys() []interface{}
type Map[K comparable, V any] interface {
Put(key K, value V)
Get(key K) (value V, found bool)
Remove(key K)
Keys() []K
containers.Container
containers.Container[V]
// Empty() bool
// Size() int
// Clear()
@ -33,8 +33,8 @@ type Map interface {
}
// BidiMap interface that all bidirectional maps implement (extends the Map interface)
type BidiMap interface {
GetKey(value interface{}) (key interface{}, found bool)
type BidiMap[K comparable, V comparable] interface {
GetKey(value V) (key K, found bool)
Map
Map[K, V]
}

@ -4,13 +4,13 @@
package treebidimap
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Enumerable implementation
var _ containers.EnumerableWithKey = (*Map)(nil)
var _ containers.EnumerableWithKey[string, int] = (*Map[string, int])(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{})) {
func (m *Map[K, V]) Each(f func(key K, value V)) {
iterator := m.Iterator()
for iterator.Next() {
f(iterator.Key(), iterator.Value())
@ -19,8 +19,8 @@ func (m *Map) Each(f func(key interface{}, value interface{})) {
// 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 := NewWith(m.keyComparator, m.valueComparator)
func (m *Map[K, V]) Map(f func(key1 K, value1 V) (K, V)) *Map[K, V] {
newMap := NewWith[K, V](m.forwardMap.Comparator, m.inverseMap.Comparator)
iterator := m.Iterator()
for iterator.Next() {
key2, value2 := f(iterator.Key(), iterator.Value())
@ -30,8 +30,8 @@ func (m *Map) Map(f func(key1 interface{}, value1 interface{}) (interface{}, int
}
// 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 := NewWith(m.keyComparator, m.valueComparator)
func (m *Map[K, V]) Select(f func(key K, value V) bool) *Map[K, V] {
newMap := NewWith[K, V](m.forwardMap.Comparator, m.inverseMap.Comparator)
iterator := m.Iterator()
for iterator.Next() {
if f(iterator.Key(), iterator.Value()) {
@ -43,7 +43,7 @@ func (m *Map) Select(f func(key interface{}, value interface{}) bool) *Map {
// 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 {
func (m *Map[K, V]) Any(f func(key K, value V) bool) bool {
iterator := m.Iterator()
for iterator.Next() {
if f(iterator.Key(), iterator.Value()) {
@ -55,7 +55,7 @@ func (m *Map) Any(f func(key interface{}, value interface{}) bool) bool {
// 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 {
func (m *Map[K, V]) All(f func(key K, value V) bool) bool {
iterator := m.Iterator()
for iterator.Next() {
if !f(iterator.Key(), iterator.Value()) {
@ -68,12 +68,12 @@ func (m *Map) All(f func(key interface{}, value interface{}) bool) bool {
// 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{}) {
func (m *Map[K, V]) Find(f func(key K, value V) bool) (k K, v V) {
iterator := m.Iterator()
for iterator.Next() {
if f(iterator.Key(), iterator.Value()) {
return iterator.Key(), iterator.Value()
}
}
return nil, nil
return k, v
}

@ -5,73 +5,73 @@
package treebidimap
import (
"github.com/emirpasic/gods/containers"
rbt "github.com/emirpasic/gods/trees/redblacktree"
"github.com/emirpasic/gods/v2/containers"
rbt "github.com/emirpasic/gods/v2/trees/redblacktree"
)
// Assert Iterator implementation
var _ containers.ReverseIteratorWithKey = (*Iterator)(nil)
var _ containers.ReverseIteratorWithKey[string, int] = (*Iterator[string, int])(nil)
// Iterator holding the iterator's state
type Iterator struct {
iterator rbt.Iterator
type Iterator[K comparable, V any] struct {
iterator *rbt.Iterator[K, V]
}
// Iterator returns a stateful iterator whose elements are key/value pairs.
func (m *Map) Iterator() Iterator {
return Iterator{iterator: m.forwardMap.Iterator()}
func (m *Map[K, V]) Iterator() *Iterator[K, V] {
return &Iterator[K, V]{iterator: m.forwardMap.Iterator()}
}
// 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 {
func (iterator *Iterator[K, V]) 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 {
func (iterator *Iterator[K, V]) 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{} {
return iterator.iterator.Value().(*data).value
func (iterator *Iterator[K, V]) Value() V {
return iterator.iterator.Value()
}
// Key returns the current element's key.
// Does not modify the state of the iterator.
func (iterator *Iterator) Key() interface{} {
func (iterator *Iterator[K, V]) Key() K {
return iterator.iterator.Key()
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
func (iterator *Iterator[K, V]) 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() {
func (iterator *Iterator[K, V]) 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 {
func (iterator *Iterator[K, V]) 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 {
func (iterator *Iterator[K, V]) Last() bool {
return iterator.iterator.Last()
}
@ -79,7 +79,7 @@ func (iterator *Iterator) Last() bool {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(key interface{}, value interface{}) bool) bool {
func (iterator *Iterator[K, V]) NextTo(f func(key K, value V) bool) bool {
for iterator.Next() {
key, value := iterator.Key(), iterator.Value()
if f(key, value) {
@ -93,7 +93,7 @@ func (iterator *Iterator) NextTo(f func(key interface{}, value interface{}) bool
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(key interface{}, value interface{}) bool) bool {
func (iterator *Iterator[K, V]) PrevTo(f func(key K, value V) bool) bool {
for iterator.Prev() {
key, value := iterator.Key(), iterator.Value()
if f(key, value) {

@ -6,43 +6,41 @@ package treebidimap
import (
"encoding/json"
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/utils"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Map)(nil)
var _ containers.JSONDeserializer = (*Map)(nil)
var _ containers.JSONSerializer = (*Map[string, int])(nil)
var _ containers.JSONDeserializer = (*Map[string, int])(nil)
// ToJSON outputs the JSON representation of the map.
func (m *Map) ToJSON() ([]byte, error) {
elements := make(map[string]interface{})
it := m.Iterator()
for it.Next() {
elements[utils.ToString(it.Key())] = it.Value()
}
return json.Marshal(&elements)
func (m *Map[K, V]) ToJSON() ([]byte, error) {
return m.forwardMap.ToJSON()
}
// FromJSON populates the map from the input JSON representation.
func (m *Map) FromJSON(data []byte) error {
elements := make(map[string]interface{})
func (m *Map[K, V]) FromJSON(data []byte) error {
var elements map[K]V
err := json.Unmarshal(data, &elements)
if err == nil {
m.Clear()
for key, value := range elements {
m.Put(key, value)
}
if err != nil {
return err
}
return err
m.Clear()
for key, value := range elements {
m.Put(key, value)
}
return nil
}
// UnmarshalJSON @implements json.Unmarshaler
func (m *Map) UnmarshalJSON(bytes []byte) error {
func (m *Map[K, V]) UnmarshalJSON(bytes []byte) error {
return m.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (m *Map) MarshalJSON() ([]byte, error) {
func (m *Map[K, V]) MarshalJSON() ([]byte, error) {
return m.ToJSON()
}

@ -18,116 +18,101 @@
package treebidimap
import (
"cmp"
"fmt"
"github.com/emirpasic/gods/maps"
"github.com/emirpasic/gods/trees/redblacktree"
"github.com/emirpasic/gods/utils"
"strings"
"github.com/emirpasic/gods/v2/maps"
"github.com/emirpasic/gods/v2/trees/redblacktree"
"github.com/emirpasic/gods/v2/utils"
)
// Assert Map implementation
var _ maps.BidiMap = (*Map)(nil)
var _ maps.BidiMap[string, int] = (*Map[string, int])(nil)
// Map holds the elements in two red-black trees.
type Map struct {
forwardMap redblacktree.Tree
inverseMap redblacktree.Tree
keyComparator utils.Comparator
valueComparator utils.Comparator
type Map[K, V comparable] struct {
forwardMap redblacktree.Tree[K, V]
inverseMap redblacktree.Tree[V, K]
}
type data struct {
key interface{}
value interface{}
// New instantiates a bidirectional map.
func New[K, V cmp.Ordered]() *Map[K, V] {
return &Map[K, V]{
forwardMap: *redblacktree.New[K, V](),
inverseMap: *redblacktree.New[V, K](),
}
}
// NewWith instantiates a bidirectional map.
func NewWith(keyComparator utils.Comparator, valueComparator utils.Comparator) *Map {
return &Map{
forwardMap: *redblacktree.NewWith(keyComparator),
inverseMap: *redblacktree.NewWith(valueComparator),
keyComparator: keyComparator,
valueComparator: valueComparator,
func NewWith[K, V comparable](keyComparator utils.Comparator[K], valueComparator utils.Comparator[V]) *Map[K, V] {
return &Map[K, V]{
forwardMap: *redblacktree.NewWith[K, V](keyComparator),
inverseMap: *redblacktree.NewWith[V, K](valueComparator),
}
}
// NewWithIntComparators instantiates a bidirectional map with the IntComparator for key and value, i.e. keys and values are of type int.
func NewWithIntComparators() *Map {
return NewWith(utils.IntComparator, utils.IntComparator)
}
// NewWithStringComparators instantiates a bidirectional map with the StringComparator for key and value, i.e. keys and values are of type string.
func NewWithStringComparators() *Map {
return NewWith(utils.StringComparator, utils.StringComparator)
}
// Put inserts element into the map.
func (m *Map) Put(key interface{}, value interface{}) {
if d, ok := m.forwardMap.Get(key); ok {
m.inverseMap.Remove(d.(*data).value)
func (m *Map[K, V]) Put(key K, value V) {
if v, ok := m.forwardMap.Get(key); ok {
m.inverseMap.Remove(v)
}
if d, ok := m.inverseMap.Get(value); ok {
m.forwardMap.Remove(d.(*data).key)
if k, ok := m.inverseMap.Get(value); ok {
m.forwardMap.Remove(k)
}
d := &data{key: key, value: value}
m.forwardMap.Put(key, d)
m.inverseMap.Put(value, d)
m.forwardMap.Put(key, value)
m.inverseMap.Put(value, key)
}
// Get searches the element 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) {
if d, ok := m.forwardMap.Get(key); ok {
return d.(*data).value, true
}
return nil, false
func (m *Map[K, V]) Get(key K) (value V, found bool) {
return m.forwardMap.Get(key)
}
// GetKey searches the element in the map by value and returns its key or nil if value is not found in map.
// Second return parameter is true if value was found, otherwise false.
func (m *Map) GetKey(value interface{}) (key interface{}, found bool) {
if d, ok := m.inverseMap.Get(value); ok {
return d.(*data).key, true
}
return nil, false
func (m *Map[K, V]) GetKey(value V) (key K, found bool) {
return m.inverseMap.Get(value)
}
// Remove removes the element from the map by key.
func (m *Map) Remove(key interface{}) {
if d, found := m.forwardMap.Get(key); found {
func (m *Map[K, V]) Remove(key K) {
if v, found := m.forwardMap.Get(key); found {
m.forwardMap.Remove(key)
m.inverseMap.Remove(d.(*data).value)
m.inverseMap.Remove(v)
}
}
// Empty returns true if map does not contain any elements
func (m *Map) Empty() bool {
func (m *Map[K, V]) Empty() bool {
return m.Size() == 0
}
// Size returns number of elements in the map.
func (m *Map) Size() int {
func (m *Map[K, V]) Size() int {
return m.forwardMap.Size()
}
// Keys returns all keys (ordered).
func (m *Map) Keys() []interface{} {
func (m *Map[K, V]) Keys() []K {
return m.forwardMap.Keys()
}
// Values returns all values (ordered).
func (m *Map) Values() []interface{} {
func (m *Map[K, V]) Values() []V {
return m.inverseMap.Keys()
}
// Clear removes all elements from the map.
func (m *Map) Clear() {
func (m *Map[K, V]) Clear() {
m.forwardMap.Clear()
m.inverseMap.Clear()
}
// String returns a string representation of container
func (m *Map) String() string {
func (m *Map[K, V]) String() string {
str := "TreeBidiMap\nmap["
it := m.Iterator()
for it.Next() {

@ -6,14 +6,14 @@ package treebidimap
import (
"encoding/json"
"fmt"
"github.com/emirpasic/gods/utils"
"strings"
"testing"
"github.com/emirpasic/gods/v2/testutils"
)
func TestMapPut(t *testing.T) {
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -26,12 +26,8 @@ func TestMapPut(t *testing.T) {
if actualValue := m.Size(); actualValue != 7 {
t.Errorf("Got %v expected %v", actualValue, 7)
}
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d", "e", "f", "g"}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, m.Keys(), []int{1, 2, 3, 4, 5, 6, 7})
testutils.SameElements(t, m.Values(), []string{"a", "b", "c", "d", "e", "f", "g"})
// key,expectedValue,expectedFound
tests1 := [][]interface{}{
@ -42,12 +38,12 @@ func TestMapPut(t *testing.T) {
{5, "e", true},
{6, "f", true},
{7, "g", true},
{8, nil, false},
{8, "", false},
}
for _, test := range tests1 {
// retrievals
actualValue, actualFound := m.Get(test[0])
actualValue, actualFound := m.Get(test[0].(int))
if actualValue != test[1] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[1])
}
@ -55,7 +51,7 @@ func TestMapPut(t *testing.T) {
}
func TestMapRemove(t *testing.T) {
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -71,13 +67,9 @@ func TestMapRemove(t *testing.T) {
m.Remove(8)
m.Remove(5)
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, m.Keys(), []int{1, 2, 3, 4})
testutils.SameElements(t, m.Values(), []string{"a", "b", "c", "d"})
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d"}; !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)
}
@ -87,14 +79,14 @@ func TestMapRemove(t *testing.T) {
{2, "b", true},
{3, "c", true},
{4, "d", true},
{5, nil, false},
{6, nil, false},
{7, nil, false},
{8, nil, false},
{5, "", false},
{6, "", false},
{7, "", false},
{8, "", false},
}
for _, test := range tests2 {
actualValue, actualFound := m.Get(test[0])
actualValue, actualFound := m.Get(test[0].(int))
if actualValue != test[1] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[1])
}
@ -107,12 +99,8 @@ func TestMapRemove(t *testing.T) {
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)
}
testutils.SameElements(t, m.Keys(), nil)
testutils.SameElements(t, m.Values(), nil)
if actualValue := m.Size(); actualValue != 0 {
t.Errorf("Got %v expected %v", actualValue, 0)
}
@ -122,7 +110,7 @@ func TestMapRemove(t *testing.T) {
}
func TestMapGetKey(t *testing.T) {
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -141,12 +129,12 @@ func TestMapGetKey(t *testing.T) {
{5, "e", true},
{6, "f", true},
{7, "g", true},
{nil, "x", false},
{0, "x", false},
}
for _, test := range tests1 {
// retrievals
actualValue, actualFound := m.GetKey(test[1])
actualValue, actualFound := m.GetKey(test[1].(string))
if actualValue != test[0] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[0])
}
@ -173,12 +161,12 @@ func sameElements(a []interface{}, b []interface{}) bool {
}
func TestMapEach(t *testing.T) {
m := NewWith(utils.StringComparator, utils.IntComparator)
m := New[string, int]()
m.Put("c", 3)
m.Put("a", 1)
m.Put("b", 2)
count := 0
m.Each(func(key interface{}, value interface{}) {
m.Each(func(key string, value int) {
count++
if actualValue, expectedValue := count, value; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -203,12 +191,12 @@ func TestMapEach(t *testing.T) {
}
func TestMapMap(t *testing.T) {
m := NewWith(utils.StringComparator, utils.IntComparator)
m := New[string, int]()
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)
mappedMap := m.Map(func(key1 string, value1 int) (key2 string, value2 int) {
return key1, value1 * value1
})
if actualValue, _ := mappedMap.Get("a"); actualValue != 1 {
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
@ -225,12 +213,12 @@ func TestMapMap(t *testing.T) {
}
func TestMapSelect(t *testing.T) {
m := NewWith(utils.StringComparator, utils.IntComparator)
m := New[string, int]()
m.Put("c", 3)
m.Put("a", 1)
m.Put("b", 2)
selectedMap := m.Select(func(key interface{}, value interface{}) bool {
return key.(string) >= "a" && key.(string) <= "b"
selectedMap := m.Select(func(key string, value int) bool {
return key >= "a" && key <= "b"
})
if actualValue, _ := selectedMap.Get("a"); actualValue != 1 {
t.Errorf("Got %v expected %v", actualValue, "value: a")
@ -244,18 +232,18 @@ func TestMapSelect(t *testing.T) {
}
func TestMapAny(t *testing.T) {
m := NewWith(utils.StringComparator, utils.IntComparator)
m := New[string, int]()
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
any := m.Any(func(key string, value int) bool {
return value == 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
any = m.Any(func(key string, value int) bool {
return value == 4
})
if any != false {
t.Errorf("Got %v expected %v", any, false)
@ -263,18 +251,18 @@ func TestMapAny(t *testing.T) {
}
func TestMapAll(t *testing.T) {
m := NewWith(utils.StringComparator, utils.IntComparator)
m := New[string, int]()
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"
all := m.All(func(key string, value int) bool {
return key >= "a" && key <= "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"
all = m.All(func(key string, value int) bool {
return key >= "a" && key <= "b"
})
if all != false {
t.Errorf("Got %v expected %v", all, false)
@ -282,38 +270,38 @@ func TestMapAll(t *testing.T) {
}
func TestMapFind(t *testing.T) {
m := NewWith(utils.StringComparator, utils.IntComparator)
m := New[string, int]()
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"
foundKey, foundValue := m.Find(func(key string, value int) bool {
return key == "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"
foundKey, foundValue = m.Find(func(key string, value int) bool {
return key == "x"
})
if foundKey != nil || foundValue != nil {
if foundKey != "" || foundValue != 0 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundKey, nil, nil)
}
}
func TestMapChaining(t *testing.T) {
m := NewWith(utils.StringComparator, utils.IntComparator)
m := New[string, int]()
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)
chainedMap := m.Select(func(key string, value int) bool {
return value > 1
}).Map(func(key string, value int) (string, int) {
return key + key, value * value
})
if actualValue := chainedMap.Size(); actualValue != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if actualValue, found := chainedMap.Get("aa"); actualValue != nil || found {
if actualValue, found := chainedMap.Get("aa"); actualValue != 0 || found {
t.Errorf("Got %v expected %v", actualValue, nil)
}
if actualValue, found := chainedMap.Get("bb"); actualValue != 4 || !found {
@ -325,7 +313,7 @@ func TestMapChaining(t *testing.T) {
}
func TestMapIteratorNextOnEmpty(t *testing.T) {
m := NewWithStringComparators()
m := New[string, string]()
it := m.Iterator()
it = m.Iterator()
for it.Next() {
@ -334,7 +322,7 @@ func TestMapIteratorNextOnEmpty(t *testing.T) {
}
func TestMapIteratorPrevOnEmpty(t *testing.T) {
m := NewWithStringComparators()
m := New[string, string]()
it := m.Iterator()
it = m.Iterator()
for it.Prev() {
@ -343,7 +331,7 @@ func TestMapIteratorPrevOnEmpty(t *testing.T) {
}
func TestMapIteratorNext(t *testing.T) {
m := NewWith(utils.StringComparator, utils.IntComparator)
m := New[string, int]()
m.Put("c", 3)
m.Put("a", 1)
m.Put("b", 2)
@ -380,7 +368,7 @@ func TestMapIteratorNext(t *testing.T) {
}
func TestMapIteratorPrev(t *testing.T) {
m := NewWith(utils.StringComparator, utils.IntComparator)
m := New[string, int]()
m.Put("c", 3)
m.Put("a", 1)
m.Put("b", 2)
@ -419,7 +407,7 @@ func TestMapIteratorPrev(t *testing.T) {
}
func TestMapIteratorBegin(t *testing.T) {
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
it := m.Iterator()
it.Begin()
m.Put(3, "c")
@ -435,7 +423,7 @@ func TestMapIteratorBegin(t *testing.T) {
}
func TestMapIteratorEnd(t *testing.T) {
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
it := m.Iterator()
m.Put(3, "c")
m.Put(1, "a")
@ -448,7 +436,7 @@ func TestMapIteratorEnd(t *testing.T) {
}
func TestMapIteratorFirst(t *testing.T) {
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
m.Put(3, "c")
m.Put(1, "a")
m.Put(2, "b")
@ -462,7 +450,7 @@ func TestMapIteratorFirst(t *testing.T) {
}
func TestMapIteratorLast(t *testing.T) {
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
m.Put(3, "c")
m.Put(1, "a")
m.Put(2, "b")
@ -477,13 +465,13 @@ func TestMapIteratorLast(t *testing.T) {
func TestMapIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index interface{}, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// NextTo (empty)
{
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
it := m.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty map")
@ -492,7 +480,7 @@ func TestMapIteratorNextTo(t *testing.T) {
// NextTo (not found)
{
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
m.Put(0, "xx")
m.Put(1, "yy")
it := m.Iterator()
@ -503,7 +491,7 @@ func TestMapIteratorNextTo(t *testing.T) {
// NextTo (found)
{
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
m.Put(0, "aa")
m.Put(1, "bb")
m.Put(2, "cc")
@ -512,13 +500,13 @@ func TestMapIteratorNextTo(t *testing.T) {
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty map")
}
if index, value := it.Key(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Key(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Key(), it.Value(); index != 2 || value.(string) != "cc" {
if index, value := it.Key(), it.Value(); index != 2 || value != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
@ -529,13 +517,13 @@ func TestMapIteratorNextTo(t *testing.T) {
func TestMapIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index interface{}, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// PrevTo (empty)
{
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
it := m.Iterator()
it.End()
for it.PrevTo(seek) {
@ -545,7 +533,7 @@ func TestMapIteratorPrevTo(t *testing.T) {
// PrevTo (not found)
{
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
m.Put(0, "xx")
m.Put(1, "yy")
it := m.Iterator()
@ -557,7 +545,7 @@ func TestMapIteratorPrevTo(t *testing.T) {
// PrevTo (found)
{
m := NewWith(utils.IntComparator, utils.StringComparator)
m := New[int, string]()
m.Put(0, "aa")
m.Put(1, "bb")
m.Put(2, "cc")
@ -566,13 +554,13 @@ func TestMapIteratorPrevTo(t *testing.T) {
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty map")
}
if index, value := it.Key(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Key(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Key(), it.Value(); index != 0 || value.(string) != "aa" {
if index, value := it.Key(), it.Value(); index != 0 || value != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
@ -583,30 +571,36 @@ func TestMapIteratorPrevTo(t *testing.T) {
func TestMapSerialization(t *testing.T) {
for i := 0; i < 10; i++ {
original := NewWith(utils.StringComparator, utils.StringComparator)
original := New[string, string]()
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 := NewWith(utils.StringComparator, utils.StringComparator)
deserialized := New[string, string]()
err = deserialized.FromJSON(serialized)
if err != nil {
t.Errorf("Got error %v", err)
}
assertSerialization(deserialized, "C", t)
if original.Size() != deserialized.Size() {
t.Errorf("Got map of size %d, expected %d", original.Size(), deserialized.Size())
}
original.Each(func(key string, expected string) {
actual, ok := deserialized.Get(key)
if !ok || actual != expected {
t.Errorf("Did not find expected value %v for key %v in deserialied map (got %q)", expected, key, actual)
}
})
}
m := NewWith(utils.StringComparator, utils.Float64Comparator)
m := New[string, float64]()
m.Put("a", 1.0)
m.Put("b", 2.0)
m.Put("c", 3.0)
@ -623,37 +617,14 @@ func TestMapSerialization(t *testing.T) {
}
func TestMapString(t *testing.T) {
c := NewWithStringComparators()
c := New[string, string]()
c.Put("a", "a")
if !strings.HasPrefix(c.String(), "TreeBidiMap") {
t.Errorf("String should start with container name")
}
}
//noinspection GoBoolExpressions
func assertSerialization(m *Map, txt string, t *testing.T) {
if actualValue := m.Keys(); false ||
actualValue[0].(string) != "a" ||
actualValue[1].(string) != "b" ||
actualValue[2].(string) != "c" ||
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[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Get(n)
@ -661,7 +632,7 @@ func benchmarkGet(b *testing.B, m *Map, size int) {
}
}
func benchmarkPut(b *testing.B, m *Map, size int) {
func benchmarkPut(b *testing.B, m *Map[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Put(n, n)
@ -669,7 +640,7 @@ func benchmarkPut(b *testing.B, m *Map, size int) {
}
}
func benchmarkRemove(b *testing.B, m *Map, size int) {
func benchmarkRemove(b *testing.B, m *Map[int, int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Remove(n)
@ -680,7 +651,7 @@ func benchmarkRemove(b *testing.B, m *Map, size int) {
func BenchmarkTreeBidiMapGet100(b *testing.B) {
b.StopTimer()
size := 100
m := NewWithIntComparators()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -691,7 +662,7 @@ func BenchmarkTreeBidiMapGet100(b *testing.B) {
func BenchmarkTreeBidiMapGet1000(b *testing.B) {
b.StopTimer()
size := 1000
m := NewWithIntComparators()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -702,7 +673,7 @@ func BenchmarkTreeBidiMapGet1000(b *testing.B) {
func BenchmarkTreeBidiMapGet10000(b *testing.B) {
b.StopTimer()
size := 10000
m := NewWithIntComparators()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -713,7 +684,7 @@ func BenchmarkTreeBidiMapGet10000(b *testing.B) {
func BenchmarkTreeBidiMapGet100000(b *testing.B) {
b.StopTimer()
size := 100000
m := NewWithIntComparators()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -724,7 +695,7 @@ func BenchmarkTreeBidiMapGet100000(b *testing.B) {
func BenchmarkTreeBidiMapPut100(b *testing.B) {
b.StopTimer()
size := 100
m := NewWithIntComparators()
m := New[int, int]()
b.StartTimer()
benchmarkPut(b, m, size)
}
@ -732,7 +703,7 @@ func BenchmarkTreeBidiMapPut100(b *testing.B) {
func BenchmarkTreeBidiMapPut1000(b *testing.B) {
b.StopTimer()
size := 1000
m := NewWithIntComparators()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -743,7 +714,7 @@ func BenchmarkTreeBidiMapPut1000(b *testing.B) {
func BenchmarkTreeBidiMapPut10000(b *testing.B) {
b.StopTimer()
size := 10000
m := NewWithIntComparators()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -754,7 +725,7 @@ func BenchmarkTreeBidiMapPut10000(b *testing.B) {
func BenchmarkTreeBidiMapPut100000(b *testing.B) {
b.StopTimer()
size := 100000
m := NewWithIntComparators()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -765,7 +736,7 @@ func BenchmarkTreeBidiMapPut100000(b *testing.B) {
func BenchmarkTreeBidiMapRemove100(b *testing.B) {
b.StopTimer()
size := 100
m := NewWithIntComparators()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -776,7 +747,7 @@ func BenchmarkTreeBidiMapRemove100(b *testing.B) {
func BenchmarkTreeBidiMapRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
m := NewWithIntComparators()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -787,7 +758,7 @@ func BenchmarkTreeBidiMapRemove1000(b *testing.B) {
func BenchmarkTreeBidiMapRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
m := NewWithIntComparators()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}
@ -798,7 +769,7 @@ func BenchmarkTreeBidiMapRemove10000(b *testing.B) {
func BenchmarkTreeBidiMapRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
m := NewWithIntComparators()
m := New[int, int]()
for n := 0; n < size; n++ {
m.Put(n, n)
}

@ -5,15 +5,15 @@
package treemap
import (
"github.com/emirpasic/gods/containers"
rbt "github.com/emirpasic/gods/trees/redblacktree"
"github.com/emirpasic/gods/v2/containers"
rbt "github.com/emirpasic/gods/v2/trees/redblacktree"
)
// Assert Enumerable implementation
var _ containers.EnumerableWithKey = (*Map)(nil)
var _ containers.EnumerableWithKey[string, int] = (*Map[string, int])(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{})) {
func (m *Map[K, V]) Each(f func(key K, value V)) {
iterator := m.Iterator()
for iterator.Next() {
f(iterator.Key(), iterator.Value())
@ -22,8 +22,8 @@ func (m *Map) Each(f func(key interface{}, value interface{})) {
// 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 := &Map{tree: rbt.NewWith(m.tree.Comparator)}
func (m *Map[K, V]) Map(f func(key1 K, value1 V) (K, V)) *Map[K, V] {
newMap := &Map[K, V]{tree: rbt.NewWith[K, V](m.tree.Comparator)}
iterator := m.Iterator()
for iterator.Next() {
key2, value2 := f(iterator.Key(), iterator.Value())
@ -33,8 +33,8 @@ func (m *Map) Map(f func(key1 interface{}, value1 interface{}) (interface{}, int
}
// 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 := &Map{tree: rbt.NewWith(m.tree.Comparator)}
func (m *Map[K, V]) Select(f func(key K, value V) bool) *Map[K, V] {
newMap := &Map[K, V]{tree: rbt.NewWith[K, V](m.tree.Comparator)}
iterator := m.Iterator()
for iterator.Next() {
if f(iterator.Key(), iterator.Value()) {
@ -46,7 +46,7 @@ func (m *Map) Select(f func(key interface{}, value interface{}) bool) *Map {
// 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 {
func (m *Map[K, V]) Any(f func(key K, value V) bool) bool {
iterator := m.Iterator()
for iterator.Next() {
if f(iterator.Key(), iterator.Value()) {
@ -58,7 +58,7 @@ func (m *Map) Any(f func(key interface{}, value interface{}) bool) bool {
// 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 {
func (m *Map[K, V]) All(f func(key K, value V) bool) bool {
iterator := m.Iterator()
for iterator.Next() {
if !f(iterator.Key(), iterator.Value()) {
@ -71,12 +71,12 @@ func (m *Map) All(f func(key interface{}, value interface{}) bool) bool {
// 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{}) {
func (m *Map[K, V]) Find(f func(key K, value V) bool) (k K, v V) {
iterator := m.Iterator()
for iterator.Next() {
if f(iterator.Key(), iterator.Value()) {
return iterator.Key(), iterator.Value()
}
}
return nil, nil
return k, v
}

@ -5,73 +5,73 @@
package treemap
import (
"github.com/emirpasic/gods/containers"
rbt "github.com/emirpasic/gods/trees/redblacktree"
"github.com/emirpasic/gods/v2/containers"
rbt "github.com/emirpasic/gods/v2/trees/redblacktree"
)
// Assert Iterator implementation
var _ containers.ReverseIteratorWithKey = (*Iterator)(nil)
var _ containers.ReverseIteratorWithKey[string, int] = (*Iterator[string, int])(nil)
// Iterator holding the iterator's state
type Iterator struct {
iterator rbt.Iterator
type Iterator[K comparable, V any] struct {
iterator *rbt.Iterator[K, V]
}
// Iterator returns a stateful iterator whose elements are key/value pairs.
func (m *Map) Iterator() Iterator {
return Iterator{iterator: m.tree.Iterator()}
func (m *Map[K, V]) Iterator() *Iterator[K, V] {
return &Iterator[K, V]{iterator: m.tree.Iterator()}
}
// 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 {
func (iterator *Iterator[K, V]) 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 {
func (iterator *Iterator[K, V]) 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{} {
func (iterator *Iterator[K, V]) Value() V {
return iterator.iterator.Value()
}
// Key returns the current element's key.
// Does not modify the state of the iterator.
func (iterator *Iterator) Key() interface{} {
func (iterator *Iterator[K, V]) Key() K {
return iterator.iterator.Key()
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
func (iterator *Iterator[K, V]) 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() {
func (iterator *Iterator[K, V]) 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 {
func (iterator *Iterator[K, V]) 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 {
func (iterator *Iterator[K, V]) Last() bool {
return iterator.iterator.Last()
}
@ -79,7 +79,7 @@ func (iterator *Iterator) Last() bool {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(key interface{}, value interface{}) bool) bool {
func (iterator *Iterator[K, V]) NextTo(f func(key K, value V) bool) bool {
for iterator.Next() {
key, value := iterator.Key(), iterator.Value()
if f(key, value) {
@ -93,7 +93,7 @@ func (iterator *Iterator) NextTo(f func(key interface{}, value interface{}) bool
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(key interface{}, value interface{}) bool) bool {
func (iterator *Iterator[K, V]) PrevTo(f func(key K, value V) bool) bool {
for iterator.Prev() {
key, value := iterator.Key(), iterator.Value()
if f(key, value) {

@ -5,29 +5,29 @@
package treemap
import (
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Map)(nil)
var _ containers.JSONDeserializer = (*Map)(nil)
var _ containers.JSONSerializer = (*Map[string, int])(nil)
var _ containers.JSONDeserializer = (*Map[string, int])(nil)
// ToJSON outputs the JSON representation of the map.
func (m *Map) ToJSON() ([]byte, error) {
func (m *Map[K, V]) ToJSON() ([]byte, error) {
return m.tree.ToJSON()
}
// FromJSON populates the map from the input JSON representation.
func (m *Map) FromJSON(data []byte) error {
func (m *Map[K, V]) FromJSON(data []byte) error {
return m.tree.FromJSON(data)
}
// UnmarshalJSON @implements json.Unmarshaler
func (m *Map) UnmarshalJSON(bytes []byte) error {
func (m *Map[K, V]) UnmarshalJSON(bytes []byte) error {
return m.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (m *Map) MarshalJSON() ([]byte, error) {
func (m *Map[K, V]) MarshalJSON() ([]byte, error) {
return m.ToJSON()
}

@ -12,96 +12,93 @@
package treemap
import (
"cmp"
"fmt"
"github.com/emirpasic/gods/maps"
rbt "github.com/emirpasic/gods/trees/redblacktree"
"github.com/emirpasic/gods/utils"
"strings"
"github.com/emirpasic/gods/v2/maps"
rbt "github.com/emirpasic/gods/v2/trees/redblacktree"
"github.com/emirpasic/gods/v2/utils"
)
// Assert Map implementation
var _ maps.Map = (*Map)(nil)
var _ maps.Map[string, int] = (*Map[string, int])(nil)
// Map holds the elements in a red-black tree
type Map struct {
tree *rbt.Tree
type Map[K comparable, V any] struct {
tree *rbt.Tree[K, V]
}
// NewWith instantiates a tree map with the custom comparator.
func NewWith(comparator utils.Comparator) *Map {
return &Map{tree: rbt.NewWith(comparator)}
// New instantiates a tree map with the built-in comparator for K
func New[K cmp.Ordered, V any]() *Map[K, V] {
return &Map[K, V]{tree: rbt.New[K, V]()}
}
// NewWithIntComparator instantiates a tree map with the IntComparator, i.e. keys are of type int.
func NewWithIntComparator() *Map {
return &Map{tree: rbt.NewWithIntComparator()}
}
// NewWithStringComparator instantiates a tree map with the StringComparator, i.e. keys are of type string.
func NewWithStringComparator() *Map {
return &Map{tree: rbt.NewWithStringComparator()}
// NewWith instantiates a tree map with the custom comparator.
func NewWith[K comparable, V any](comparator utils.Comparator[K]) *Map[K, V] {
return &Map[K, V]{tree: rbt.NewWith[K, V](comparator)}
}
// 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{}) {
func (m *Map[K, V]) Put(key K, value V) {
m.tree.Put(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) {
func (m *Map[K, V]) Get(key K) (value V, found bool) {
return m.tree.Get(key)
}
// 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{}) {
func (m *Map[K, V]) Remove(key K) {
m.tree.Remove(key)
}
// Empty returns true if map does not contain any elements
func (m *Map) Empty() bool {
func (m *Map[K, V]) Empty() bool {
return m.tree.Empty()
}
// Size returns number of elements in the map.
func (m *Map) Size() int {
func (m *Map[K, V]) Size() int {
return m.tree.Size()
}
// Keys returns all keys in-order
func (m *Map) Keys() []interface{} {
func (m *Map[K, V]) Keys() []K {
return m.tree.Keys()
}
// Values returns all values in-order based on the key.
func (m *Map) Values() []interface{} {
func (m *Map[K, V]) Values() []V {
return m.tree.Values()
}
// Clear removes all elements from the map.
func (m *Map) Clear() {
func (m *Map[K, V]) Clear() {
m.tree.Clear()
}
// Min returns the minimum key and its value from the tree map.
// Returns nil, nil if map is empty.
func (m *Map) Min() (key interface{}, value interface{}) {
// Returns 0-value, 0-value, false if map is empty.
func (m *Map[K, V]) Min() (key K, value V, ok bool) {
if node := m.tree.Left(); node != nil {
return node.Key, node.Value
return node.Key, node.Value, true
}
return nil, nil
return key, value, false
}
// Max returns the maximum key and its value from the tree map.
// Returns nil, nil if map is empty.
func (m *Map) Max() (key interface{}, value interface{}) {
// Returns 0-value, 0-value, false if map is empty.
func (m *Map[K, V]) Max() (key K, value V, ok bool) {
if node := m.tree.Right(); node != nil {
return node.Key, node.Value
return node.Key, node.Value, true
}
return nil, nil
return key, value, false
}
// Floor finds the floor key-value pair for the input key.
@ -113,12 +110,12 @@ func (m *Map) Max() (key interface{}, value interface{}) {
// all keys in the map are larger than the given key.
//
// Key should adhere to the comparator's type assertion, otherwise method panics.
func (m *Map) Floor(key interface{}) (foundKey interface{}, foundValue interface{}) {
func (m *Map[K, V]) Floor(key K) (foundKey K, foundValue V, ok bool) {
node, found := m.tree.Floor(key)
if found {
return node.Key, node.Value
return node.Key, node.Value, true
}
return nil, nil
return foundKey, foundValue, false
}
// Ceiling finds the ceiling key-value pair for the input key.
@ -130,16 +127,16 @@ func (m *Map) Floor(key interface{}) (foundKey interface{}, foundValue interface
// all keys in the map are smaller than the given key.
//
// Key should adhere to the comparator's type assertion, otherwise method panics.
func (m *Map) Ceiling(key interface{}) (foundKey interface{}, foundValue interface{}) {
func (m *Map[K, V]) Ceiling(key K) (foundKey K, foundValue V, ok bool) {
node, found := m.tree.Ceiling(key)
if found {
return node.Key, node.Value
return node.Key, node.Value, true
}
return nil, nil
return foundKey, foundValue, false
}
// String returns a string representation of container
func (m *Map) String() string {
func (m *Map[K, V]) String() string {
str := "TreeMap\nmap["
it := m.Iterator()
for it.Next() {

@ -6,14 +6,14 @@ package treemap
import (
"encoding/json"
"fmt"
"github.com/emirpasic/gods/utils"
"strings"
"testing"
"github.com/emirpasic/gods/v2/testutils"
)
func TestMapPut(t *testing.T) {
m := NewWith(utils.IntComparator)
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -26,12 +26,8 @@ func TestMapPut(t *testing.T) {
if actualValue := m.Size(); actualValue != 7 {
t.Errorf("Got %v expected %v", actualValue, 7)
}
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4, 5, 6, 7}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d", "e", "f", "g"}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, m.Keys(), []int{1, 2, 3, 4, 5, 6, 7})
testutils.SameElements(t, m.Values(), []string{"a", "b", "c", "d", "e", "f", "g"})
// key,expectedValue,expectedFound
tests1 := [][]interface{}{
@ -42,12 +38,12 @@ func TestMapPut(t *testing.T) {
{5, "e", true},
{6, "f", true},
{7, "g", true},
{8, nil, false},
{8, "", false},
}
for _, test := range tests1 {
// retrievals
actualValue, actualFound := m.Get(test[0])
actualValue, actualFound := m.Get(test[0].(int))
if actualValue != test[1] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[1])
}
@ -55,10 +51,10 @@ func TestMapPut(t *testing.T) {
}
func TestMapMin(t *testing.T) {
m := NewWithIntComparator()
m := New[int, string]()
if k, v := m.Min(); k != nil || v != nil {
t.Errorf("Got %v->%v expected %v->%v", k, v, nil, nil)
if k, v, ok := m.Min(); k != 0 || v != "" || ok {
t.Errorf("Got %v->%v->%v expected %v->%v-%v", k, v, ok, 0, "", false)
}
m.Put(5, "e")
@ -70,21 +66,24 @@ func TestMapMin(t *testing.T) {
m.Put(2, "b")
m.Put(1, "a") //overwrite
actualKey, actualValue := m.Min()
expectedKey, expectedValue := 1, "a"
actualKey, actualValue, actualOk := m.Min()
expectedKey, expectedValue, expectedOk := 1, "a", true
if actualKey != expectedKey {
t.Errorf("Got %v expected %v", actualKey, expectedKey)
}
if actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualOk != expectedOk {
t.Errorf("Got %v expected %v", actualOk, expectedOk)
}
}
func TestMapMax(t *testing.T) {
m := NewWithIntComparator()
m := New[int, string]()
if k, v := m.Max(); k != nil || v != nil {
t.Errorf("Got %v->%v expected %v->%v", k, v, nil, nil)
if k, v, ok := m.Max(); k != 0 || v != "" || ok {
t.Errorf("Got %v->%v->%v expected %v->%v-%v", k, v, ok, 0, "", false)
}
m.Put(5, "e")
@ -96,18 +95,21 @@ func TestMapMax(t *testing.T) {
m.Put(2, "b")
m.Put(1, "a") //overwrite
actualKey, actualValue := m.Max()
expectedKey, expectedValue := 7, "g"
actualKey, actualValue, actualOk := m.Max()
expectedKey, expectedValue, expectedOk := 7, "g", true
if actualKey != expectedKey {
t.Errorf("Got %v expected %v", actualKey, expectedKey)
}
if actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualOk != expectedOk {
t.Errorf("Got %v expected %v", actualOk, expectedOk)
}
}
func TestMapClear(t *testing.T) {
m := NewWithIntComparator()
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -122,7 +124,7 @@ func TestMapClear(t *testing.T) {
}
func TestMapRemove(t *testing.T) {
m := NewWithIntComparator()
m := New[int, string]()
m.Put(5, "e")
m.Put(6, "f")
m.Put(7, "g")
@ -138,13 +140,9 @@ func TestMapRemove(t *testing.T) {
m.Remove(8)
m.Remove(5)
if actualValue, expectedValue := m.Keys(), []interface{}{1, 2, 3, 4}; !sameElements(actualValue, expectedValue) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, m.Keys(), []int{1, 2, 3, 4})
testutils.SameElements(t, m.Values(), []string{"a", "b", "c", "d"})
if actualValue, expectedValue := m.Values(), []interface{}{"a", "b", "c", "d"}; !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)
}
@ -154,14 +152,14 @@ func TestMapRemove(t *testing.T) {
{2, "b", true},
{3, "c", true},
{4, "d", true},
{5, nil, false},
{6, nil, false},
{7, nil, false},
{8, nil, false},
{5, "", false},
{6, "", false},
{7, "", false},
{8, "", false},
}
for _, test := range tests2 {
actualValue, actualFound := m.Get(test[0])
actualValue, actualFound := m.Get(test[0].(int))
if actualValue != test[1] || actualFound != test[2] {
t.Errorf("Got %v expected %v", actualValue, test[1])
}
@ -174,12 +172,8 @@ func TestMapRemove(t *testing.T) {
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)
}
testutils.SameElements(t, m.Keys(), nil)
testutils.SameElements(t, m.Values(), nil)
if actualValue := m.Size(); actualValue != 0 {
t.Errorf("Got %v expected %v", actualValue, 0)
}
@ -189,15 +183,15 @@ func TestMapRemove(t *testing.T) {
}
func TestMapFloor(t *testing.T) {
m := NewWithIntComparator()
m := New[int, string]()
m.Put(7, "g")
m.Put(3, "c")
m.Put(1, "a")
// key,expectedKey,expectedValue,expectedFound
tests1 := [][]interface{}{
{-1, nil, nil, false},
{0, nil, nil, false},
{-1, 0, "", false},
{0, 0, "", false},
{1, 1, "a", true},
{2, 1, "a", true},
{3, 3, "c", true},
@ -208,16 +202,15 @@ func TestMapFloor(t *testing.T) {
for _, test := range tests1 {
// retrievals
actualKey, actualValue := m.Floor(test[0])
actualFound := actualKey != nil && actualValue != nil
if actualKey != test[1] || actualValue != test[2] || actualFound != test[3] {
t.Errorf("Got %v, %v, %v, expected %v, %v, %v", actualKey, actualValue, actualFound, test[1], test[2], test[3])
actualKey, actualValue, actualOk := m.Floor(test[0].(int))
if actualKey != test[1] || actualValue != test[2] || actualOk != test[3] {
t.Errorf("Got %v, %v, %v, expected %v, %v, %v", actualKey, actualValue, actualOk, test[1], test[2], test[3])
}
}
}
func TestMapCeiling(t *testing.T) {
m := NewWithIntComparator()
m := New[int, string]()
m.Put(7, "g")
m.Put(3, "c")
m.Put(1, "a")
@ -231,45 +224,25 @@ func TestMapCeiling(t *testing.T) {
{3, 3, "c", true},
{4, 7, "g", true},
{7, 7, "g", true},
{8, nil, nil, false},
{8, 0, "", false},
}
for _, test := range tests1 {
// retrievals
actualKey, actualValue := m.Ceiling(test[0])
actualFound := actualKey != nil && actualValue != nil
if actualKey != test[1] || actualValue != test[2] || actualFound != test[3] {
t.Errorf("Got %v, %v, %v, expected %v, %v, %v", actualKey, actualValue, actualFound, test[1], test[2], test[3])
}
}
}
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
actualKey, actualValue, actualOk := m.Ceiling(test[0].(int))
if actualKey != test[1] || actualValue != test[2] || actualOk != test[3] {
t.Errorf("Got %v, %v, %v, expected %v, %v, %v", actualKey, actualValue, actualOk, test[1], test[2], test[3])
}
}
return true
}
func TestMapEach(t *testing.T) {
m := NewWithStringComparator()
m := New[string, int]()
m.Put("c", 3)
m.Put("a", 1)
m.Put("b", 2)
count := 0
m.Each(func(key interface{}, value interface{}) {
m.Each(func(key string, value int) {
count++
if actualValue, expectedValue := count, value; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -294,12 +267,12 @@ func TestMapEach(t *testing.T) {
}
func TestMapMap(t *testing.T) {
m := NewWithStringComparator()
m := New[string, int]()
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)
mappedMap := m.Map(func(key1 string, value1 int) (key2 string, value2 int) {
return key1, value1 * value1
})
if actualValue, _ := mappedMap.Get("a"); actualValue != 1 {
t.Errorf("Got %v expected %v", actualValue, "mapped: a")
@ -316,12 +289,12 @@ func TestMapMap(t *testing.T) {
}
func TestMapSelect(t *testing.T) {
m := NewWithStringComparator()
m := New[string, int]()
m.Put("c", 3)
m.Put("a", 1)
m.Put("b", 2)
selectedMap := m.Select(func(key interface{}, value interface{}) bool {
return key.(string) >= "a" && key.(string) <= "b"
selectedMap := m.Select(func(key string, value int) bool {
return key >= "a" && key <= "b"
})
if actualValue, _ := selectedMap.Get("a"); actualValue != 1 {
t.Errorf("Got %v expected %v", actualValue, "value: a")
@ -335,18 +308,18 @@ func TestMapSelect(t *testing.T) {
}
func TestMapAny(t *testing.T) {
m := NewWithStringComparator()
m := New[string, int]()
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
any := m.Any(func(key string, value int) bool {
return value == 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
any = m.Any(func(key string, value int) bool {
return value == 4
})
if any != false {
t.Errorf("Got %v expected %v", any, false)
@ -354,18 +327,18 @@ func TestMapAny(t *testing.T) {
}
func TestMapAll(t *testing.T) {
m := NewWithStringComparator()
m := New[string, int]()
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"
all := m.All(func(key string, value int) bool {
return key >= "a" && key <= "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"
all = m.All(func(key string, value int) bool {
return key >= "a" && key <= "b"
})
if all != false {
t.Errorf("Got %v expected %v", all, false)
@ -373,38 +346,38 @@ func TestMapAll(t *testing.T) {
}
func TestMapFind(t *testing.T) {
m := NewWithStringComparator()
m := New[string, int]()
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"
foundKey, foundValue := m.Find(func(key string, value int) bool {
return key == "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"
foundKey, foundValue = m.Find(func(key string, value int) bool {
return key == "x"
})
if foundKey != nil || foundValue != nil {
if foundKey != "" || foundValue != 0 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundKey, nil, nil)
}
}
func TestMapChaining(t *testing.T) {
m := NewWithStringComparator()
m := New[string, int]()
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)
chainedMap := m.Select(func(key string, value int) bool {
return value > 1
}).Map(func(key string, value int) (string, int) {
return key + key, value * value
})
if actualValue := chainedMap.Size(); actualValue != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if actualValue, found := chainedMap.Get("aa"); actualValue != nil || found {
if actualValue, found := chainedMap.Get("aa"); actualValue != 0 || found {
t.Errorf("Got %v expected %v", actualValue, nil)
}
if actualValue, found := chainedMap.Get("bb"); actualValue != 4 || !found {
@ -416,7 +389,7 @@ func TestMapChaining(t *testing.T) {
}
func TestMapIteratorNextOnEmpty(t *testing.T) {
m := NewWithStringComparator()
m := New[string, int]()
it := m.Iterator()
it = m.Iterator()
for it.Next() {
@ -425,7 +398,7 @@ func TestMapIteratorNextOnEmpty(t *testing.T) {
}
func TestMapIteratorPrevOnEmpty(t *testing.T) {
m := NewWithStringComparator()
m := New[string, int]()
it := m.Iterator()
it = m.Iterator()
for it.Prev() {
@ -434,7 +407,7 @@ func TestMapIteratorPrevOnEmpty(t *testing.T) {
}
func TestMapIteratorNext(t *testing.T) {
m := NewWithStringComparator()
m := New[string, int]()
m.Put("c", 3)
m.Put("a", 1)
m.Put("b", 2)
@ -471,7 +444,7 @@ func TestMapIteratorNext(t *testing.T) {
}
func TestMapIteratorPrev(t *testing.T) {
m := NewWithStringComparator()
m := New[string, int]()
m.Put("c", 3)
m.Put("a", 1)
m.Put("b", 2)
@ -510,7 +483,7 @@ func TestMapIteratorPrev(t *testing.T) {
}
func TestMapIteratorBegin(t *testing.T) {
m := NewWithIntComparator()
m := New[int, string]()
it := m.Iterator()
it.Begin()
m.Put(3, "c")
@ -526,7 +499,7 @@ func TestMapIteratorBegin(t *testing.T) {
}
func TestMapIteratorEnd(t *testing.T) {
m := NewWithIntComparator()
m := New[int, string]()
it := m.Iterator()
m.Put(3, "c")
m.Put(1, "a")
@ -539,7 +512,7 @@ func TestMapIteratorEnd(t *testing.T) {
}
func TestMapIteratorFirst(t *testing.T) {
m := NewWithIntComparator()
m := New[int, string]()
m.Put(3, "c")
m.Put(1, "a")
m.Put(2, "b")
@ -553,7 +526,7 @@ func TestMapIteratorFirst(t *testing.T) {
}
func TestMapIteratorLast(t *testing.T) {
m := NewWithIntComparator()
m := New[int, string]()
m.Put(3, "c")
m.Put(1, "a")
m.Put(2, "b")
@ -568,13 +541,13 @@ func TestMapIteratorLast(t *testing.T) {
func TestMapIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index interface{}, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// NextTo (empty)
{
m := NewWithIntComparator()
m := New[int, string]()
it := m.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty map")
@ -583,7 +556,7 @@ func TestMapIteratorNextTo(t *testing.T) {
// NextTo (not found)
{
m := NewWithIntComparator()
m := New[int, string]()
m.Put(0, "xx")
m.Put(1, "yy")
it := m.Iterator()
@ -594,7 +567,7 @@ func TestMapIteratorNextTo(t *testing.T) {
// NextTo (found)
{
m := NewWithIntComparator()
m := New[int, string]()
m.Put(0, "aa")
m.Put(1, "bb")
m.Put(2, "cc")
@ -603,13 +576,13 @@ func TestMapIteratorNextTo(t *testing.T) {
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty map")
}
if index, value := it.Key(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Key(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Key(), it.Value(); index != 2 || value.(string) != "cc" {
if index, value := it.Key(), it.Value(); index != 2 || value != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
@ -620,13 +593,13 @@ func TestMapIteratorNextTo(t *testing.T) {
func TestMapIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index interface{}, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// PrevTo (empty)
{
m := NewWithIntComparator()
m := New[int, string]()
it := m.Iterator()
it.End()
for it.PrevTo(seek) {
@ -636,7 +609,7 @@ func TestMapIteratorPrevTo(t *testing.T) {
// PrevTo (not found)
{
m := NewWithIntComparator()
m := New[int, string]()
m.Put(0, "xx")
m.Put(1, "yy")
it := m.Iterator()
@ -648,7 +621,7 @@ func TestMapIteratorPrevTo(t *testing.T) {
// PrevTo (found)
{
m := NewWithIntComparator()
m := New[int, string]()
m.Put(0, "aa")
m.Put(1, "bb")
m.Put(2, "cc")
@ -657,13 +630,13 @@ func TestMapIteratorPrevTo(t *testing.T) {
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty map")
}
if index, value := it.Key(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Key(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Key(), it.Value(); index != 0 || value.(string) != "aa" {
if index, value := it.Key(), it.Value(); index != 0 || value != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
@ -674,7 +647,7 @@ func TestMapIteratorPrevTo(t *testing.T) {
func TestMapSerialization(t *testing.T) {
for i := 0; i < 10; i++ {
original := NewWithStringComparator()
original := New[string, string]()
original.Put("d", "4")
original.Put("e", "5")
original.Put("c", "3")
@ -689,7 +662,7 @@ func TestMapSerialization(t *testing.T) {
}
assertSerialization(original, "B", t)
deserialized := NewWithStringComparator()
deserialized := New[string, string]()
err = deserialized.FromJSON(serialized)
if err != nil {
t.Errorf("Got error %v", err)
@ -697,7 +670,7 @@ func TestMapSerialization(t *testing.T) {
assertSerialization(deserialized, "C", t)
}
m := NewWithStringComparator()
m := New[string, float64]()
m.Put("a", 1.0)
m.Put("b", 2.0)
m.Put("c", 3.0)
@ -714,29 +687,29 @@ func TestMapSerialization(t *testing.T) {
}
func TestMapString(t *testing.T) {
c := NewWithStringComparator()
c := New[string, int]()
c.Put("a", 1)
if !strings.HasPrefix(c.String(), "TreeMap") {
t.Errorf("String should start with container name")
}
}
//noinspection GoBoolExpressions
func assertSerialization(m *Map, txt string, t *testing.T) {
// noinspection GoBoolExpressions
func assertSerialization(m *Map[string, string], txt string, t *testing.T) {
if actualValue := m.Keys(); false ||
actualValue[0].(string) != "a" ||
actualValue[1].(string) != "b" ||
actualValue[2].(string) != "c" ||
actualValue[3].(string) != "d" ||
actualValue[4].(string) != "e" {
actualValue[0] != "a" ||
actualValue[1] != "b" ||
actualValue[2] != "c" ||
actualValue[3] != "d" ||
actualValue[4] != "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" {
actualValue[0] != "1" ||
actualValue[1] != "2" ||
actualValue[2] != "3" ||
actualValue[3] != "4" ||
actualValue[4] != "5" {
t.Errorf("[%s] Got %v expected %v", txt, actualValue, "[1,2,3,4,5]")
}
if actualValue, expectedValue := m.Size(), 5; actualValue != expectedValue {
@ -744,7 +717,7 @@ func assertSerialization(m *Map, txt string, t *testing.T) {
}
}
func benchmarkGet(b *testing.B, m *Map, size int) {
func benchmarkGet(b *testing.B, m *Map[int, struct{}], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Get(n)
@ -752,7 +725,7 @@ func benchmarkGet(b *testing.B, m *Map, size int) {
}
}
func benchmarkPut(b *testing.B, m *Map, size int) {
func benchmarkPut(b *testing.B, m *Map[int, struct{}], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
@ -760,7 +733,7 @@ func benchmarkPut(b *testing.B, m *Map, size int) {
}
}
func benchmarkRemove(b *testing.B, m *Map, size int) {
func benchmarkRemove(b *testing.B, m *Map[int, struct{}], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
m.Remove(n)
@ -771,7 +744,7 @@ func benchmarkRemove(b *testing.B, m *Map, size int) {
func BenchmarkTreeMapGet100(b *testing.B) {
b.StopTimer()
size := 100
m := NewWithIntComparator()
m := New[int, struct{}]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
}
@ -782,7 +755,7 @@ func BenchmarkTreeMapGet100(b *testing.B) {
func BenchmarkTreeMapGet1000(b *testing.B) {
b.StopTimer()
size := 1000
m := NewWithIntComparator()
m := New[int, struct{}]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
}
@ -793,7 +766,7 @@ func BenchmarkTreeMapGet1000(b *testing.B) {
func BenchmarkTreeMapGet10000(b *testing.B) {
b.StopTimer()
size := 10000
m := NewWithIntComparator()
m := New[int, struct{}]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
}
@ -804,7 +777,7 @@ func BenchmarkTreeMapGet10000(b *testing.B) {
func BenchmarkTreeMapGet100000(b *testing.B) {
b.StopTimer()
size := 100000
m := NewWithIntComparator()
m := New[int, struct{}]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
}
@ -815,7 +788,7 @@ func BenchmarkTreeMapGet100000(b *testing.B) {
func BenchmarkTreeMapPut100(b *testing.B) {
b.StopTimer()
size := 100
m := NewWithIntComparator()
m := New[int, struct{}]()
b.StartTimer()
benchmarkPut(b, m, size)
}
@ -823,7 +796,7 @@ func BenchmarkTreeMapPut100(b *testing.B) {
func BenchmarkTreeMapPut1000(b *testing.B) {
b.StopTimer()
size := 1000
m := NewWithIntComparator()
m := New[int, struct{}]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
}
@ -834,7 +807,7 @@ func BenchmarkTreeMapPut1000(b *testing.B) {
func BenchmarkTreeMapPut10000(b *testing.B) {
b.StopTimer()
size := 10000
m := NewWithIntComparator()
m := New[int, struct{}]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
}
@ -845,7 +818,7 @@ func BenchmarkTreeMapPut10000(b *testing.B) {
func BenchmarkTreeMapPut100000(b *testing.B) {
b.StopTimer()
size := 100000
m := NewWithIntComparator()
m := New[int, struct{}]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
}
@ -856,7 +829,7 @@ func BenchmarkTreeMapPut100000(b *testing.B) {
func BenchmarkTreeMapRemove100(b *testing.B) {
b.StopTimer()
size := 100
m := NewWithIntComparator()
m := New[int, struct{}]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
}
@ -867,7 +840,7 @@ func BenchmarkTreeMapRemove100(b *testing.B) {
func BenchmarkTreeMapRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
m := NewWithIntComparator()
m := New[int, struct{}]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
}
@ -878,7 +851,7 @@ func BenchmarkTreeMapRemove1000(b *testing.B) {
func BenchmarkTreeMapRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
m := NewWithIntComparator()
m := New[int, struct{}]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
}
@ -889,7 +862,7 @@ func BenchmarkTreeMapRemove10000(b *testing.B) {
func BenchmarkTreeMapRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
m := NewWithIntComparator()
m := New[int, struct{}]()
for n := 0; n < size; n++ {
m.Put(n, struct{}{})
}

@ -13,31 +13,31 @@ import (
"fmt"
"strings"
"github.com/emirpasic/gods/lists/arraylist"
"github.com/emirpasic/gods/queues"
"github.com/emirpasic/gods/v2/lists/arraylist"
"github.com/emirpasic/gods/v2/queues"
)
// Assert Queue implementation
var _ queues.Queue = (*Queue)(nil)
var _ queues.Queue[int] = (*Queue[int])(nil)
// Queue holds elements in an array-list
type Queue struct {
list *arraylist.List
type Queue[T comparable] struct {
list *arraylist.List[T]
}
// New instantiates a new empty queue
func New() *Queue {
return &Queue{list: arraylist.New()}
func New[T comparable]() *Queue[T] {
return &Queue[T]{list: arraylist.New[T]()}
}
// Enqueue adds a value to the end of the queue
func (queue *Queue) Enqueue(value interface{}) {
func (queue *Queue[T]) Enqueue(value T) {
queue.list.Add(value)
}
// Dequeue removes first element of the queue and returns it, or nil if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to dequeue.
func (queue *Queue) Dequeue() (value interface{}, ok bool) {
func (queue *Queue[T]) Dequeue() (value T, ok bool) {
value, ok = queue.list.Get(0)
if ok {
queue.list.Remove(0)
@ -47,32 +47,32 @@ func (queue *Queue) Dequeue() (value interface{}, ok bool) {
// Peek returns first element of the queue without removing it, or nil if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to peek.
func (queue *Queue) Peek() (value interface{}, ok bool) {
func (queue *Queue[T]) Peek() (value T, ok bool) {
return queue.list.Get(0)
}
// Empty returns true if queue does not contain any elements.
func (queue *Queue) Empty() bool {
func (queue *Queue[T]) Empty() bool {
return queue.list.Empty()
}
// Size returns number of elements within the queue.
func (queue *Queue) Size() int {
func (queue *Queue[T]) Size() int {
return queue.list.Size()
}
// Clear removes all elements from the queue.
func (queue *Queue) Clear() {
func (queue *Queue[T]) Clear() {
queue.list.Clear()
}
// Values returns all elements in the queue (FIFO order).
func (queue *Queue) Values() []interface{} {
func (queue *Queue[T]) Values() []T {
return queue.list.Values()
}
// String returns a string representation of container
func (queue *Queue) String() string {
func (queue *Queue[T]) String() string {
str := "ArrayQueue\n"
values := []string{}
for _, value := range queue.list.Values() {
@ -83,6 +83,6 @@ func (queue *Queue) String() string {
}
// Check that the index is within bounds of the list
func (queue *Queue) withinRange(index int) bool {
func (queue *Queue[T]) withinRange(index int) bool {
return index >= 0 && index < queue.list.Size()
}

@ -6,13 +6,14 @@ package arrayqueue
import (
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/emirpasic/gods/v2/testutils"
)
func TestQueueEnqueue(t *testing.T) {
queue := New()
queue := New[int]()
if actualValue := queue.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
@ -20,7 +21,7 @@ func TestQueueEnqueue(t *testing.T) {
queue.Enqueue(2)
queue.Enqueue(3)
if actualValue := queue.Values(); actualValue[0].(int) != 1 || actualValue[1].(int) != 2 || actualValue[2].(int) != 3 {
if actualValue := queue.Values(); actualValue[0] != 1 || actualValue[1] != 2 || actualValue[2] != 3 {
t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
}
if actualValue := queue.Empty(); actualValue != false {
@ -35,8 +36,8 @@ func TestQueueEnqueue(t *testing.T) {
}
func TestQueuePeek(t *testing.T) {
queue := New()
if actualValue, ok := queue.Peek(); actualValue != nil || ok {
queue := New[int]()
if actualValue, ok := queue.Peek(); actualValue != 0 || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
queue.Enqueue(1)
@ -48,7 +49,7 @@ func TestQueuePeek(t *testing.T) {
}
func TestQueueDequeue(t *testing.T) {
queue := New()
queue := New[int]()
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
@ -62,7 +63,7 @@ func TestQueueDequeue(t *testing.T) {
if actualValue, ok := queue.Dequeue(); actualValue != 3 || !ok {
t.Errorf("Got %v expected %v", actualValue, 3)
}
if actualValue, ok := queue.Dequeue(); actualValue != nil || ok {
if actualValue, ok := queue.Dequeue(); actualValue != 0 || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
if actualValue := queue.Empty(); actualValue != true {
@ -74,7 +75,7 @@ func TestQueueDequeue(t *testing.T) {
}
func TestQueueIteratorOnEmpty(t *testing.T) {
queue := New()
queue := New[int]()
it := queue.Iterator()
for it.Next() {
t.Errorf("Shouldn't iterate on empty queue")
@ -82,7 +83,7 @@ func TestQueueIteratorOnEmpty(t *testing.T) {
}
func TestQueueIteratorNext(t *testing.T) {
queue := New()
queue := New[string]()
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
@ -125,7 +126,7 @@ func TestQueueIteratorNext(t *testing.T) {
}
func TestQueueIteratorPrev(t *testing.T) {
queue := New()
queue := New[string]()
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
@ -164,7 +165,7 @@ func TestQueueIteratorPrev(t *testing.T) {
}
func TestQueueIteratorBegin(t *testing.T) {
queue := New()
queue := New[string]()
it := queue.Iterator()
it.Begin()
queue.Enqueue("a")
@ -180,7 +181,7 @@ func TestQueueIteratorBegin(t *testing.T) {
}
func TestQueueIteratorEnd(t *testing.T) {
queue := New()
queue := New[string]()
it := queue.Iterator()
if index := it.Index(); index != -1 {
@ -207,7 +208,7 @@ func TestQueueIteratorEnd(t *testing.T) {
}
func TestQueueIteratorFirst(t *testing.T) {
queue := New()
queue := New[string]()
it := queue.Iterator()
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -224,7 +225,7 @@ func TestQueueIteratorFirst(t *testing.T) {
}
func TestQueueIteratorLast(t *testing.T) {
queue := New()
queue := New[string]()
it := queue.Iterator()
if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -242,13 +243,13 @@ func TestQueueIteratorLast(t *testing.T) {
func TestQueueIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// NextTo (empty)
{
queue := New()
queue := New[string]()
it := queue.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
@ -257,7 +258,7 @@ func TestQueueIteratorNextTo(t *testing.T) {
// NextTo (not found)
{
queue := New()
queue := New[string]()
queue.Enqueue("xx")
queue.Enqueue("yy")
it := queue.Iterator()
@ -268,7 +269,7 @@ func TestQueueIteratorNextTo(t *testing.T) {
// NextTo (found)
{
queue := New()
queue := New[string]()
queue.Enqueue("aa")
queue.Enqueue("bb")
queue.Enqueue("cc")
@ -277,13 +278,13 @@ func TestQueueIteratorNextTo(t *testing.T) {
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 2 || value.(string) != "cc" {
if index, value := it.Index(), it.Value(); index != 2 || value != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
@ -294,13 +295,13 @@ func TestQueueIteratorNextTo(t *testing.T) {
func TestQueueIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// PrevTo (empty)
{
queue := New()
queue := New[string]()
it := queue.Iterator()
it.End()
for it.PrevTo(seek) {
@ -310,7 +311,7 @@ func TestQueueIteratorPrevTo(t *testing.T) {
// PrevTo (not found)
{
queue := New()
queue := New[string]()
queue.Enqueue("xx")
queue.Enqueue("yy")
it := queue.Iterator()
@ -322,7 +323,7 @@ func TestQueueIteratorPrevTo(t *testing.T) {
// PrevTo (found)
{
queue := New()
queue := New[string]()
queue.Enqueue("aa")
queue.Enqueue("bb")
queue.Enqueue("cc")
@ -331,13 +332,13 @@ func TestQueueIteratorPrevTo(t *testing.T) {
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 0 || value.(string) != "aa" {
if index, value := it.Index(), it.Value(); index != 0 || value != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
@ -347,16 +348,14 @@ func TestQueueIteratorPrevTo(t *testing.T) {
}
func TestQueueSerialization(t *testing.T) {
queue := New()
queue := New[string]()
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
var err error
assert := func() {
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", queue.Values()...), "abc"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, queue.Values(), []string{"a", "b", "c"})
if actualValue, expectedValue := queue.Size(), 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
@ -378,21 +377,22 @@ func TestQueueSerialization(t *testing.T) {
t.Errorf("Got error %v", err)
}
err = json.Unmarshal([]byte(`[1,2,3]`), &queue)
err = json.Unmarshal([]byte(`["a","b","c"]`), &queue)
if err != nil {
t.Errorf("Got error %v", err)
}
assert()
}
func TestQueueString(t *testing.T) {
c := New()
c := New[int]()
c.Enqueue(1)
if !strings.HasPrefix(c.String(), "ArrayQueue") {
t.Errorf("String should start with container name")
}
}
func benchmarkEnqueue(b *testing.B, queue *Queue, size int) {
func benchmarkEnqueue(b *testing.B, queue *Queue[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Enqueue(n)
@ -400,7 +400,7 @@ func benchmarkEnqueue(b *testing.B, queue *Queue, size int) {
}
}
func benchmarkDequeue(b *testing.B, queue *Queue, size int) {
func benchmarkDequeue(b *testing.B, queue *Queue[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Dequeue()
@ -411,7 +411,7 @@ func benchmarkDequeue(b *testing.B, queue *Queue, size int) {
func BenchmarkArrayQueueDequeue100(b *testing.B) {
b.StopTimer()
size := 100
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -422,7 +422,7 @@ func BenchmarkArrayQueueDequeue100(b *testing.B) {
func BenchmarkArrayQueueDequeue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -433,7 +433,7 @@ func BenchmarkArrayQueueDequeue1000(b *testing.B) {
func BenchmarkArrayQueueDequeue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -444,7 +444,7 @@ func BenchmarkArrayQueueDequeue10000(b *testing.B) {
func BenchmarkArrayQueueDequeue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -455,7 +455,7 @@ func BenchmarkArrayQueueDequeue100000(b *testing.B) {
func BenchmarkArrayQueueEnqueue100(b *testing.B) {
b.StopTimer()
size := 100
queue := New()
queue := New[int]()
b.StartTimer()
benchmarkEnqueue(b, queue, size)
}
@ -463,7 +463,7 @@ func BenchmarkArrayQueueEnqueue100(b *testing.B) {
func BenchmarkArrayQueueEnqueue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -474,7 +474,7 @@ func BenchmarkArrayQueueEnqueue1000(b *testing.B) {
func BenchmarkArrayQueueEnqueue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -485,7 +485,7 @@ func BenchmarkArrayQueueEnqueue10000(b *testing.B) {
func BenchmarkArrayQueueEnqueue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}

@ -4,27 +4,27 @@
package arrayqueue
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Iterator implementation
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator struct {
queue *Queue
type Iterator[T comparable] struct {
queue *Queue[T]
index int
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (queue *Queue) Iterator() Iterator {
return Iterator{queue: queue, index: -1}
func (queue *Queue[T]) Iterator() *Iterator[T] {
return &Iterator[T]{queue: queue, index: -1}
}
// 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 index and value can be retrieved by Index() 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 {
func (iterator *Iterator[T]) Next() bool {
if iterator.index < iterator.queue.Size() {
iterator.index++
}
@ -34,7 +34,7 @@ func (iterator *Iterator) Next() bool {
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Prev() bool {
func (iterator *Iterator[T]) Prev() bool {
if iterator.index >= 0 {
iterator.index--
}
@ -43,33 +43,33 @@ func (iterator *Iterator) Prev() bool {
// Value returns the current element's value.
// Does not modify the state of the iterator.
func (iterator *Iterator) Value() interface{} {
func (iterator *Iterator[T]) Value() T {
value, _ := iterator.queue.list.Get(iterator.index)
return value
}
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
func (iterator *Iterator[T]) Index() int {
return iterator.index
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
func (iterator *Iterator[T]) Begin() {
iterator.index = -1
}
// 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() {
func (iterator *Iterator[T]) End() {
iterator.index = iterator.queue.Size()
}
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
func (iterator *Iterator[T]) First() bool {
iterator.Begin()
return iterator.Next()
}
@ -77,7 +77,7 @@ func (iterator *Iterator) First() bool {
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Last() bool {
func (iterator *Iterator[T]) Last() bool {
iterator.End()
return iterator.Prev()
}
@ -86,7 +86,7 @@ func (iterator *Iterator) Last() bool {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) NextTo(f func(index int, value T) bool) bool {
for iterator.Next() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
@ -100,7 +100,7 @@ func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) PrevTo(f func(index int, value T) bool) bool {
for iterator.Prev() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {

@ -5,29 +5,29 @@
package arrayqueue
import (
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Queue)(nil)
var _ containers.JSONDeserializer = (*Queue)(nil)
var _ containers.JSONSerializer = (*Queue[int])(nil)
var _ containers.JSONDeserializer = (*Queue[int])(nil)
// ToJSON outputs the JSON representation of the queue.
func (queue *Queue) ToJSON() ([]byte, error) {
func (queue *Queue[T]) ToJSON() ([]byte, error) {
return queue.list.ToJSON()
}
// FromJSON populates the queue from the input JSON representation.
func (queue *Queue) FromJSON(data []byte) error {
func (queue *Queue[T]) FromJSON(data []byte) error {
return queue.list.FromJSON(data)
}
// UnmarshalJSON @implements json.Unmarshaler
func (queue *Queue) UnmarshalJSON(bytes []byte) error {
func (queue *Queue[T]) UnmarshalJSON(bytes []byte) error {
return queue.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (queue *Queue) MarshalJSON() ([]byte, error) {
func (queue *Queue[T]) MarshalJSON() ([]byte, error) {
return queue.ToJSON()
}

@ -15,15 +15,15 @@ import (
"fmt"
"strings"
"github.com/emirpasic/gods/queues"
"github.com/emirpasic/gods/v2/queues"
)
// Assert Queue implementation
var _ queues.Queue = (*Queue)(nil)
var _ queues.Queue[int] = (*Queue[int])(nil)
// Queue holds values in a slice.
type Queue struct {
values []interface{}
type Queue[T comparable] struct {
values []T
start int
end int
full bool
@ -33,17 +33,17 @@ type Queue struct {
// New instantiates a new empty queue with the specified size of maximum number of elements that it can hold.
// This max size of the buffer cannot be changed.
func New(maxSize int) *Queue {
func New[T comparable](maxSize int) *Queue[T] {
if maxSize < 1 {
panic("Invalid maxSize, should be at least 1")
}
queue := &Queue{maxSize: maxSize}
queue := &Queue[T]{maxSize: maxSize}
queue.Clear()
return queue
}
// Enqueue adds a value to the end of the queue
func (queue *Queue) Enqueue(value interface{}) {
func (queue *Queue[T]) Enqueue(value T) {
if queue.Full() {
queue.Dequeue()
}
@ -59,24 +59,19 @@ func (queue *Queue) Enqueue(value interface{}) {
queue.size = queue.calculateSize()
}
// Dequeue removes first element of the queue and returns it, or nil if queue is empty.
// Dequeue removes first element of the queue and returns it, or the 0-value if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to dequeue.
func (queue *Queue) Dequeue() (value interface{}, ok bool) {
func (queue *Queue[T]) Dequeue() (value T, ok bool) {
if queue.Empty() {
return nil, false
return value, false
}
value, ok = queue.values[queue.start], true
if value != nil {
queue.values[queue.start] = nil
queue.start = queue.start + 1
if queue.start >= queue.maxSize {
queue.start = 0
}
queue.full = false
queue.start = queue.start + 1
if queue.start >= queue.maxSize {
queue.start = 0
}
queue.full = false
queue.size = queue.size - 1
return
@ -84,31 +79,31 @@ func (queue *Queue) Dequeue() (value interface{}, ok bool) {
// Peek returns first element of the queue without removing it, or nil if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to peek.
func (queue *Queue) Peek() (value interface{}, ok bool) {
func (queue *Queue[T]) Peek() (value T, ok bool) {
if queue.Empty() {
return nil, false
return value, false
}
return queue.values[queue.start], true
}
// Empty returns true if queue does not contain any elements.
func (queue *Queue) Empty() bool {
func (queue *Queue[T]) Empty() bool {
return queue.Size() == 0
}
// Full returns true if the queue is full, i.e. has reached the maximum number of elements that it can hold.
func (queue *Queue) Full() bool {
func (queue *Queue[T]) Full() bool {
return queue.Size() == queue.maxSize
}
// Size returns number of elements within the queue.
func (queue *Queue) Size() int {
func (queue *Queue[T]) Size() int {
return queue.size
}
// Clear removes all elements from the queue.
func (queue *Queue) Clear() {
queue.values = make([]interface{}, queue.maxSize, queue.maxSize)
func (queue *Queue[T]) Clear() {
queue.values = make([]T, queue.maxSize, queue.maxSize)
queue.start = 0
queue.end = 0
queue.full = false
@ -116,8 +111,8 @@ func (queue *Queue) Clear() {
}
// Values returns all elements in the queue (FIFO order).
func (queue *Queue) Values() []interface{} {
values := make([]interface{}, queue.Size(), queue.Size())
func (queue *Queue[T]) Values() []T {
values := make([]T, queue.Size(), queue.Size())
for i := 0; i < queue.Size(); i++ {
values[i] = queue.values[(queue.start+i)%queue.maxSize]
}
@ -125,7 +120,7 @@ func (queue *Queue) Values() []interface{} {
}
// String returns a string representation of container
func (queue *Queue) String() string {
func (queue *Queue[T]) String() string {
str := "CircularBuffer\n"
var values []string
for _, value := range queue.Values() {
@ -136,11 +131,11 @@ func (queue *Queue) String() string {
}
// Check that the index is within bounds of the list
func (queue *Queue) withinRange(index int) bool {
func (queue *Queue[T]) withinRange(index int) bool {
return index >= 0 && index < queue.size
}
func (queue *Queue) calculateSize() int {
func (queue *Queue[T]) calculateSize() int {
if queue.end < queue.start {
return queue.maxSize - queue.start + queue.end
} else if queue.end == queue.start {

@ -6,13 +6,14 @@ package circularbuffer
import (
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/emirpasic/gods/v2/testutils"
)
func TestQueueEnqueue(t *testing.T) {
queue := New(3)
queue := New[int](3)
if actualValue := queue.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
@ -20,7 +21,7 @@ func TestQueueEnqueue(t *testing.T) {
queue.Enqueue(2)
queue.Enqueue(3)
if actualValue := queue.Values(); actualValue[0].(int) != 1 || actualValue[1].(int) != 2 || actualValue[2].(int) != 3 {
if actualValue := queue.Values(); actualValue[0] != 1 || actualValue[1] != 2 || actualValue[2] != 3 {
t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
}
if actualValue := queue.Empty(); actualValue != false {
@ -35,8 +36,8 @@ func TestQueueEnqueue(t *testing.T) {
}
func TestQueuePeek(t *testing.T) {
queue := New(3)
if actualValue, ok := queue.Peek(); actualValue != nil || ok {
queue := New[int](3)
if actualValue, ok := queue.Peek(); actualValue != 0 || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
queue.Enqueue(1)
@ -54,7 +55,7 @@ func TestQueueDequeue(t *testing.T) {
}
}
queue := New(3)
queue := New[int](3)
assert(queue.Empty(), true)
assert(queue.Empty(), true)
assert(queue.Full(), false)
@ -89,7 +90,7 @@ func TestQueueDequeue(t *testing.T) {
assert(queue.Empty(), true)
assert(queue.Full(), false)
if actualValue, ok := queue.Dequeue(); actualValue != nil || ok {
if actualValue, ok := queue.Dequeue(); actualValue != 0 || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
assert(queue.Size(), 0)
@ -106,7 +107,7 @@ func TestQueueDequeueFull(t *testing.T) {
}
}
queue := New(2)
queue := New[int](2)
assert(queue.Empty(), true)
assert(queue.Full(), false)
assert(queue.Size(), 0)
@ -142,7 +143,7 @@ func TestQueueDequeueFull(t *testing.T) {
}
assert(queue.Size(), 0)
if actualValue, ok := queue.Dequeue(); actualValue != nil || ok {
if actualValue, ok := queue.Dequeue(); actualValue != 0 || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
assert(queue.Empty(), true)
@ -151,7 +152,7 @@ func TestQueueDequeueFull(t *testing.T) {
}
func TestQueueIteratorOnEmpty(t *testing.T) {
queue := New(3)
queue := New[int](3)
it := queue.Iterator()
for it.Next() {
t.Errorf("Shouldn't iterate on empty queue")
@ -159,7 +160,7 @@ func TestQueueIteratorOnEmpty(t *testing.T) {
}
func TestQueueIteratorNext(t *testing.T) {
queue := New(3)
queue := New[string](3)
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
@ -202,7 +203,7 @@ func TestQueueIteratorNext(t *testing.T) {
}
func TestQueueIteratorPrev(t *testing.T) {
queue := New(3)
queue := New[string](3)
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
@ -241,7 +242,7 @@ func TestQueueIteratorPrev(t *testing.T) {
}
func TestQueueIteratorBegin(t *testing.T) {
queue := New(3)
queue := New[string](3)
it := queue.Iterator()
it.Begin()
queue.Enqueue("a")
@ -257,7 +258,7 @@ func TestQueueIteratorBegin(t *testing.T) {
}
func TestQueueIteratorEnd(t *testing.T) {
queue := New(3)
queue := New[string](3)
it := queue.Iterator()
if index := it.Index(); index != -1 {
@ -284,7 +285,7 @@ func TestQueueIteratorEnd(t *testing.T) {
}
func TestQueueIteratorFirst(t *testing.T) {
queue := New(3)
queue := New[string](3)
it := queue.Iterator()
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -301,7 +302,7 @@ func TestQueueIteratorFirst(t *testing.T) {
}
func TestQueueIteratorLast(t *testing.T) {
queue := New(3)
queue := New[string](3)
it := queue.Iterator()
if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -319,13 +320,13 @@ func TestQueueIteratorLast(t *testing.T) {
func TestQueueIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// NextTo (empty)
{
queue := New(3)
queue := New[string](3)
it := queue.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
@ -334,7 +335,7 @@ func TestQueueIteratorNextTo(t *testing.T) {
// NextTo (not found)
{
queue := New(3)
queue := New[string](3)
queue.Enqueue("xx")
queue.Enqueue("yy")
it := queue.Iterator()
@ -345,7 +346,7 @@ func TestQueueIteratorNextTo(t *testing.T) {
// NextTo (found)
{
queue := New(3)
queue := New[string](3)
queue.Enqueue("aa")
queue.Enqueue("bb")
queue.Enqueue("cc")
@ -354,13 +355,13 @@ func TestQueueIteratorNextTo(t *testing.T) {
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 2 || value.(string) != "cc" {
if index, value := it.Index(), it.Value(); index != 2 || value != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
@ -371,13 +372,13 @@ func TestQueueIteratorNextTo(t *testing.T) {
func TestQueueIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// PrevTo (empty)
{
queue := New(3)
queue := New[string](3)
it := queue.Iterator()
it.End()
for it.PrevTo(seek) {
@ -387,7 +388,7 @@ func TestQueueIteratorPrevTo(t *testing.T) {
// PrevTo (not found)
{
queue := New(3)
queue := New[string](3)
queue.Enqueue("xx")
queue.Enqueue("yy")
it := queue.Iterator()
@ -399,7 +400,7 @@ func TestQueueIteratorPrevTo(t *testing.T) {
// PrevTo (found)
{
queue := New(3)
queue := New[string](3)
queue.Enqueue("aa")
queue.Enqueue("bb")
queue.Enqueue("cc")
@ -408,13 +409,13 @@ func TestQueueIteratorPrevTo(t *testing.T) {
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 0 || value.(string) != "aa" {
if index, value := it.Index(), it.Value(); index != 0 || value != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
@ -430,7 +431,7 @@ func TestQueueIterator(t *testing.T) {
}
}
queue := New(2)
queue := New[string](2)
queue.Enqueue("a")
queue.Enqueue("b")
@ -482,16 +483,14 @@ func TestQueueIterator(t *testing.T) {
}
func TestQueueSerialization(t *testing.T) {
queue := New(3)
queue := New[string](3)
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
var err error
assert := func() {
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", queue.Values()...), "abc"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, queue.Values(), []string{"a", "b", "c"})
if actualValue, expectedValue := queue.Size(), 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
@ -513,21 +512,22 @@ func TestQueueSerialization(t *testing.T) {
t.Errorf("Got error %v", err)
}
err = json.Unmarshal([]byte(`[1,2,3]`), &queue)
err = json.Unmarshal([]byte(`["a","b","c"]`), &queue)
if err != nil {
t.Errorf("Got error %v", err)
}
assert()
}
func TestQueueString(t *testing.T) {
c := New(3)
c := New[int](3)
c.Enqueue(1)
if !strings.HasPrefix(c.String(), "CircularBuffer") {
t.Errorf("String should start with container name")
}
}
func benchmarkEnqueue(b *testing.B, queue *Queue, size int) {
func benchmarkEnqueue(b *testing.B, queue *Queue[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Enqueue(n)
@ -535,7 +535,7 @@ func benchmarkEnqueue(b *testing.B, queue *Queue, size int) {
}
}
func benchmarkDequeue(b *testing.B, queue *Queue, size int) {
func benchmarkDequeue(b *testing.B, queue *Queue[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Dequeue()
@ -546,7 +546,7 @@ func benchmarkDequeue(b *testing.B, queue *Queue, size int) {
func BenchmarkArrayQueueDequeue100(b *testing.B) {
b.StopTimer()
size := 100
queue := New(3)
queue := New[int](3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -557,7 +557,7 @@ func BenchmarkArrayQueueDequeue100(b *testing.B) {
func BenchmarkArrayQueueDequeue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := New(3)
queue := New[int](3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -568,7 +568,7 @@ func BenchmarkArrayQueueDequeue1000(b *testing.B) {
func BenchmarkArrayQueueDequeue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := New(3)
queue := New[int](3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -579,7 +579,7 @@ func BenchmarkArrayQueueDequeue10000(b *testing.B) {
func BenchmarkArrayQueueDequeue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := New(3)
queue := New[int](3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -590,7 +590,7 @@ func BenchmarkArrayQueueDequeue100000(b *testing.B) {
func BenchmarkArrayQueueEnqueue100(b *testing.B) {
b.StopTimer()
size := 100
queue := New(3)
queue := New[int](3)
b.StartTimer()
benchmarkEnqueue(b, queue, size)
}
@ -598,7 +598,7 @@ func BenchmarkArrayQueueEnqueue100(b *testing.B) {
func BenchmarkArrayQueueEnqueue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := New(3)
queue := New[int](3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -609,7 +609,7 @@ func BenchmarkArrayQueueEnqueue1000(b *testing.B) {
func BenchmarkArrayQueueEnqueue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := New(3)
queue := New[int](3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -620,7 +620,7 @@ func BenchmarkArrayQueueEnqueue10000(b *testing.B) {
func BenchmarkArrayQueueEnqueue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := New(3)
queue := New[int](3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}

@ -4,27 +4,27 @@
package circularbuffer
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Iterator implementation
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator struct {
queue *Queue
type Iterator[T comparable] struct {
queue *Queue[T]
index int
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (queue *Queue) Iterator() Iterator {
return Iterator{queue: queue, index: -1}
func (queue *Queue[T]) Iterator() *Iterator[T] {
return &Iterator[T]{queue: queue, index: -1}
}
// 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 index and value can be retrieved by Index() 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 {
func (iterator *Iterator[T]) Next() bool {
if iterator.index < iterator.queue.size {
iterator.index++
}
@ -34,7 +34,7 @@ func (iterator *Iterator) Next() bool {
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Prev() bool {
func (iterator *Iterator[T]) Prev() bool {
if iterator.index >= 0 {
iterator.index--
}
@ -43,7 +43,7 @@ func (iterator *Iterator) Prev() bool {
// Value returns the current element's value.
// Does not modify the state of the iterator.
func (iterator *Iterator) Value() interface{} {
func (iterator *Iterator[T]) Value() T {
index := (iterator.index + iterator.queue.start) % iterator.queue.maxSize
value := iterator.queue.values[index]
return value
@ -51,26 +51,26 @@ func (iterator *Iterator) Value() interface{} {
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
func (iterator *Iterator[T]) Index() int {
return iterator.index
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
func (iterator *Iterator[T]) Begin() {
iterator.index = -1
}
// 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() {
func (iterator *Iterator[T]) End() {
iterator.index = iterator.queue.size
}
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
func (iterator *Iterator[T]) First() bool {
iterator.Begin()
return iterator.Next()
}
@ -78,7 +78,7 @@ func (iterator *Iterator) First() bool {
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Last() bool {
func (iterator *Iterator[T]) Last() bool {
iterator.End()
return iterator.Prev()
}
@ -87,7 +87,7 @@ func (iterator *Iterator) Last() bool {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) NextTo(f func(index int, value T) bool) bool {
for iterator.Next() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
@ -101,7 +101,7 @@ func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) PrevTo(f func(index int, value T) bool) bool {
for iterator.Prev() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {

@ -6,21 +6,22 @@ package circularbuffer
import (
"encoding/json"
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Queue)(nil)
var _ containers.JSONDeserializer = (*Queue)(nil)
var _ containers.JSONSerializer = (*Queue[int])(nil)
var _ containers.JSONDeserializer = (*Queue[int])(nil)
// ToJSON outputs the JSON representation of queue's elements.
func (queue *Queue) ToJSON() ([]byte, error) {
func (queue *Queue[T]) ToJSON() ([]byte, error) {
return json.Marshal(queue.values[:queue.maxSize])
}
// FromJSON populates list's elements from the input JSON representation.
func (queue *Queue) FromJSON(data []byte) error {
var values []interface{}
func (queue *Queue[T]) FromJSON(data []byte) error {
var values []T
err := json.Unmarshal(data, &values)
if err == nil {
for _, value := range values {
@ -31,11 +32,11 @@ func (queue *Queue) FromJSON(data []byte) error {
}
// UnmarshalJSON @implements json.Unmarshaler
func (queue *Queue) UnmarshalJSON(bytes []byte) error {
func (queue *Queue[T]) UnmarshalJSON(bytes []byte) error {
return queue.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (queue *Queue) MarshalJSON() ([]byte, error) {
func (queue *Queue[T]) MarshalJSON() ([]byte, error) {
return queue.ToJSON()
}

@ -4,27 +4,27 @@
package linkedlistqueue
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Iterator implementation
var _ containers.IteratorWithIndex = (*Iterator)(nil)
var _ containers.IteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator struct {
queue *Queue
type Iterator[T comparable] struct {
queue *Queue[T]
index int
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (queue *Queue) Iterator() Iterator {
return Iterator{queue: queue, index: -1}
func (queue *Queue[T]) Iterator() *Iterator[T] {
return &Iterator[T]{queue: queue, index: -1}
}
// 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 index and value can be retrieved by Index() 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 {
func (iterator *Iterator[T]) Next() bool {
if iterator.index < iterator.queue.Size() {
iterator.index++
}
@ -33,27 +33,27 @@ func (iterator *Iterator) Next() bool {
// Value returns the current element's value.
// Does not modify the state of the iterator.
func (iterator *Iterator) Value() interface{} {
func (iterator *Iterator[T]) Value() T {
value, _ := iterator.queue.list.Get(iterator.index)
return value
}
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
func (iterator *Iterator[T]) Index() int {
return iterator.index
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
func (iterator *Iterator[T]) Begin() {
iterator.index = -1
}
// 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
func (iterator *Iterator[T]) First() bool {
iterator.Begin()
return iterator.Next()
}
@ -62,7 +62,7 @@ func (iterator *Iterator) First() bool {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) NextTo(f func(index int, value T) bool) bool {
for iterator.Next() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {

@ -13,31 +13,31 @@ import (
"fmt"
"strings"
"github.com/emirpasic/gods/lists/singlylinkedlist"
"github.com/emirpasic/gods/queues"
"github.com/emirpasic/gods/v2/lists/singlylinkedlist"
"github.com/emirpasic/gods/v2/queues"
)
// Assert Queue implementation
var _ queues.Queue = (*Queue)(nil)
var _ queues.Queue[int] = (*Queue[int])(nil)
// Queue holds elements in a singly-linked-list
type Queue struct {
list *singlylinkedlist.List
type Queue[T comparable] struct {
list *singlylinkedlist.List[T]
}
// New instantiates a new empty queue
func New() *Queue {
return &Queue{list: &singlylinkedlist.List{}}
func New[T comparable]() *Queue[T] {
return &Queue[T]{list: singlylinkedlist.New[T]()}
}
// Enqueue adds a value to the end of the queue
func (queue *Queue) Enqueue(value interface{}) {
func (queue *Queue[T]) Enqueue(value T) {
queue.list.Add(value)
}
// Dequeue removes first element of the queue and returns it, or nil if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to dequeue.
func (queue *Queue) Dequeue() (value interface{}, ok bool) {
func (queue *Queue[T]) Dequeue() (value T, ok bool) {
value, ok = queue.list.Get(0)
if ok {
queue.list.Remove(0)
@ -47,32 +47,32 @@ func (queue *Queue) Dequeue() (value interface{}, ok bool) {
// Peek returns first element of the queue without removing it, or nil if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to peek.
func (queue *Queue) Peek() (value interface{}, ok bool) {
func (queue *Queue[T]) Peek() (value T, ok bool) {
return queue.list.Get(0)
}
// Empty returns true if queue does not contain any elements.
func (queue *Queue) Empty() bool {
func (queue *Queue[T]) Empty() bool {
return queue.list.Empty()
}
// Size returns number of elements within the queue.
func (queue *Queue) Size() int {
func (queue *Queue[T]) Size() int {
return queue.list.Size()
}
// Clear removes all elements from the queue.
func (queue *Queue) Clear() {
func (queue *Queue[T]) Clear() {
queue.list.Clear()
}
// Values returns all elements in the queue (FIFO order).
func (queue *Queue) Values() []interface{} {
func (queue *Queue[T]) Values() []T {
return queue.list.Values()
}
// String returns a string representation of container
func (queue *Queue) String() string {
func (queue *Queue[T]) String() string {
str := "LinkedListQueue\n"
values := []string{}
for _, value := range queue.list.Values() {
@ -83,6 +83,6 @@ func (queue *Queue) String() string {
}
// Check that the index is within bounds of the list
func (queue *Queue) withinRange(index int) bool {
func (queue *Queue[T]) withinRange(index int) bool {
return index >= 0 && index < queue.list.Size()
}

@ -6,13 +6,14 @@ package linkedlistqueue
import (
"encoding/json"
"fmt"
"strings"
"testing"
"github.com/emirpasic/gods/v2/testutils"
)
func TestQueueEnqueue(t *testing.T) {
queue := New()
queue := New[int]()
if actualValue := queue.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
@ -20,7 +21,7 @@ func TestQueueEnqueue(t *testing.T) {
queue.Enqueue(2)
queue.Enqueue(3)
if actualValue := queue.Values(); actualValue[0].(int) != 1 || actualValue[1].(int) != 2 || actualValue[2].(int) != 3 {
if actualValue := queue.Values(); actualValue[0] != 1 || actualValue[1] != 2 || actualValue[2] != 3 {
t.Errorf("Got %v expected %v", actualValue, "[1,2,3]")
}
if actualValue := queue.Empty(); actualValue != false {
@ -35,8 +36,8 @@ func TestQueueEnqueue(t *testing.T) {
}
func TestQueuePeek(t *testing.T) {
queue := New()
if actualValue, ok := queue.Peek(); actualValue != nil || ok {
queue := New[int]()
if actualValue, ok := queue.Peek(); actualValue != 0 || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
queue.Enqueue(1)
@ -48,7 +49,7 @@ func TestQueuePeek(t *testing.T) {
}
func TestQueueDequeue(t *testing.T) {
queue := New()
queue := New[int]()
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
@ -62,7 +63,7 @@ func TestQueueDequeue(t *testing.T) {
if actualValue, ok := queue.Dequeue(); actualValue != 3 || !ok {
t.Errorf("Got %v expected %v", actualValue, 3)
}
if actualValue, ok := queue.Dequeue(); actualValue != nil || ok {
if actualValue, ok := queue.Dequeue(); actualValue != 0 || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
if actualValue := queue.Empty(); actualValue != true {
@ -74,7 +75,7 @@ func TestQueueDequeue(t *testing.T) {
}
func TestQueueIteratorOnEmpty(t *testing.T) {
queue := New()
queue := New[int]()
it := queue.Iterator()
for it.Next() {
t.Errorf("Shouldn't iterate on empty queue")
@ -82,7 +83,7 @@ func TestQueueIteratorOnEmpty(t *testing.T) {
}
func TestQueueIteratorNext(t *testing.T) {
queue := New()
queue := New[string]()
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
@ -125,7 +126,7 @@ func TestQueueIteratorNext(t *testing.T) {
}
func TestQueueIteratorBegin(t *testing.T) {
queue := New()
queue := New[string]()
it := queue.Iterator()
it.Begin()
queue.Enqueue("a")
@ -141,7 +142,7 @@ func TestQueueIteratorBegin(t *testing.T) {
}
func TestQueueIteratorFirst(t *testing.T) {
queue := New()
queue := New[string]()
it := queue.Iterator()
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -159,13 +160,13 @@ func TestQueueIteratorFirst(t *testing.T) {
func TestQueueIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// NextTo (empty)
{
queue := New()
queue := New[string]()
it := queue.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
@ -174,7 +175,7 @@ func TestQueueIteratorNextTo(t *testing.T) {
// NextTo (not found)
{
queue := New()
queue := New[string]()
queue.Enqueue("xx")
queue.Enqueue("yy")
it := queue.Iterator()
@ -185,7 +186,7 @@ func TestQueueIteratorNextTo(t *testing.T) {
// NextTo (found)
{
queue := New()
queue := New[string]()
queue.Enqueue("aa")
queue.Enqueue("bb")
queue.Enqueue("cc")
@ -194,13 +195,13 @@ func TestQueueIteratorNextTo(t *testing.T) {
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 2 || value.(string) != "cc" {
if index, value := it.Index(), it.Value(); index != 2 || value != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
@ -210,16 +211,14 @@ func TestQueueIteratorNextTo(t *testing.T) {
}
func TestQueueSerialization(t *testing.T) {
queue := New()
queue := New[string]()
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
var err error
assert := func() {
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", queue.Values()...), "abc"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
testutils.SameElements(t, queue.Values(), []string{"a", "b", "c"})
if actualValue, expectedValue := queue.Size(), 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
@ -241,21 +240,22 @@ func TestQueueSerialization(t *testing.T) {
t.Errorf("Got error %v", err)
}
err = json.Unmarshal([]byte(`[1,2,3]`), &queue)
err = json.Unmarshal([]byte(`["a","b","c"]`), &queue)
if err != nil {
t.Errorf("Got error %v", err)
}
assert()
}
func TestQueueString(t *testing.T) {
c := New()
c := New[int]()
c.Enqueue(1)
if !strings.HasPrefix(c.String(), "LinkedListQueue") {
t.Errorf("String should start with container name")
}
}
func benchmarkEnqueue(b *testing.B, queue *Queue, size int) {
func benchmarkEnqueue(b *testing.B, queue *Queue[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Enqueue(n)
@ -263,7 +263,7 @@ func benchmarkEnqueue(b *testing.B, queue *Queue, size int) {
}
}
func benchmarkDequeue(b *testing.B, queue *Queue, size int) {
func benchmarkDequeue(b *testing.B, queue *Queue[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Dequeue()
@ -274,7 +274,7 @@ func benchmarkDequeue(b *testing.B, queue *Queue, size int) {
func BenchmarkArrayQueueDequeue100(b *testing.B) {
b.StopTimer()
size := 100
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -285,7 +285,7 @@ func BenchmarkArrayQueueDequeue100(b *testing.B) {
func BenchmarkArrayQueueDequeue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -296,7 +296,7 @@ func BenchmarkArrayQueueDequeue1000(b *testing.B) {
func BenchmarkArrayQueueDequeue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -307,7 +307,7 @@ func BenchmarkArrayQueueDequeue10000(b *testing.B) {
func BenchmarkArrayQueueDequeue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -318,7 +318,7 @@ func BenchmarkArrayQueueDequeue100000(b *testing.B) {
func BenchmarkArrayQueueEnqueue100(b *testing.B) {
b.StopTimer()
size := 100
queue := New()
queue := New[int]()
b.StartTimer()
benchmarkEnqueue(b, queue, size)
}
@ -326,7 +326,7 @@ func BenchmarkArrayQueueEnqueue100(b *testing.B) {
func BenchmarkArrayQueueEnqueue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -337,7 +337,7 @@ func BenchmarkArrayQueueEnqueue1000(b *testing.B) {
func BenchmarkArrayQueueEnqueue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
@ -348,7 +348,7 @@ func BenchmarkArrayQueueEnqueue10000(b *testing.B) {
func BenchmarkArrayQueueEnqueue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := New()
queue := New[int]()
for n := 0; n < size; n++ {
queue.Enqueue(n)
}

@ -5,29 +5,29 @@
package linkedlistqueue
import (
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Queue)(nil)
var _ containers.JSONDeserializer = (*Queue)(nil)
var _ containers.JSONSerializer = (*Queue[int])(nil)
var _ containers.JSONDeserializer = (*Queue[int])(nil)
// ToJSON outputs the JSON representation of the queue.
func (queue *Queue) ToJSON() ([]byte, error) {
func (queue *Queue[T]) ToJSON() ([]byte, error) {
return queue.list.ToJSON()
}
// FromJSON populates the queue from the input JSON representation.
func (queue *Queue) FromJSON(data []byte) error {
func (queue *Queue[T]) FromJSON(data []byte) error {
return queue.list.FromJSON(data)
}
// UnmarshalJSON @implements json.Unmarshaler
func (queue *Queue) UnmarshalJSON(bytes []byte) error {
func (queue *Queue[T]) UnmarshalJSON(bytes []byte) error {
return queue.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (queue *Queue) MarshalJSON() ([]byte, error) {
func (queue *Queue[T]) MarshalJSON() ([]byte, error) {
return queue.ToJSON()
}

@ -5,73 +5,73 @@
package priorityqueue
import (
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/trees/binaryheap"
"github.com/emirpasic/gods/v2/containers"
"github.com/emirpasic/gods/v2/trees/binaryheap"
)
// Assert Iterator implementation
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator struct {
iterator binaryheap.Iterator
type Iterator[T comparable] struct {
iterator *binaryheap.Iterator[T]
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (queue *Queue) Iterator() Iterator {
return Iterator{iterator: queue.heap.Iterator()}
func (queue *Queue[T]) Iterator() *Iterator[T] {
return &Iterator[T]{iterator: queue.heap.Iterator()}
}
// 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 index and value can be retrieved by Index() 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 {
func (iterator *Iterator[T]) 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Prev() bool {
func (iterator *Iterator[T]) 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{} {
func (iterator *Iterator[T]) Value() T {
return iterator.iterator.Value()
}
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
func (iterator *Iterator[T]) Index() int {
return iterator.iterator.Index()
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
func (iterator *Iterator[T]) 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() {
func (iterator *Iterator[T]) 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
func (iterator *Iterator[T]) 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Last() bool {
func (iterator *Iterator[T]) Last() bool {
return iterator.iterator.Last()
}
@ -79,7 +79,7 @@ func (iterator *Iterator) Last() bool {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) NextTo(f func(index int, value T) bool) bool {
return iterator.iterator.NextTo(f)
}
@ -87,6 +87,6 @@ func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) PrevTo(f func(index int, value T) bool) bool {
return iterator.iterator.PrevTo(f)
}

@ -16,66 +16,72 @@
package priorityqueue
import (
"cmp"
"fmt"
"github.com/emirpasic/gods/queues"
"github.com/emirpasic/gods/trees/binaryheap"
"github.com/emirpasic/gods/utils"
"strings"
"github.com/emirpasic/gods/v2/queues"
"github.com/emirpasic/gods/v2/trees/binaryheap"
"github.com/emirpasic/gods/v2/utils"
)
// Assert Queue implementation
var _ queues.Queue = (*Queue)(nil)
var _ queues.Queue[int] = (*Queue[int])(nil)
// Queue holds elements in an array-list
type Queue struct {
heap *binaryheap.Heap
Comparator utils.Comparator
type Queue[T comparable] struct {
heap *binaryheap.Heap[T]
Comparator utils.Comparator[T]
}
func New[T cmp.Ordered]() *Queue[T] {
return NewWith[T](cmp.Compare[T])
}
// NewWith instantiates a new empty queue with the custom comparator.
func NewWith(comparator utils.Comparator) *Queue {
return &Queue{heap: binaryheap.NewWith(comparator), Comparator: comparator}
func NewWith[T comparable](comparator utils.Comparator[T]) *Queue[T] {
return &Queue[T]{heap: binaryheap.NewWith(comparator), Comparator: comparator}
}
// Enqueue adds a value to the end of the queue
func (queue *Queue) Enqueue(value interface{}) {
func (queue *Queue[T]) Enqueue(value T) {
queue.heap.Push(value)
}
// Dequeue removes first element of the queue and returns it, or nil if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to dequeue.
func (queue *Queue) Dequeue() (value interface{}, ok bool) {
func (queue *Queue[T]) Dequeue() (value T, ok bool) {
return queue.heap.Pop()
}
// Peek returns top element on the queue without removing it, or nil if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to peek.
func (queue *Queue) Peek() (value interface{}, ok bool) {
func (queue *Queue[T]) Peek() (value T, ok bool) {
return queue.heap.Peek()
}
// Empty returns true if queue does not contain any elements.
func (queue *Queue) Empty() bool {
func (queue *Queue[T]) Empty() bool {
return queue.heap.Empty()
}
// Size returns number of elements within the queue.
func (queue *Queue) Size() int {
func (queue *Queue[T]) Size() int {
return queue.heap.Size()
}
// Clear removes all elements from the queue.
func (queue *Queue) Clear() {
func (queue *Queue[T]) Clear() {
queue.heap.Clear()
}
// Values returns all elements in the queue.
func (queue *Queue) Values() []interface{} {
func (queue *Queue[T]) Values() []T {
return queue.heap.Values()
}
// String returns a string representation of container
func (queue *Queue) String() string {
func (queue *Queue[T]) String() string {
str := "PriorityQueue\n"
values := make([]string, queue.heap.Size(), queue.heap.Size())
for index, value := range queue.heap.Values() {

@ -5,9 +5,9 @@
package priorityqueue
import (
"cmp"
"encoding/json"
"fmt"
"github.com/emirpasic/gods/utils"
"math/rand"
"strings"
"testing"
@ -23,15 +23,12 @@ func (element Element) String() string {
}
// Comparator function (sort by priority value in descending order)
func byPriority(a, b interface{}) int {
return -utils.IntComparator( // Note "-" for descending order
a.(Element).priority,
b.(Element).priority,
)
func byPriority(a, b Element) int {
return -cmp.Compare(a.priority, b.priority) // Note "-" for descending order
}
func TestBinaryQueueEnqueue(t *testing.T) {
queue := NewWith(byPriority)
queue := NewWith[Element](byPriority)
if actualValue := queue.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
@ -53,15 +50,15 @@ func TestBinaryQueueEnqueue(t *testing.T) {
value := it.Value()
switch index {
case 0:
if actualValue, expectedValue := value.(Element).name, "c"; actualValue != expectedValue {
if actualValue, expectedValue := value.name, "c"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 1:
if actualValue, expectedValue := value.(Element).name, "b"; actualValue != expectedValue {
if actualValue, expectedValue := value.name, "b"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 2:
if actualValue, expectedValue := value.(Element).name, "a"; actualValue != expectedValue {
if actualValue, expectedValue := value.name, "a"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
default:
@ -72,13 +69,13 @@ func TestBinaryQueueEnqueue(t *testing.T) {
}
}
if actualValue := queue.Values(); actualValue[0].(Element).name != "c" || actualValue[1].(Element).name != "b" || actualValue[2].(Element).name != "a" {
if actualValue := queue.Values(); actualValue[0].name != "c" || actualValue[1].name != "b" || actualValue[2].name != "a" {
t.Errorf("Got %v expected %v", actualValue, `[{3 c} {2 b} {1 a}]`)
}
}
func TestBinaryQueueEnqueueBulk(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue := New[int]()
queue.Enqueue(15)
queue.Enqueue(20)
@ -109,7 +106,7 @@ func TestBinaryQueueEnqueueBulk(t *testing.T) {
}
func TestBinaryQueueDequeue(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue := New[int]()
if actualValue := queue.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
@ -126,7 +123,7 @@ func TestBinaryQueueDequeue(t *testing.T) {
if actualValue, ok := queue.Dequeue(); actualValue != 3 || !ok {
t.Errorf("Got %v expected %v", actualValue, 3)
}
if actualValue, ok := queue.Dequeue(); actualValue != nil || ok {
if actualValue, ok := queue.Dequeue(); actualValue != 0 || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
if actualValue := queue.Empty(); actualValue != true {
@ -138,7 +135,7 @@ func TestBinaryQueueDequeue(t *testing.T) {
}
func TestBinaryQueueRandom(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue := New[int]()
rand.Seed(3)
for i := 0; i < 10000; i++ {
@ -149,7 +146,7 @@ func TestBinaryQueueRandom(t *testing.T) {
prev, _ := queue.Dequeue()
for !queue.Empty() {
curr, _ := queue.Dequeue()
if prev.(int) > curr.(int) {
if prev > curr {
t.Errorf("Queue property invalidated. prev: %v current: %v", prev, curr)
}
prev = curr
@ -157,7 +154,7 @@ func TestBinaryQueueRandom(t *testing.T) {
}
func TestBinaryQueueIteratorOnEmpty(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue := New[int]()
it := queue.Iterator()
for it.Next() {
t.Errorf("Shouldn't iterate on empty queue")
@ -165,7 +162,7 @@ func TestBinaryQueueIteratorOnEmpty(t *testing.T) {
}
func TestBinaryQueueIteratorNext(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue := New[int]()
queue.Enqueue(3)
queue.Enqueue(2)
queue.Enqueue(1)
@ -202,7 +199,7 @@ func TestBinaryQueueIteratorNext(t *testing.T) {
}
func TestBinaryQueueIteratorPrev(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue := New[int]()
queue.Enqueue(3)
queue.Enqueue(2)
queue.Enqueue(1)
@ -241,7 +238,7 @@ func TestBinaryQueueIteratorPrev(t *testing.T) {
}
func TestBinaryQueueIteratorBegin(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue := New[int]()
it := queue.Iterator()
it.Begin()
queue.Enqueue(2)
@ -257,7 +254,7 @@ func TestBinaryQueueIteratorBegin(t *testing.T) {
}
func TestBinaryQueueIteratorEnd(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue := New[int]()
it := queue.Iterator()
if index := it.Index(); index != -1 {
@ -284,7 +281,7 @@ func TestBinaryQueueIteratorEnd(t *testing.T) {
}
func TestBinaryQueueIteratorFirst(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue := New[int]()
it := queue.Iterator()
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -301,7 +298,7 @@ func TestBinaryQueueIteratorFirst(t *testing.T) {
}
func TestBinaryQueueIteratorLast(t *testing.T) {
tree := NewWith(utils.IntComparator)
tree := New[int]()
it := tree.Iterator()
if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -319,13 +316,13 @@ func TestBinaryQueueIteratorLast(t *testing.T) {
func TestBinaryQueueIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// NextTo (empty)
{
tree := NewWith(utils.StringComparator)
tree := New[string]()
it := tree.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
@ -334,7 +331,7 @@ func TestBinaryQueueIteratorNextTo(t *testing.T) {
// NextTo (not found)
{
tree := NewWith(utils.StringComparator)
tree := New[string]()
tree.Enqueue("xx")
tree.Enqueue("yy")
it := tree.Iterator()
@ -345,7 +342,7 @@ func TestBinaryQueueIteratorNextTo(t *testing.T) {
// NextTo (found)
{
tree := NewWith(utils.StringComparator)
tree := New[string]()
tree.Enqueue("aa")
tree.Enqueue("bb")
tree.Enqueue("cc")
@ -354,13 +351,13 @@ func TestBinaryQueueIteratorNextTo(t *testing.T) {
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 2 || value.(string) != "cc" {
if index, value := it.Index(), it.Value(); index != 2 || value != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
@ -371,13 +368,13 @@ func TestBinaryQueueIteratorNextTo(t *testing.T) {
func TestBinaryQueueIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// PrevTo (empty)
{
tree := NewWith(utils.StringComparator)
tree := New[string]()
it := tree.Iterator()
it.End()
for it.PrevTo(seek) {
@ -387,7 +384,7 @@ func TestBinaryQueueIteratorPrevTo(t *testing.T) {
// PrevTo (not found)
{
tree := NewWith(utils.StringComparator)
tree := New[string]()
tree.Enqueue("xx")
tree.Enqueue("yy")
it := tree.Iterator()
@ -399,7 +396,7 @@ func TestBinaryQueueIteratorPrevTo(t *testing.T) {
// PrevTo (found)
{
tree := NewWith(utils.StringComparator)
tree := New[string]()
tree.Enqueue("aa")
tree.Enqueue("bb")
tree.Enqueue("cc")
@ -408,13 +405,13 @@ func TestBinaryQueueIteratorPrevTo(t *testing.T) {
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 0 || value.(string) != "aa" {
if index, value := it.Index(), it.Value(); index != 0 || value != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
@ -424,7 +421,7 @@ func TestBinaryQueueIteratorPrevTo(t *testing.T) {
}
func TestBinaryQueueSerialization(t *testing.T) {
queue := NewWith(utils.StringComparator)
queue := New[string]()
queue.Enqueue("c")
queue.Enqueue("b")
@ -432,7 +429,7 @@ func TestBinaryQueueSerialization(t *testing.T) {
var err error
assert := func() {
if actualValue := queue.Values(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" {
if actualValue := queue.Values(); actualValue[0] != "a" || actualValue[1] != "b" || actualValue[2] != "c" {
t.Errorf("Got %v expected %v", actualValue, "[1,3,2]")
}
if actualValue := queue.Size(); actualValue != 3 {
@ -459,21 +456,22 @@ func TestBinaryQueueSerialization(t *testing.T) {
t.Errorf("Got error %v", err)
}
err = json.Unmarshal([]byte(`[1,2,3]`), &queue)
err = json.Unmarshal([]byte(`["a","b","c"]`), &queue)
if err != nil {
t.Errorf("Got error %v", err)
}
assert()
}
func TestBTreeString(t *testing.T) {
c := NewWith(byPriority)
c := New[int]()
c.Enqueue(1)
if !strings.HasPrefix(c.String(), "PriorityQueue") {
t.Errorf("String should start with container name")
}
}
func benchmarkEnqueue(b *testing.B, queue *Queue, size int) {
func benchmarkEnqueue(b *testing.B, queue *Queue[Element], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Enqueue(Element{})
@ -481,7 +479,7 @@ func benchmarkEnqueue(b *testing.B, queue *Queue, size int) {
}
}
func benchmarkDequeue(b *testing.B, queue *Queue, size int) {
func benchmarkDequeue(b *testing.B, queue *Queue[Element], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Dequeue()
@ -492,7 +490,7 @@ func benchmarkDequeue(b *testing.B, queue *Queue, size int) {
func BenchmarkBinaryQueueDequeue100(b *testing.B) {
b.StopTimer()
size := 100
queue := NewWith(byPriority)
queue := NewWith[Element](byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(Element{})
}
@ -503,7 +501,7 @@ func BenchmarkBinaryQueueDequeue100(b *testing.B) {
func BenchmarkBinaryQueueDequeue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := NewWith(byPriority)
queue := NewWith[Element](byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(Element{})
}
@ -514,7 +512,7 @@ func BenchmarkBinaryQueueDequeue1000(b *testing.B) {
func BenchmarkBinaryQueueDequeue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := NewWith(byPriority)
queue := NewWith[Element](byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(Element{})
}
@ -525,7 +523,7 @@ func BenchmarkBinaryQueueDequeue10000(b *testing.B) {
func BenchmarkBinaryQueueDequeue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := NewWith(byPriority)
queue := NewWith[Element](byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(Element{})
}
@ -544,7 +542,7 @@ func BenchmarkBinaryQueueEnqueue100(b *testing.B) {
func BenchmarkBinaryQueueEnqueue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := NewWith(byPriority)
queue := NewWith[Element](byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(Element{})
}
@ -555,7 +553,7 @@ func BenchmarkBinaryQueueEnqueue1000(b *testing.B) {
func BenchmarkBinaryQueueEnqueue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := NewWith(byPriority)
queue := NewWith[Element](byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(Element{})
}
@ -566,7 +564,7 @@ func BenchmarkBinaryQueueEnqueue10000(b *testing.B) {
func BenchmarkBinaryQueueEnqueue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := NewWith(byPriority)
queue := NewWith[Element](byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(Element{})
}

@ -5,29 +5,29 @@
package priorityqueue
import (
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Queue)(nil)
var _ containers.JSONDeserializer = (*Queue)(nil)
var _ containers.JSONSerializer = (*Queue[int])(nil)
var _ containers.JSONDeserializer = (*Queue[int])(nil)
// ToJSON outputs the JSON representation of the queue.
func (queue *Queue) ToJSON() ([]byte, error) {
func (queue *Queue[T]) ToJSON() ([]byte, error) {
return queue.heap.ToJSON()
}
// FromJSON populates the queue from the input JSON representation.
func (queue *Queue) FromJSON(data []byte) error {
func (queue *Queue[T]) FromJSON(data []byte) error {
return queue.heap.FromJSON(data)
}
// UnmarshalJSON @implements json.Unmarshaler
func (queue *Queue) UnmarshalJSON(bytes []byte) error {
func (queue *Queue[T]) UnmarshalJSON(bytes []byte) error {
return queue.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (queue *Queue) MarshalJSON() ([]byte, error) {
func (queue *Queue[T]) MarshalJSON() ([]byte, error) {
return queue.ToJSON()
}

@ -10,15 +10,15 @@
// Reference: https://en.wikipedia.org/wiki/Queue_(abstract_data_type)
package queues
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Queue interface that all queues implement
type Queue interface {
Enqueue(value interface{})
Dequeue() (value interface{}, ok bool)
Peek() (value interface{}, ok bool)
type Queue[T comparable] interface {
Enqueue(value T)
Dequeue() (value T, ok bool)
Peek() (value T, ok bool)
containers.Container
containers.Container[T]
// Empty() bool
// Size() int
// Clear()

@ -11,23 +11,24 @@ package hashset
import (
"fmt"
"github.com/emirpasic/gods/sets"
"strings"
"github.com/emirpasic/gods/v2/sets"
)
// Assert Set implementation
var _ sets.Set = (*Set)(nil)
var _ sets.Set[int] = (*Set[int])(nil)
// Set holds elements in go's native map
type Set struct {
items map[interface{}]struct{}
type Set[T comparable] struct {
items map[T]struct{}
}
var itemExists = struct{}{}
// New instantiates a new empty set and adds the passed values, if any, to the set
func New(values ...interface{}) *Set {
set := &Set{items: make(map[interface{}]struct{})}
func New[T comparable](values ...T) *Set[T] {
set := &Set[T]{items: make(map[T]struct{})}
if len(values) > 0 {
set.Add(values...)
}
@ -35,14 +36,14 @@ func New(values ...interface{}) *Set {
}
// Add adds the items (one or more) to the set.
func (set *Set) Add(items ...interface{}) {
func (set *Set[T]) Add(items ...T) {
for _, item := range items {
set.items[item] = itemExists
}
}
// Remove removes the items (one or more) from the set.
func (set *Set) Remove(items ...interface{}) {
func (set *Set[T]) Remove(items ...T) {
for _, item := range items {
delete(set.items, item)
}
@ -51,7 +52,7 @@ func (set *Set) Remove(items ...interface{}) {
// Contains check if items (one or more) are present in the set.
// All items have to be present in the set for the method to return true.
// 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[T]) Contains(items ...T) bool {
for _, item := range items {
if _, contains := set.items[item]; !contains {
return false
@ -61,23 +62,23 @@ func (set *Set) Contains(items ...interface{}) bool {
}
// Empty returns true if set does not contain any elements.
func (set *Set) Empty() bool {
func (set *Set[T]) Empty() bool {
return set.Size() == 0
}
// Size returns number of elements within the set.
func (set *Set) Size() int {
func (set *Set[T]) Size() int {
return len(set.items)
}
// Clear clears all values in the set.
func (set *Set) Clear() {
set.items = make(map[interface{}]struct{})
func (set *Set[T]) Clear() {
set.items = make(map[T]struct{})
}
// Values returns all items in the set.
func (set *Set) Values() []interface{} {
values := make([]interface{}, set.Size())
func (set *Set[T]) Values() []T {
values := make([]T, set.Size())
count := 0
for item := range set.items {
values[count] = item
@ -87,7 +88,7 @@ func (set *Set) Values() []interface{} {
}
// String returns a string representation of container
func (set *Set) String() string {
func (set *Set[T]) String() string {
str := "HashSet\n"
items := []string{}
for k := range set.items {
@ -100,8 +101,8 @@ func (set *Set) String() string {
// Intersection returns the intersection between two sets.
// The new set consists of all elements that are both in "set" and "another".
// Ref: https://en.wikipedia.org/wiki/Intersection_(set_theory)
func (set *Set) Intersection(another *Set) *Set {
result := New()
func (set *Set[T]) Intersection(another *Set[T]) *Set[T] {
result := New[T]()
// Iterate over smaller set (optimization)
if set.Size() <= another.Size() {
@ -124,8 +125,8 @@ func (set *Set) Intersection(another *Set) *Set {
// Union returns the union of two sets.
// The new set consists of all elements that are in "set" or "another" (possibly both).
// Ref: https://en.wikipedia.org/wiki/Union_(set_theory)
func (set *Set) Union(another *Set) *Set {
result := New()
func (set *Set[T]) Union(another *Set[T]) *Set[T] {
result := New[T]()
for item := range set.items {
result.Add(item)
@ -140,8 +141,8 @@ func (set *Set) Union(another *Set) *Set {
// Difference returns the difference between two sets.
// The new set consists of all elements that are in "set" but not in "another".
// Ref: https://proofwiki.org/wiki/Definition:Set_Difference
func (set *Set) Difference(another *Set) *Set {
result := New()
func (set *Set[T]) Difference(another *Set[T]) *Set[T] {
result := New[T]()
for item := range set.items {
if _, contains := another.items[item]; !contains {

@ -28,7 +28,7 @@ func TestSetNew(t *testing.T) {
}
func TestSetAdd(t *testing.T) {
set := New()
set := New[int]()
set.Add()
set.Add(1)
set.Add(2)
@ -43,7 +43,7 @@ func TestSetAdd(t *testing.T) {
}
func TestSetContains(t *testing.T) {
set := New()
set := New[int]()
set.Add(3, 1, 2)
set.Add(2, 3)
set.Add()
@ -62,7 +62,7 @@ func TestSetContains(t *testing.T) {
}
func TestSetRemove(t *testing.T) {
set := New()
set := New[int]()
set.Add(3, 1, 2)
set.Remove()
if actualValue := set.Size(); actualValue != 3 {
@ -82,7 +82,7 @@ func TestSetRemove(t *testing.T) {
}
func TestSetSerialization(t *testing.T) {
set := New()
set := New[string]()
set.Add("a", "b", "c")
var err error
@ -111,14 +111,15 @@ func TestSetSerialization(t *testing.T) {
t.Errorf("Got error %v", err)
}
err = json.Unmarshal([]byte(`[1,2,3]`), &set)
err = json.Unmarshal([]byte(`["a","b","c"]`), &set)
if err != nil {
t.Errorf("Got error %v", err)
}
assert()
}
func TestSetString(t *testing.T) {
c := New()
c := New[int]()
c.Add(1)
if !strings.HasPrefix(c.String(), "HashSet") {
t.Errorf("String should start with container name")
@ -126,8 +127,8 @@ func TestSetString(t *testing.T) {
}
func TestSetIntersection(t *testing.T) {
set := New()
another := New()
set := New[string]()
another := New[string]()
intersection := set.Intersection(another)
if actualValue, expectedValue := intersection.Size(), 0; actualValue != expectedValue {
@ -148,8 +149,8 @@ func TestSetIntersection(t *testing.T) {
}
func TestSetUnion(t *testing.T) {
set := New()
another := New()
set := New[string]()
another := New[string]()
union := set.Union(another)
if actualValue, expectedValue := union.Size(), 0; actualValue != expectedValue {
@ -170,8 +171,8 @@ func TestSetUnion(t *testing.T) {
}
func TestSetDifference(t *testing.T) {
set := New()
another := New()
set := New[string]()
another := New[string]()
difference := set.Difference(another)
if actualValue, expectedValue := difference.Size(), 0; actualValue != expectedValue {
@ -191,7 +192,7 @@ func TestSetDifference(t *testing.T) {
}
}
func benchmarkContains(b *testing.B, set *Set, size int) {
func benchmarkContains(b *testing.B, set *Set[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
set.Contains(n)
@ -199,7 +200,7 @@ func benchmarkContains(b *testing.B, set *Set, size int) {
}
}
func benchmarkAdd(b *testing.B, set *Set, size int) {
func benchmarkAdd(b *testing.B, set *Set[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
set.Add(n)
@ -207,7 +208,7 @@ func benchmarkAdd(b *testing.B, set *Set, size int) {
}
}
func benchmarkRemove(b *testing.B, set *Set, size int) {
func benchmarkRemove(b *testing.B, set *Set[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
set.Remove(n)
@ -218,7 +219,7 @@ func benchmarkRemove(b *testing.B, set *Set, size int) {
func BenchmarkHashSetContains100(b *testing.B) {
b.StopTimer()
size := 100
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -229,7 +230,7 @@ func BenchmarkHashSetContains100(b *testing.B) {
func BenchmarkHashSetContains1000(b *testing.B) {
b.StopTimer()
size := 1000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -240,7 +241,7 @@ func BenchmarkHashSetContains1000(b *testing.B) {
func BenchmarkHashSetContains10000(b *testing.B) {
b.StopTimer()
size := 10000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -251,7 +252,7 @@ func BenchmarkHashSetContains10000(b *testing.B) {
func BenchmarkHashSetContains100000(b *testing.B) {
b.StopTimer()
size := 100000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -262,7 +263,7 @@ func BenchmarkHashSetContains100000(b *testing.B) {
func BenchmarkHashSetAdd100(b *testing.B) {
b.StopTimer()
size := 100
set := New()
set := New[int]()
b.StartTimer()
benchmarkAdd(b, set, size)
}
@ -270,7 +271,7 @@ func BenchmarkHashSetAdd100(b *testing.B) {
func BenchmarkHashSetAdd1000(b *testing.B) {
b.StopTimer()
size := 1000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -281,7 +282,7 @@ func BenchmarkHashSetAdd1000(b *testing.B) {
func BenchmarkHashSetAdd10000(b *testing.B) {
b.StopTimer()
size := 10000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -292,7 +293,7 @@ func BenchmarkHashSetAdd10000(b *testing.B) {
func BenchmarkHashSetAdd100000(b *testing.B) {
b.StopTimer()
size := 100000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -303,7 +304,7 @@ func BenchmarkHashSetAdd100000(b *testing.B) {
func BenchmarkHashSetRemove100(b *testing.B) {
b.StopTimer()
size := 100
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -314,7 +315,7 @@ func BenchmarkHashSetRemove100(b *testing.B) {
func BenchmarkHashSetRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -325,7 +326,7 @@ func BenchmarkHashSetRemove1000(b *testing.B) {
func BenchmarkHashSetRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -336,7 +337,7 @@ func BenchmarkHashSetRemove10000(b *testing.B) {
func BenchmarkHashSetRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}

@ -6,21 +6,22 @@ package hashset
import (
"encoding/json"
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Set)(nil)
var _ containers.JSONDeserializer = (*Set)(nil)
var _ containers.JSONSerializer = (*Set[int])(nil)
var _ containers.JSONDeserializer = (*Set[int])(nil)
// ToJSON outputs the JSON representation of the set.
func (set *Set) ToJSON() ([]byte, error) {
func (set *Set[T]) ToJSON() ([]byte, error) {
return json.Marshal(set.Values())
}
// FromJSON populates the set from the input JSON representation.
func (set *Set) FromJSON(data []byte) error {
elements := []interface{}{}
func (set *Set[T]) FromJSON(data []byte) error {
var elements []T
err := json.Unmarshal(data, &elements)
if err == nil {
set.Clear()
@ -30,11 +31,11 @@ func (set *Set) FromJSON(data []byte) error {
}
// UnmarshalJSON @implements json.Unmarshaler
func (set *Set) UnmarshalJSON(bytes []byte) error {
func (set *Set[T]) UnmarshalJSON(bytes []byte) error {
return set.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (set *Set) MarshalJSON() ([]byte, error) {
func (set *Set[T]) MarshalJSON() ([]byte, error) {
return set.ToJSON()
}

@ -4,13 +4,13 @@
package linkedhashset
import "github.com/emirpasic/gods/containers"
import "github.com/emirpasic/gods/v2/containers"
// Assert Enumerable implementation
var _ containers.EnumerableWithIndex = (*Set)(nil)
var _ containers.EnumerableWithIndex[int] = (*Set[int])(nil)
// Each calls the given function once for each element, passing that element's index and value.
func (set *Set) Each(f func(index int, value interface{})) {
func (set *Set[T]) Each(f func(index int, value T)) {
iterator := set.Iterator()
for iterator.Next() {
f(iterator.Index(), iterator.Value())
@ -19,8 +19,8 @@ func (set *Set) Each(f func(index int, value interface{})) {
// Map invokes the given function once for each element and returns a
// container containing the values returned by the given function.
func (set *Set) Map(f func(index int, value interface{}) interface{}) *Set {
newSet := New()
func (set *Set[T]) Map(f func(index int, value T) T) *Set[T] {
newSet := New[T]()
iterator := set.Iterator()
for iterator.Next() {
newSet.Add(f(iterator.Index(), iterator.Value()))
@ -29,8 +29,8 @@ func (set *Set) Map(f func(index int, value interface{}) interface{}) *Set {
}
// Select returns a new container containing all elements for which the given function returns a true value.
func (set *Set) Select(f func(index int, value interface{}) bool) *Set {
newSet := New()
func (set *Set[T]) Select(f func(index int, value T) bool) *Set[T] {
newSet := New[T]()
iterator := set.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
@ -42,7 +42,7 @@ func (set *Set) Select(f func(index int, value interface{}) bool) *Set {
// Any passes each element of the container to the given function and
// returns true if the function ever returns true for any element.
func (set *Set) Any(f func(index int, value interface{}) bool) bool {
func (set *Set[T]) Any(f func(index int, value T) bool) bool {
iterator := set.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
@ -54,7 +54,7 @@ func (set *Set) Any(f func(index int, value interface{}) bool) bool {
// All passes each element of the container to the given function and
// returns true if the function returns true for all elements.
func (set *Set) All(f func(index int, value interface{}) bool) bool {
func (set *Set[T]) All(f func(index int, value T) bool) bool {
iterator := set.Iterator()
for iterator.Next() {
if !f(iterator.Index(), iterator.Value()) {
@ -67,12 +67,13 @@ func (set *Set) All(f func(index int, value interface{}) bool) bool {
// Find passes each element of the container to the given function and returns
// the first (index,value) for which the function is true or -1,nil otherwise
// if no element matches the criteria.
func (set *Set) Find(f func(index int, value interface{}) bool) (int, interface{}) {
func (set *Set[T]) Find(f func(index int, value T) bool) (int, T) {
iterator := set.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
return iterator.Index(), iterator.Value()
}
}
return -1, nil
var t T
return -1, t
}

@ -5,73 +5,73 @@
package linkedhashset
import (
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/lists/doublylinkedlist"
"github.com/emirpasic/gods/v2/containers"
"github.com/emirpasic/gods/v2/lists/doublylinkedlist"
)
// Assert Iterator implementation
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
var _ containers.ReverseIteratorWithIndex[int] = (*Iterator[int])(nil)
// Iterator holding the iterator's state
type Iterator struct {
iterator doublylinkedlist.Iterator
type Iterator[T comparable] struct {
iterator doublylinkedlist.Iterator[T]
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (set *Set) Iterator() Iterator {
return Iterator{iterator: set.ordering.Iterator()}
func (set *Set[T]) Iterator() Iterator[T] {
return Iterator[T]{iterator: set.ordering.Iterator()}
}
// 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 index and value can be retrieved by Index() 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 {
func (iterator *Iterator[T]) 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Prev() bool {
func (iterator *Iterator[T]) 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{} {
func (iterator *Iterator[T]) Value() T {
return iterator.iterator.Value()
}
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
func (iterator *Iterator[T]) Index() int {
return iterator.iterator.Index()
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
func (iterator *Iterator[T]) 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() {
func (iterator *Iterator[T]) 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
func (iterator *Iterator[T]) 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 index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Last() bool {
func (iterator *Iterator[T]) Last() bool {
return iterator.iterator.Last()
}
@ -79,7 +79,7 @@ func (iterator *Iterator) Last() bool {
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) NextTo(f func(index int, value T) bool) bool {
for iterator.Next() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
@ -93,7 +93,7 @@ func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool {
func (iterator *Iterator[T]) PrevTo(f func(index int, value T) bool) bool {
for iterator.Prev() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {

@ -15,27 +15,28 @@ package linkedhashset
import (
"fmt"
"github.com/emirpasic/gods/lists/doublylinkedlist"
"github.com/emirpasic/gods/sets"
"strings"
"github.com/emirpasic/gods/v2/lists/doublylinkedlist"
"github.com/emirpasic/gods/v2/sets"
)
// Assert Set implementation
var _ sets.Set = (*Set)(nil)
var _ sets.Set[int] = (*Set[int])(nil)
// Set holds elements in go's native map
type Set struct {
table map[interface{}]struct{}
ordering *doublylinkedlist.List
type Set[T comparable] struct {
table map[T]struct{}
ordering *doublylinkedlist.List[T]
}
var itemExists = struct{}{}
// New instantiates a new empty set and adds the passed values, if any, to the set
func New(values ...interface{}) *Set {
set := &Set{
table: make(map[interface{}]struct{}),
ordering: doublylinkedlist.New(),
func New[T comparable](values ...T) *Set[T] {
set := &Set[T]{
table: make(map[T]struct{}),
ordering: doublylinkedlist.New[T](),
}
if len(values) > 0 {
set.Add(values...)
@ -45,7 +46,7 @@ func New(values ...interface{}) *Set {
// Add adds the items (one or more) to 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[T]) Add(items ...T) {
for _, item := range items {
if _, contains := set.table[item]; !contains {
set.table[item] = itemExists
@ -56,7 +57,7 @@ func (set *Set) Add(items ...interface{}) {
// Remove removes the items (one or more) from the set.
// Slow operation, worst-case O(n^2).
func (set *Set) Remove(items ...interface{}) {
func (set *Set[T]) Remove(items ...T) {
for _, item := range items {
if _, contains := set.table[item]; contains {
delete(set.table, item)
@ -69,7 +70,7 @@ func (set *Set) Remove(items ...interface{}) {
// Contains check if items (one or more) are present in the set.
// All items have to be present in the set for the method to return true.
// 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[T]) Contains(items ...T) bool {
for _, item := range items {
if _, contains := set.table[item]; !contains {
return false
@ -79,24 +80,24 @@ func (set *Set) Contains(items ...interface{}) bool {
}
// Empty returns true if set does not contain any elements.
func (set *Set) Empty() bool {
func (set *Set[T]) Empty() bool {
return set.Size() == 0
}
// Size returns number of elements within the set.
func (set *Set) Size() int {
func (set *Set[T]) Size() int {
return set.ordering.Size()
}
// Clear clears all values in the set.
func (set *Set) Clear() {
set.table = make(map[interface{}]struct{})
func (set *Set[T]) Clear() {
set.table = make(map[T]struct{})
set.ordering.Clear()
}
// Values returns all items in the set.
func (set *Set) Values() []interface{} {
values := make([]interface{}, set.Size())
func (set *Set[T]) Values() []T {
values := make([]T, set.Size())
it := set.Iterator()
for it.Next() {
values[it.Index()] = it.Value()
@ -105,7 +106,7 @@ func (set *Set) Values() []interface{} {
}
// String returns a string representation of container
func (set *Set) String() string {
func (set *Set[T]) String() string {
str := "LinkedHashSet\n"
items := []string{}
it := set.Iterator()
@ -119,8 +120,8 @@ func (set *Set) String() string {
// Intersection returns the intersection between two sets.
// The new set consists of all elements that are both in "set" and "another".
// Ref: https://en.wikipedia.org/wiki/Intersection_(set_theory)
func (set *Set) Intersection(another *Set) *Set {
result := New()
func (set *Set[T]) Intersection(another *Set[T]) *Set[T] {
result := New[T]()
// Iterate over smaller set (optimization)
if set.Size() <= another.Size() {
@ -143,8 +144,8 @@ func (set *Set) Intersection(another *Set) *Set {
// Union returns the union of two sets.
// The new set consists of all elements that are in "set" or "another" (possibly both).
// Ref: https://en.wikipedia.org/wiki/Union_(set_theory)
func (set *Set) Union(another *Set) *Set {
result := New()
func (set *Set[T]) Union(another *Set[T]) *Set[T] {
result := New[T]()
for item := range set.table {
result.Add(item)
@ -159,8 +160,8 @@ func (set *Set) Union(another *Set) *Set {
// Difference returns the difference between two sets.
// The new set consists of all elements that are in "set" but not in "another".
// Ref: https://proofwiki.org/wiki/Definition:Set_Difference
func (set *Set) Difference(another *Set) *Set {
result := New()
func (set *Set[T]) Difference(another *Set[T]) *Set[T] {
result := New[T]()
for item := range set.table {
if _, contains := another.table[item]; !contains {

@ -13,20 +13,23 @@ import (
func TestSetNew(t *testing.T) {
set := New(2, 1)
if actualValue := set.Size(); actualValue != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
}
values := set.Values()
if actualValue := values[0]; actualValue != 2 {
t.Errorf("Got %v expected %v", actualValue, 2)
if actualValue := set.Contains(1); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
if actualValue := values[1]; actualValue != 1 {
t.Errorf("Got %v expected %v", actualValue, 1)
if actualValue := set.Contains(2); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
if actualValue := set.Contains(3); actualValue != false {
t.Errorf("Got %v expected %v", actualValue, true)
}
}
func TestSetAdd(t *testing.T) {
set := New()
set := New[int]()
set.Add()
set.Add(1)
set.Add(2)
@ -41,7 +44,7 @@ func TestSetAdd(t *testing.T) {
}
func TestSetContains(t *testing.T) {
set := New()
set := New[int]()
set.Add(3, 1, 2)
set.Add(2, 3)
set.Add()
@ -60,7 +63,7 @@ func TestSetContains(t *testing.T) {
}
func TestSetRemove(t *testing.T) {
set := New()
set := New[int]()
set.Add(3, 1, 2)
set.Remove()
if actualValue := set.Size(); actualValue != 3 {
@ -80,9 +83,9 @@ func TestSetRemove(t *testing.T) {
}
func TestSetEach(t *testing.T) {
set := New()
set := New[string]()
set.Add("c", "a", "b")
set.Each(func(index int, value interface{}) {
set.Each(func(index int, value string) {
switch index {
case 0:
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
@ -103,10 +106,10 @@ func TestSetEach(t *testing.T) {
}
func TestSetMap(t *testing.T) {
set := New()
set := New[string]()
set.Add("c", "a", "b")
mappedSet := set.Map(func(index int, value interface{}) interface{} {
return "mapped: " + value.(string)
mappedSet := set.Map(func(index int, value string) string {
return "mapped: " + value
})
if actualValue, expectedValue := mappedSet.Contains("mapped: c", "mapped: b", "mapped: a"), true; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
@ -120,10 +123,10 @@ func TestSetMap(t *testing.T) {
}
func TestSetSelect(t *testing.T) {
set := New()
set := New[string]()
set.Add("c", "a", "b")
selectedSet := set.Select(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "b"
selectedSet := set.Select(func(index int, value string) bool {
return value >= "a" && value <= "b"
})
if actualValue, expectedValue := selectedSet.Contains("a", "b"), true; actualValue != expectedValue {
fmt.Println("A: ", selectedSet.Contains("b"))
@ -138,16 +141,16 @@ func TestSetSelect(t *testing.T) {
}
func TestSetAny(t *testing.T) {
set := New()
set := New[string]()
set.Add("c", "a", "b")
any := set.Any(func(index int, value interface{}) bool {
return value.(string) == "c"
any := set.Any(func(index int, value string) bool {
return value == "c"
})
if any != true {
t.Errorf("Got %v expected %v", any, true)
}
any = set.Any(func(index int, value interface{}) bool {
return value.(string) == "x"
any = set.Any(func(index int, value string) bool {
return value == "x"
})
if any != false {
t.Errorf("Got %v expected %v", any, false)
@ -155,16 +158,16 @@ func TestSetAny(t *testing.T) {
}
func TestSetAll(t *testing.T) {
set := New()
set := New[string]()
set.Add("c", "a", "b")
all := set.All(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "c"
all := set.All(func(index int, value string) bool {
return value >= "a" && value <= "c"
})
if all != true {
t.Errorf("Got %v expected %v", all, true)
}
all = set.All(func(index int, value interface{}) bool {
return value.(string) >= "a" && value.(string) <= "b"
all = set.All(func(index int, value string) bool {
return value >= "a" && value <= "b"
})
if all != false {
t.Errorf("Got %v expected %v", all, false)
@ -172,29 +175,29 @@ func TestSetAll(t *testing.T) {
}
func TestSetFind(t *testing.T) {
set := New()
set := New[string]()
set.Add("c", "a", "b")
foundIndex, foundValue := set.Find(func(index int, value interface{}) bool {
return value.(string) == "c"
foundIndex, foundValue := set.Find(func(index int, value string) bool {
return value == "c"
})
if foundValue != "c" || foundIndex != 0 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, "c", 0)
}
foundIndex, foundValue = set.Find(func(index int, value interface{}) bool {
return value.(string) == "x"
foundIndex, foundValue = set.Find(func(index int, value string) bool {
return value == "x"
})
if foundValue != nil || foundIndex != -1 {
if foundValue != "" || foundIndex != -1 {
t.Errorf("Got %v at %v expected %v at %v", foundValue, foundIndex, nil, nil)
}
}
func TestSetChaining(t *testing.T) {
set := New()
set := New[string]()
set.Add("c", "a", "b")
}
func TestSetIteratorPrevOnEmpty(t *testing.T) {
set := New()
set := New[string]()
it := set.Iterator()
for it.Prev() {
t.Errorf("Shouldn't iterate on empty set")
@ -202,7 +205,7 @@ func TestSetIteratorPrevOnEmpty(t *testing.T) {
}
func TestSetIteratorNext(t *testing.T) {
set := New()
set := New[string]()
set.Add("c", "a", "b")
it := set.Iterator()
count := 0
@ -236,7 +239,7 @@ func TestSetIteratorNext(t *testing.T) {
}
func TestSetIteratorPrev(t *testing.T) {
set := New()
set := New[string]()
set.Add("c", "a", "b")
it := set.Iterator()
for it.Prev() {
@ -272,7 +275,7 @@ func TestSetIteratorPrev(t *testing.T) {
}
func TestSetIteratorBegin(t *testing.T) {
set := New()
set := New[string]()
it := set.Iterator()
it.Begin()
set.Add("a", "b", "c")
@ -286,7 +289,7 @@ func TestSetIteratorBegin(t *testing.T) {
}
func TestSetIteratorEnd(t *testing.T) {
set := New()
set := New[string]()
it := set.Iterator()
if index := it.Index(); index != -1 {
@ -311,7 +314,7 @@ func TestSetIteratorEnd(t *testing.T) {
}
func TestSetIteratorFirst(t *testing.T) {
set := New()
set := New[string]()
set.Add("a", "b", "c")
it := set.Iterator()
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
@ -323,7 +326,7 @@ func TestSetIteratorFirst(t *testing.T) {
}
func TestSetIteratorLast(t *testing.T) {
set := New()
set := New[string]()
set.Add("a", "b", "c")
it := set.Iterator()
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
@ -336,13 +339,13 @@ func TestSetIteratorLast(t *testing.T) {
func TestSetIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// NextTo (empty)
{
set := New()
set := New[string]()
it := set.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty set")
@ -351,7 +354,7 @@ func TestSetIteratorNextTo(t *testing.T) {
// NextTo (not found)
{
set := New()
set := New[string]()
set.Add("xx", "yy")
it := set.Iterator()
for it.NextTo(seek) {
@ -361,20 +364,20 @@ func TestSetIteratorNextTo(t *testing.T) {
// NextTo (found)
{
set := New()
set := New[string]()
set.Add("aa", "bb", "cc")
it := set.Iterator()
it.Begin()
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty set")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 2 || value.(string) != "cc" {
if index, value := it.Index(), it.Value(); index != 2 || value != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
@ -385,13 +388,13 @@ func TestSetIteratorNextTo(t *testing.T) {
func TestSetIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
seek := func(index int, value string) bool {
return strings.HasSuffix(value, "b")
}
// PrevTo (empty)
{
set := New()
set := New[string]()
it := set.Iterator()
it.End()
for it.PrevTo(seek) {
@ -401,7 +404,7 @@ func TestSetIteratorPrevTo(t *testing.T) {
// PrevTo (not found)
{
set := New()
set := New[string]()
set.Add("xx", "yy")
it := set.Iterator()
it.End()
@ -412,20 +415,20 @@ func TestSetIteratorPrevTo(t *testing.T) {
// PrevTo (found)
{
set := New()
set := New[string]()
set.Add("aa", "bb", "cc")
it := set.Iterator()
it.End()
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty set")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
if index, value := it.Index(), it.Value(); index != 1 || value != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 0 || value.(string) != "aa" {
if index, value := it.Index(), it.Value(); index != 0 || value != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
@ -435,7 +438,7 @@ func TestSetIteratorPrevTo(t *testing.T) {
}
func TestSetSerialization(t *testing.T) {
set := New()
set := New[string]()
set.Add("a", "b", "c")
var err error
@ -464,14 +467,15 @@ func TestSetSerialization(t *testing.T) {
t.Errorf("Got error %v", err)
}
err = json.Unmarshal([]byte(`[1,2,3]`), &set)
err = json.Unmarshal([]byte(`["a","b","c"]`), &set)
if err != nil {
t.Errorf("Got error %v", err)
}
assert()
}
func TestSetString(t *testing.T) {
c := New()
c := New[int]()
c.Add(1)
if !strings.HasPrefix(c.String(), "LinkedHashSet") {
t.Errorf("String should start with container name")
@ -479,8 +483,8 @@ func TestSetString(t *testing.T) {
}
func TestSetIntersection(t *testing.T) {
set := New()
another := New()
set := New[string]()
another := New[string]()
intersection := set.Intersection(another)
if actualValue, expectedValue := intersection.Size(), 0; actualValue != expectedValue {
@ -501,8 +505,8 @@ func TestSetIntersection(t *testing.T) {
}
func TestSetUnion(t *testing.T) {
set := New()
another := New()
set := New[string]()
another := New[string]()
union := set.Union(another)
if actualValue, expectedValue := union.Size(), 0; actualValue != expectedValue {
@ -523,8 +527,8 @@ func TestSetUnion(t *testing.T) {
}
func TestSetDifference(t *testing.T) {
set := New()
another := New()
set := New[string]()
another := New[string]()
difference := set.Difference(another)
if actualValue, expectedValue := difference.Size(), 0; actualValue != expectedValue {
@ -544,7 +548,7 @@ func TestSetDifference(t *testing.T) {
}
}
func benchmarkContains(b *testing.B, set *Set, size int) {
func benchmarkContains(b *testing.B, set *Set[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
set.Contains(n)
@ -552,7 +556,7 @@ func benchmarkContains(b *testing.B, set *Set, size int) {
}
}
func benchmarkAdd(b *testing.B, set *Set, size int) {
func benchmarkAdd(b *testing.B, set *Set[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
set.Add(n)
@ -560,7 +564,7 @@ func benchmarkAdd(b *testing.B, set *Set, size int) {
}
}
func benchmarkRemove(b *testing.B, set *Set, size int) {
func benchmarkRemove(b *testing.B, set *Set[int], size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
set.Remove(n)
@ -571,7 +575,7 @@ func benchmarkRemove(b *testing.B, set *Set, size int) {
func BenchmarkHashSetContains100(b *testing.B) {
b.StopTimer()
size := 100
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -582,7 +586,7 @@ func BenchmarkHashSetContains100(b *testing.B) {
func BenchmarkHashSetContains1000(b *testing.B) {
b.StopTimer()
size := 1000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -593,7 +597,7 @@ func BenchmarkHashSetContains1000(b *testing.B) {
func BenchmarkHashSetContains10000(b *testing.B) {
b.StopTimer()
size := 10000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -604,7 +608,7 @@ func BenchmarkHashSetContains10000(b *testing.B) {
func BenchmarkHashSetContains100000(b *testing.B) {
b.StopTimer()
size := 100000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -615,7 +619,7 @@ func BenchmarkHashSetContains100000(b *testing.B) {
func BenchmarkHashSetAdd100(b *testing.B) {
b.StopTimer()
size := 100
set := New()
set := New[int]()
b.StartTimer()
benchmarkAdd(b, set, size)
}
@ -623,7 +627,7 @@ func BenchmarkHashSetAdd100(b *testing.B) {
func BenchmarkHashSetAdd1000(b *testing.B) {
b.StopTimer()
size := 1000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -634,7 +638,7 @@ func BenchmarkHashSetAdd1000(b *testing.B) {
func BenchmarkHashSetAdd10000(b *testing.B) {
b.StopTimer()
size := 10000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -645,7 +649,7 @@ func BenchmarkHashSetAdd10000(b *testing.B) {
func BenchmarkHashSetAdd100000(b *testing.B) {
b.StopTimer()
size := 100000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -656,7 +660,7 @@ func BenchmarkHashSetAdd100000(b *testing.B) {
func BenchmarkHashSetRemove100(b *testing.B) {
b.StopTimer()
size := 100
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -667,7 +671,7 @@ func BenchmarkHashSetRemove100(b *testing.B) {
func BenchmarkHashSetRemove1000(b *testing.B) {
b.StopTimer()
size := 1000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -678,7 +682,7 @@ func BenchmarkHashSetRemove1000(b *testing.B) {
func BenchmarkHashSetRemove10000(b *testing.B) {
b.StopTimer()
size := 10000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}
@ -689,7 +693,7 @@ func BenchmarkHashSetRemove10000(b *testing.B) {
func BenchmarkHashSetRemove100000(b *testing.B) {
b.StopTimer()
size := 100000
set := New()
set := New[int]()
for n := 0; n < size; n++ {
set.Add(n)
}

@ -6,21 +6,22 @@ package linkedhashset
import (
"encoding/json"
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/v2/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Set)(nil)
var _ containers.JSONDeserializer = (*Set)(nil)
var _ containers.JSONSerializer = (*Set[int])(nil)
var _ containers.JSONDeserializer = (*Set[int])(nil)
// ToJSON outputs the JSON representation of the set.
func (set *Set) ToJSON() ([]byte, error) {
func (set *Set[T]) ToJSON() ([]byte, error) {
return json.Marshal(set.Values())
}
// FromJSON populates the set from the input JSON representation.
func (set *Set) FromJSON(data []byte) error {
elements := []interface{}{}
func (set *Set[T]) FromJSON(data []byte) error {
var elements []T
err := json.Unmarshal(data, &elements)
if err == nil {
set.Clear()
@ -30,11 +31,11 @@ func (set *Set) FromJSON(data []byte) error {
}
// UnmarshalJSON @implements json.Unmarshaler
func (set *Set) UnmarshalJSON(bytes []byte) error {
func (set *Set[T]) UnmarshalJSON(bytes []byte) error {
return set.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (set *Set) MarshalJSON() ([]byte, error) {
func (set *Set[T]) MarshalJSON() ([]byte, error) {
return set.ToJSON()
}

@ -9,18 +9,17 @@
// Reference: https://en.wikipedia.org/wiki/Set_%28abstract_data_type%29
package sets
import "github.com/emirpasic/gods/containers"
import (
"github.com/emirpasic/gods/v2/containers"
)
// Set interface that all sets implement
type Set interface {
Add(elements ...interface{})
Remove(elements ...interface{})
Contains(elements ...interface{}) bool
// Intersection(another *Set) *Set
// Union(another *Set) *Set
// Difference(another *Set) *Set
type Set[T comparable] interface {
Add(elements ...T)
Remove(elements ...T)
Contains(elements ...T) bool
containers.Container
containers.Container[T]
// Empty() bool
// Size() int
// Clear()

@ -5,15 +5,15 @@
package treeset
import (
"github.com/emirpasic/gods/containers"
rbt "github.com/emirpasic/gods/trees/redblacktree"
"github.com/emirpasic/gods/v2/containers"
rbt "github.com/emirpasic/gods/v2/trees/redblacktree"
)
// Assert Enumerable implementation
var _ containers.EnumerableWithIndex = (*Set)(nil)
var _ containers.EnumerableWithIndex[int] = (*Set[int])(nil)
// Each calls the given function once for each element, passing that element's index and value.
func (set *Set) Each(f func(index int, value interface{})) {
func (set *Set[T]) Each(f func(index int, value T)) {
iterator := set.Iterator()
for iterator.Next() {
f(iterator.Index(), iterator.Value())
@ -22,8 +22,8 @@ func (set *Set) Each(f func(index int, value interface{})) {
// Map invokes the given function once for each element and returns a
// container containing the values returned by the given function.
func (set *Set) Map(f func(index int, value interface{}) interface{}) *Set {
newSet := &Set{tree: rbt.NewWith(set.tree.Comparator)}
func (set *Set[T]) Map(f func(index int, value T) T) *Set[T] {
newSet := &Set[T]{tree: rbt.NewWith[T, struct{}](set.tree.Comparator)}
iterator := set.Iterator()
for iterator.Next() {
newSet.Add(f(iterator.Index(), iterator.Value()))
@ -32,8 +32,8 @@ func (set *Set) Map(f func(index int, value interface{}) interface{}) *Set {
}
// Select returns a new container containing all elements for which the given function returns a true value.
func (set *Set) Select(f func(index int, value interface{}) bool) *Set {
newSet := &Set{tree: rbt.NewWith(set.tree.Comparator)}
func (set *Set[T]) Select(f func(index int, value T) bool) *Set[T] {
newSet := &Set[T]{tree: rbt.NewWith[T, struct{}](set.tree.Comparator)}
iterator := set.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
@ -45,7 +45,7 @@ func (set *Set) Select(f func(index int, value interface{}) bool) *Set {
// Any passes each element of the container to the given function and
// returns true if the function ever returns true for any element.
func (set *Set) Any(f func(index int, value interface{}) bool) bool {
func (set *Set[T]) Any(f func(index int, value T) bool) bool {
iterator := set.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
@ -57,7 +57,7 @@ func (set *Set) Any(f func(index int, value interface{}) bool) bool {
// All passes each element of the container to the given function and
// returns true if the function returns true for all elements.
func (set *Set) All(f func(index int, value interface{}) bool) bool {
func (set *Set[T]) All(f func(index int, value T) bool) bool {
iterator := set.Iterator()
for iterator.Next() {
if !f(iterator.Index(), iterator.Value()) {
@ -70,12 +70,13 @@ func (set *Set) All(f func(index int, value interface{}) bool) bool {
// Find passes each element of the container to the given function and returns
// the first (index,value) for which the function is true or -1,nil otherwise
// if no element matches the criteria.
func (set *Set) Find(f func(index int, value interface{}) bool) (int, interface{}) {
func (set *Set[T]) Find(f func(index int, value T) bool) (int, T) {
iterator := set.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
return iterator.Index(), iterator.Value()
}
}
return -1, nil
var t T
return -1, t
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save