github.com/djordje200179/extendedlibrary/datastructures@v1.7.1-0.20240227175559-d09520a92dd4/maps/linkmap/wrapper.go (about)

     1  package linkmap
     2  
     3  import (
     4  	"github.com/djordje200179/extendedlibrary/datastructures/iter"
     5  	"github.com/djordje200179/extendedlibrary/datastructures/maps"
     6  	"github.com/djordje200179/extendedlibrary/datastructures/maps/hashmap"
     7  	"github.com/djordje200179/extendedlibrary/misc"
     8  )
     9  
    10  // Order represents the order of the nodes in the map.
    11  type Order bool
    12  
    13  const (
    14  	FIFO Order = false // FIFO represents the first-in-first-out order.
    15  	LRU        = true  // LRU represents the least-recently-used order.
    16  )
    17  
    18  // Wrapper is a map that keeps track of the order of the nodes.
    19  type Wrapper[K, V any] struct {
    20  	m maps.Map[K, *Node[K, V]]
    21  
    22  	head, tail *Node[K, V]
    23  	order      Order
    24  
    25  	capacity int
    26  }
    27  
    28  // From returns a new Wrapper that wraps the given map.
    29  func From[K, V any](m maps.Map[K, *Node[K, V]], capacity int, order Order) *Wrapper[K, V] {
    30  	wrapper := &Wrapper[K, V]{
    31  		m: m,
    32  
    33  		order:    order,
    34  		capacity: capacity,
    35  	}
    36  
    37  	for it := m.Iterator(); it.Valid(); it.Move() {
    38  		node := it.Get().Second
    39  		if wrapper.head == nil {
    40  			wrapper.head = node
    41  		} else {
    42  			wrapper.tail = node
    43  		}
    44  	}
    45  
    46  	return wrapper
    47  }
    48  
    49  // NewHashmap returns a new Wrapper around a empty hashmap.
    50  func NewHashmap[K comparable, V any](capacity int, order Order) *Wrapper[K, V] {
    51  	m := hashmap.NewWithCapacity[K, *Node[K, V]](capacity)
    52  	wrapper := &Wrapper[K, V]{
    53  		m: m,
    54  
    55  		order:    order,
    56  		capacity: capacity,
    57  	}
    58  
    59  	return wrapper
    60  }
    61  
    62  func (w *Wrapper[K, V]) moveToFront(node *Node[K, V]) {
    63  	if node.prev != nil {
    64  		node.prev.next = node.next
    65  	} else {
    66  		w.head = node.next
    67  	}
    68  
    69  	if node.next != nil {
    70  		node.next.prev = node.prev
    71  	} else {
    72  		w.tail = node.prev
    73  	}
    74  
    75  	if w.head == nil {
    76  		w.head = node
    77  	} else {
    78  		w.tail.next = node
    79  		node.prev = w.tail
    80  	}
    81  	w.tail = node
    82  }
    83  
    84  // Size returns the number of entries in the map.
    85  func (w *Wrapper[K, V]) Size() int {
    86  	return w.m.Size()
    87  }
    88  
    89  // Contains returns true if the map contains the given key.
    90  func (w *Wrapper[K, V]) Contains(key K) bool {
    91  	return w.m.Contains(key)
    92  }
    93  
    94  // TryGet returns the value associated with the given key.
    95  // If the key is not in the map, the zero value and false is returned.
    96  // If the order is LRU, the entry is moved to the front.
    97  func (w *Wrapper[K, V]) TryGet(key K) (V, bool) {
    98  	node, ok := w.m.TryGet(key)
    99  	if !ok {
   100  		var zero V
   101  		return zero, false
   102  	}
   103  
   104  	if w.order == LRU {
   105  		w.moveToFront(node)
   106  	}
   107  
   108  	return node.Value, true
   109  }
   110  
   111  // Get returns the value associated with the given key.
   112  // Panics if the key is not in the map.
   113  // If the order is LRU, the entry is moved to the front.
   114  func (w *Wrapper[K, V]) Get(key K) V {
   115  	node := w.m.Get(key)
   116  
   117  	if w.order == LRU {
   118  		w.moveToFront(node)
   119  	}
   120  
   121  	return node.Value
   122  }
   123  
   124  // GetRef returns a reference to the value associated with the given key.
   125  // Panics if the key is not in the map.
   126  // If the order is LRU, the entry is moved to the front.
   127  func (w *Wrapper[K, V]) GetRef(key K) *V {
   128  	node := w.m.Get(key)
   129  
   130  	if w.order == LRU {
   131  		w.moveToFront(node)
   132  	}
   133  
   134  	return &node.Value
   135  }
   136  
   137  // Set sets the value associated with the given key.
   138  // Entry is moved to the front of the map.
   139  // If the map is full, the last entry is removed.
   140  func (w *Wrapper[K, V]) Set(key K, value V) {
   141  	node, ok := w.m.TryGet(key)
   142  	if ok {
   143  		node.Value = value
   144  
   145  		if w.order == LRU {
   146  			w.moveToFront(node)
   147  		}
   148  
   149  		return
   150  	}
   151  
   152  	if w.capacity > 0 && w.m.Size() == w.capacity {
   153  		firstNode := w.head
   154  
   155  		w.head = firstNode.next
   156  		if w.head != nil {
   157  			w.head.prev = nil
   158  		} else {
   159  			w.tail = nil
   160  		}
   161  
   162  		w.m.Remove(firstNode.key)
   163  	}
   164  
   165  	node = &Node[K, V]{key: key, Value: value}
   166  
   167  	if w.head == nil {
   168  		w.head = node
   169  	} else {
   170  		w.tail.next = node
   171  		node.prev = w.tail
   172  	}
   173  	w.tail = node
   174  
   175  	w.m.Set(key, node)
   176  }
   177  
   178  // Remove removes the entry with the given key.
   179  // If the key is not in the map, nothing happens.
   180  func (w *Wrapper[K, V]) Remove(key K) {
   181  	node, ok := w.m.TryGet(key)
   182  	if !ok {
   183  		return
   184  	}
   185  
   186  	if node.prev != nil {
   187  		node.prev.next = node.next
   188  	} else {
   189  		w.head = node.next
   190  	}
   191  
   192  	if node.next != nil {
   193  		node.next.prev = node.prev
   194  	} else {
   195  		w.tail = node.prev
   196  	}
   197  
   198  	w.m.Remove(key)
   199  }
   200  
   201  // Clear removes all entries from the map.
   202  func (w *Wrapper[K, V]) Clear() {
   203  	w.m.Clear()
   204  
   205  	w.head = nil
   206  	w.tail = nil
   207  }
   208  
   209  // Clone returns a copy of the wrapper and
   210  // of the underlying map.
   211  func (w *Wrapper[K, V]) Clone() maps.Map[K, V] {
   212  	clonedMap := w.m.Clone()
   213  
   214  	var clonedHead, clonedTail *Node[K, V]
   215  	for oldIt, newIt := w.m.Iterator(), clonedMap.MapIterator(); oldIt.Valid(); oldIt.Move() {
   216  		oldNode := oldIt.Get().Second
   217  
   218  		newNode := oldNode.Clone()
   219  		if clonedHead == nil {
   220  			clonedHead = newNode
   221  		} else {
   222  			clonedTail.next = newNode
   223  			newNode.prev = clonedTail
   224  		}
   225  		clonedTail = newNode
   226  
   227  		newIt.SetValue(newNode)
   228  
   229  		newIt.Move()
   230  	}
   231  
   232  	return &Wrapper[K, V]{
   233  		m: clonedMap,
   234  
   235  		head:     clonedHead,
   236  		tail:     clonedTail,
   237  		capacity: w.capacity,
   238  		order:    w.order,
   239  	}
   240  }
   241  
   242  // Iterator returns an iter.Iterator over the entries in the map.
   243  func (w *Wrapper[K, V]) Iterator() iter.Iterator[misc.Pair[K, V]] {
   244  	return w.MapIterator()
   245  }
   246  
   247  // MapIterator returns a iterator over the entries in the map.
   248  func (w *Wrapper[K, V]) MapIterator() maps.Iterator[K, V] {
   249  	return &Iterator[K, V]{wrapper: w, curr: w.head}
   250  }
   251  
   252  // Stream2 streams over the entries in the Map.
   253  func (w *Wrapper[K, V]) Stream2(yield func(K, V) bool) {
   254  	for it := w.MapIterator(); it.Valid(); it.Move() {
   255  		if !yield(it.Key(), it.Value()) {
   256  			break
   257  		}
   258  	}
   259  }
   260  
   261  // RefsStream2 streams keys and references to values of the Map
   262  func (w *Wrapper[K, V]) RefsStream2(yield func(K, *V) bool) {
   263  	for it := w.MapIterator(); it.Valid(); it.Move() {
   264  		if !yield(it.Key(), it.ValueRef()) {
   265  			break
   266  		}
   267  	}
   268  }