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