github.com/mymmsc/gox@v1.3.33/util/arraylist/arraylist.go (about) 1 // Copyright (c) 2015, Emir Pasic. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package arraylist implements the array list. 6 // 7 // Structure is not thread safe. 8 // 9 // Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29 10 package arraylist 11 12 import ( 13 "fmt" 14 "github.com/mymmsc/gox/util" 15 "strings" 16 ) 17 18 func assertListImplementation() { 19 var _ util.List = (*List)(nil) 20 } 21 22 // List holds the elements in a slice 23 type List struct { 24 elements []interface{} 25 size int 26 } 27 28 const ( 29 growthFactor = float32(2.0) // growth by 100% 30 shrinkFactor = float32(0.25) // shrink when size is 25% of capacity (0 means never shrink) 31 ) 32 33 // New instantiates a new list and adds the passed values, if any, to the list 34 func New(values ...interface{}) *List { 35 list := &List{} 36 if len(values) > 0 { 37 list.Add(values...) 38 } 39 return list 40 } 41 42 // Add appends a value at the end of the list 43 func (list *List) Add(values ...interface{}) { 44 list.growBy(len(values)) 45 for _, value := range values { 46 list.elements[list.size] = value 47 list.size++ 48 } 49 } 50 51 // Get returns the element at index. 52 // Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false. 53 func (list *List) Get(index int) (interface{}, bool) { 54 55 if !list.withinRange(index) { 56 return nil, false 57 } 58 59 return list.elements[index], true 60 } 61 62 // Remove removes the element at the given index from the list. 63 func (list *List) Remove(index int) { 64 65 if !list.withinRange(index) { 66 return 67 } 68 69 list.elements[index] = nil // cleanup reference 70 copy(list.elements[index:], list.elements[index+1:list.size]) // shift to the left by one (slow operation, need ways to optimize this) 71 list.size-- 72 73 list.shrink() 74 } 75 76 // Contains checks if elements (one or more) are present in the set. 77 // All elements have to be present in the set for the method to return true. 78 // Performance time complexity of n^2. 79 // Returns true if no arguments are passed at all, i.e. set is always super-set of empty set. 80 func (list *List) Contains(values ...interface{}) bool { 81 82 for _, searchValue := range values { 83 found := false 84 for _, element := range list.elements { 85 if element == searchValue { 86 found = true 87 break 88 } 89 } 90 if !found { 91 return false 92 } 93 } 94 return true 95 } 96 97 // Values returns all elements in the list. 98 func (list *List) Values() []interface{} { 99 newElements := make([]interface{}, list.size, list.size) 100 copy(newElements, list.elements[:list.size]) 101 return newElements 102 } 103 104 //IndexOf returns index of provided element 105 func (list *List) IndexOf(value interface{}) int { 106 if list.size == 0 { 107 return -1 108 } 109 for index, element := range list.elements { 110 if element == value { 111 return index 112 } 113 } 114 return -1 115 } 116 117 // Empty returns true if list does not contain any elements. 118 func (list *List) Empty() bool { 119 return list.size == 0 120 } 121 122 // Size returns number of elements within the list. 123 func (list *List) Size() int { 124 return list.size 125 } 126 127 // Clear removes all elements from the list. 128 func (list *List) Clear() { 129 list.size = 0 130 list.elements = []interface{}{} 131 } 132 133 // Sort sorts values (in-place) using. 134 func (list *List) Sort(comparator util.Comparator) { 135 if len(list.elements) < 2 { 136 return 137 } 138 util.Sort(list.elements[:list.size], comparator) 139 } 140 141 // Swap swaps the two values at the specified positions. 142 func (list *List) Swap(i, j int) { 143 if list.withinRange(i) && list.withinRange(j) { 144 list.elements[i], list.elements[j] = list.elements[j], list.elements[i] 145 } 146 } 147 148 // Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right. 149 // Does not do anything if position is negative or bigger than list's size 150 // Note: position equal to list's size is valid, i.e. append. 151 func (list *List) Insert(index int, values ...interface{}) { 152 153 if !list.withinRange(index) { 154 // Append 155 if index == list.size { 156 list.Add(values...) 157 } 158 return 159 } 160 161 l := len(values) 162 list.growBy(l) 163 list.size += l 164 copy(list.elements[index+l:], list.elements[index:list.size-l]) 165 copy(list.elements[index:], values) 166 } 167 168 // Set the value at specified index 169 // Does not do anything if position is negative or bigger than list's size 170 // Note: position equal to list's size is valid, i.e. append. 171 func (list *List) Set(index int, value interface{}) { 172 173 if !list.withinRange(index) { 174 // Append 175 if index == list.size { 176 list.Add(value) 177 } 178 return 179 } 180 181 list.elements[index] = value 182 } 183 184 // String returns a string representation of container 185 func (list *List) String() string { 186 str := "ArrayList\n" 187 values := []string{} 188 for _, value := range list.elements[:list.size] { 189 values = append(values, fmt.Sprintf("%v", value)) 190 } 191 str += strings.Join(values, ", ") 192 return str 193 } 194 195 // Check that the index is within bounds of the list 196 func (list *List) withinRange(index int) bool { 197 return index >= 0 && index < list.size 198 } 199 200 func (list *List) resize(cap int) { 201 newElements := make([]interface{}, cap, cap) 202 copy(newElements, list.elements) 203 list.elements = newElements 204 } 205 206 // Expand the array if necessary, i.e. capacity will be reached if we add n elements 207 func (list *List) growBy(n int) { 208 // When capacity is reached, grow by a factor of growthFactor and add number of elements 209 currentCapacity := cap(list.elements) 210 if list.size+n >= currentCapacity { 211 newCapacity := int(growthFactor * float32(currentCapacity+n)) 212 list.resize(newCapacity) 213 } 214 } 215 216 // Shrink the array if necessary, i.e. when size is shrinkFactor percent of current capacity 217 func (list *List) shrink() { 218 if shrinkFactor == 0.0 { 219 return 220 } 221 // Shrink when size is at shrinkFactor * capacity 222 currentCapacity := cap(list.elements) 223 if list.size <= int(float32(currentCapacity)*shrinkFactor) { 224 list.resize(list.size) 225 } 226 }