|
1 | 1 | package cacheset |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "github.com/emirpasic/gods/lists/singlylinkedlist" |
| 4 | + "github.com/emirpasic/gods/sets/linkedhashset" |
5 | 5 | "strconv" |
6 | 6 | "sync" |
7 | 7 | ) |
8 | 8 |
|
9 | 9 | var lock sync.RWMutex |
10 | 10 |
|
11 | 11 | type CacheSet struct { |
12 | | - table map[interface{}]struct{} |
13 | | - ordering *singlylinkedlist.List |
| 12 | + table *linkedhashset.Set |
14 | 13 | maxSize int |
15 | 14 | } |
16 | 15 |
|
17 | 16 | var itemExists = struct{}{} |
18 | 17 |
|
19 | 18 | func New(maxSize int) *CacheSet { |
20 | | - set := &CacheSet{ |
21 | | - table: make(map[interface{}]struct{}), |
22 | | - ordering: singlylinkedlist.New(), |
23 | | - maxSize: maxSize, |
| 19 | + s := &CacheSet{ |
| 20 | + table: linkedhashset.New(), |
| 21 | + maxSize: maxSize, |
24 | 22 | } |
25 | | - return set |
| 23 | + return s |
26 | 24 | } |
27 | 25 |
|
28 | 26 | func (set *CacheSet) Add(item interface{}) { |
29 | 27 | lock.Lock() |
30 | 28 | defer lock.Unlock() |
31 | | - var contains bool |
32 | | - if _, contains = set.table[item]; !contains { |
| 29 | + if !set.table.Contains(item) { |
33 | 30 | set.removeExceeded() |
34 | | - set.table[item] = itemExists |
35 | | - set.ordering.Append(item) |
| 31 | + set.table.Add(item) |
36 | 32 | } |
37 | 33 | } |
38 | 34 |
|
39 | 35 | func (set *CacheSet) removeExceeded() { |
40 | | - for set.ordering.Size() >= set.maxSize { |
41 | | - item, exist := set.ordering.Get(0) |
42 | | - if exist { |
43 | | - set.ordering.Remove(0) |
44 | | - delete(set.table, item) |
45 | | - } |
| 36 | + removalCount := set.table.Size() - set.maxSize |
| 37 | + if removalCount < 0 { |
| 38 | + return |
| 39 | + } |
| 40 | + var removals []interface{} |
| 41 | + iterator := set.table.Iterator() |
| 42 | + |
| 43 | + for i := removalCount; i >= 0; i-- { |
| 44 | + iterator.Next() |
| 45 | + removals = append(removals, iterator.Value()) |
| 46 | + } |
| 47 | + for _, removal := range removals { |
| 48 | + set.table.Remove(removal) |
46 | 49 | } |
47 | 50 | } |
48 | 51 |
|
49 | 52 | func (set *CacheSet) Contains(item interface{}) bool { |
50 | 53 | lock.RLock() |
51 | 54 | defer lock.RUnlock() |
52 | | - if _, contains := set.table[item]; !contains { |
53 | | - return false |
54 | | - } |
55 | | - return true |
| 55 | + return set.table.Contains(item) |
56 | 56 | } |
57 | 57 |
|
58 | 58 | func (set *CacheSet) Empty() bool { |
59 | 59 | lock.Lock() |
60 | 60 | defer lock.Unlock() |
61 | | - return set.Size() == 0 |
| 61 | + return set.table. Size() == 0 |
62 | 62 | } |
63 | 63 |
|
64 | 64 | func (set *CacheSet) Size() int { |
65 | | - return set.ordering.Size() |
| 65 | + return set.table.Size() |
66 | 66 | } |
67 | 67 |
|
68 | 68 | func (set *CacheSet) Clear() { |
69 | 69 | lock.Lock() |
70 | 70 | defer lock.Unlock() |
71 | | - set.table = make(map[interface{}]struct{}) |
72 | | - set.ordering.Clear() |
| 71 | + set.table = linkedhashset.New() |
73 | 72 | } |
74 | 73 |
|
75 | 74 | func (set *CacheSet) String() string { |
76 | | - return "CacheSet[" + strconv.Itoa(set.ordering.Size()) + "]" |
| 75 | + return "CacheSet[" + strconv.Itoa(set.Size()) + "]" |
77 | 76 | } |
78 | 77 |
|
0 commit comments