mirror of https://github.com/emirpasic/gods
ArrayList addition (inc. test, example and documentation)
parent
a2f7d2482e
commit
3aa0eeddfb
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright (c) 2015, Emir Pasic
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package examples
|
||||
|
||||
import "github.com/emirpasic/gods/lists/arraylist"
|
||||
|
||||
func ArrayListExample() {
|
||||
list := arraylist.New()
|
||||
list.Add("a") // ["a"]
|
||||
list.Add("b", "c") // ["a","b","c"]
|
||||
_, _ = list.Get(0) // "a",true
|
||||
_, _ = list.Get(100) // nil,false
|
||||
_ = list.Contains("a", "b", "c") // true
|
||||
_ = list.Contains("a", "b", "c", "d") // false
|
||||
list.Remove(2) // ["a","b"]
|
||||
list.Remove(1) // ["a"]
|
||||
list.Remove(0) // []
|
||||
list.Remove(0) // [] (ignored)
|
||||
_ = list.Empty() // true
|
||||
_ = list.Size() // 0
|
||||
list.Add("a") // ["a"]
|
||||
list.Clear() // []
|
||||
}
|
@ -0,0 +1,182 @@
|
||||
/*
|
||||
Copyright (c) 2015, Emir Pasic
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Implementation of list using a slice.
|
||||
// Structure is not thread safe.
|
||||
// References: http://en.wikipedia.org/wiki/List_%28abstract_data_type%29
|
||||
|
||||
package arraylist
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/emirpasic/gods/lists"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func assertInterfaceImplementation() {
|
||||
var _ lists.Interface = (*List)(nil)
|
||||
}
|
||||
|
||||
type List struct {
|
||||
elements []interface{}
|
||||
size int
|
||||
}
|
||||
|
||||
const (
|
||||
GROWTH_FACTOR = float32(1.5) // growth by 50%
|
||||
SHRINK_FACTOR = float32(0.5) // shrink when size is 50% of capacity (0 means never shrink)
|
||||
)
|
||||
|
||||
// Instantiates a new empty list
|
||||
func New() *List {
|
||||
return &List{}
|
||||
}
|
||||
|
||||
// Appends a value at the end of the list
|
||||
func (list *List) Add(elements ...interface{}) {
|
||||
list.growBy(len(elements))
|
||||
for _, element := range elements {
|
||||
list.elements[list.size] = element
|
||||
list.size += 1
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
||||
if !list.withinRange(index) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return list.elements[index], true
|
||||
}
|
||||
|
||||
// Removes one or more elements from the list with the supplied indices.
|
||||
func (list *List) Remove(index int) {
|
||||
|
||||
if !list.withinRange(index) {
|
||||
return
|
||||
}
|
||||
|
||||
list.elements[index] = nil // cleanup reference
|
||||
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 -= 1
|
||||
|
||||
list.shrink()
|
||||
}
|
||||
|
||||
// Check if elements (one or more) are present in the set.
|
||||
// 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(elements ...interface{}) bool {
|
||||
|
||||
for _, searchElement := range elements {
|
||||
found := false
|
||||
for _, element := range list.elements {
|
||||
if element == searchElement {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Returns all elements in the list.
|
||||
func (list *List) Values() []interface{} {
|
||||
newElements := make([]interface{}, list.size, list.size)
|
||||
copy(newElements, list.elements[:list.size])
|
||||
return newElements
|
||||
}
|
||||
|
||||
// Returns true if list does not contain any elements.
|
||||
func (list *List) Empty() bool {
|
||||
return list.size == 0
|
||||
}
|
||||
|
||||
// Returns number of elements within the list.
|
||||
func (list *List) Size() int {
|
||||
return list.size
|
||||
}
|
||||
|
||||
// Removes all elements from the list.
|
||||
func (list *List) Clear() {
|
||||
list.size = 0
|
||||
list.elements = []interface{}{}
|
||||
}
|
||||
|
||||
func (list *List) String() string {
|
||||
str := "ArrayList\n"
|
||||
values := []string{}
|
||||
for _, value := range list.elements {
|
||||
values = append(values, fmt.Sprintf("%v", value))
|
||||
}
|
||||
str += strings.Join(values, ", ")
|
||||
return str
|
||||
}
|
||||
|
||||
/*************
|
||||
* Internals *
|
||||
*************/
|
||||
|
||||
// Check that the index is withing bounds of the list
|
||||
func (list *List) withinRange(index int) bool {
|
||||
return index >= 0 && index < list.size && list.size != 0
|
||||
}
|
||||
|
||||
func (list *List) resize(cap int) {
|
||||
newElements := make([]interface{}, 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) {
|
||||
// Grow when capacity is reached by a factor of 1.5 and add number of elements
|
||||
currentCapacity := cap(list.elements)
|
||||
if list.size+n >= currentCapacity {
|
||||
newCapacity := int(GROWTH_FACTOR * float32(currentCapacity+n))
|
||||
list.resize(newCapacity)
|
||||
}
|
||||
}
|
||||
|
||||
// Shrink the array if necessary, i.e. when size is SHRINK_FACTOR percent of current capacity
|
||||
func (list *List) shrink() {
|
||||
if SHRINK_FACTOR == 0.0 {
|
||||
return
|
||||
}
|
||||
// Shrink when size is at SHRINK_FACTOR * capacity
|
||||
currentCapacity := cap(list.elements)
|
||||
if list.size <= int(float32(currentCapacity)*SHRINK_FACTOR) {
|
||||
list.resize(list.size)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright (c) 2015, Emir Pasic
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package arraylist
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestArrayList(t *testing.T) {
|
||||
|
||||
list := New()
|
||||
|
||||
list.Add("a", "b", "c", "d", "e", "f", "g")
|
||||
list.Clear()
|
||||
|
||||
if actualValue := list.Empty(); actualValue != true {
|
||||
t.Errorf("Got %v expected %v", actualValue, true)
|
||||
}
|
||||
|
||||
if actualValue := list.Size(); actualValue != 0 {
|
||||
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||
}
|
||||
|
||||
list.Add("a")
|
||||
list.Add("b", "c")
|
||||
|
||||
if actualValue := list.Empty(); actualValue != false {
|
||||
t.Errorf("Got %v expected %v", actualValue, false)
|
||||
}
|
||||
|
||||
if actualValue := list.Size(); actualValue != 3 {
|
||||
t.Errorf("Got %v expected %v", actualValue, 3)
|
||||
}
|
||||
|
||||
if actualValue, ok := list.Get(2); actualValue != "c" || !ok {
|
||||
t.Errorf("Got %v expected %v", actualValue, "c")
|
||||
}
|
||||
|
||||
list.Remove(2)
|
||||
|
||||
if actualValue, ok := list.Get(2); actualValue != nil || ok {
|
||||
t.Errorf("Got %v expected %v", actualValue, nil)
|
||||
}
|
||||
|
||||
list.Remove(1)
|
||||
list.Remove(0)
|
||||
|
||||
if actualValue := list.Empty(); actualValue != true {
|
||||
t.Errorf("Got %v expected %v", actualValue, true)
|
||||
}
|
||||
|
||||
if actualValue := list.Size(); actualValue != 0 {
|
||||
t.Errorf("Got %v expected %v", actualValue, 0)
|
||||
}
|
||||
|
||||
list.Add("a", "b", "c")
|
||||
|
||||
if actualValue := list.Contains("a", "b", "c"); actualValue != true {
|
||||
t.Errorf("Got %v expected %v", actualValue, true)
|
||||
}
|
||||
|
||||
if actualValue := list.Contains("a", "b", "c", "d"); actualValue != false {
|
||||
t.Errorf("Got %v expected %v", actualValue, false)
|
||||
}
|
||||
|
||||
list.Clear()
|
||||
|
||||
if actualValue := list.Contains("a"); actualValue != false {
|
||||
t.Errorf("Got %v expected %v", actualValue, false)
|
||||
}
|
||||
|
||||
if actualValue, ok := list.Get(0); actualValue != nil || ok {
|
||||
t.Errorf("Got %v expected %v", actualValue, false)
|
||||
}
|
||||
|
||||
if actualValue := list.Empty(); actualValue != true {
|
||||
t.Errorf("Got %v expected %v", actualValue, true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func BenchmarkArrayList(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
list := New()
|
||||
for n := 0; n < 1000; n++ {
|
||||
list.Add(i)
|
||||
}
|
||||
for !list.Empty() {
|
||||
list.Remove(0)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright (c) Emir Pasic, All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3.0 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. See the file LICENSE included
|
||||
with this distribution for more information.
|
||||
*/
|
||||
|
||||
package lists
|
||||
|
||||
type Interface interface {
|
||||
Get(index int) (interface{}, bool)
|
||||
Remove(index int)
|
||||
Add(elements ...interface{})
|
||||
Contains(elements ...interface{}) bool
|
||||
Empty() bool
|
||||
Size() int
|
||||
Clear()
|
||||
Values() []interface{}
|
||||
}
|
Loading…
Reference in New Issue