mirror of
https://gitee.com/johng/gf.git
synced 2024-12-01 03:38:35 +08:00
add gtree.RedBlackTree container
This commit is contained in:
parent
b15d8bdd2e
commit
abaef9ba87
@ -103,6 +103,15 @@ func (m *Map) Sets(data map[interface{}]interface{}) {
|
|||||||
m.mu.Unlock()
|
m.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search searches the map with given <key>.
|
||||||
|
// Second return parameter <found> is true if key was found, otherwise false.
|
||||||
|
func (m *Map) Search(key interface{}) (value interface{}, found bool) {
|
||||||
|
m.mu.RLock()
|
||||||
|
value, found = m.data[key]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns the value by given <key>.
|
// Get returns the value by given <key>.
|
||||||
func (m *Map) Get(key interface{}) interface{} {
|
func (m *Map) Get(key interface{}) interface{} {
|
||||||
m.mu.RLock()
|
m.mu.RLock()
|
||||||
@ -136,7 +145,7 @@ func (m *Map) doSetWithLockCheck(key interface{}, value interface{}) interface{}
|
|||||||
// GetOrSet returns the value by key,
|
// GetOrSet returns the value by key,
|
||||||
// or set value with given <value> if not exist and returns this value.
|
// or set value with given <value> if not exist and returns this value.
|
||||||
func (m *Map) GetOrSet(key interface{}, value interface{}) interface{} {
|
func (m *Map) GetOrSet(key interface{}, value interface{}) interface{} {
|
||||||
if v := m.Get(key); v == nil {
|
if v, ok := m.Search(key); !ok {
|
||||||
return m.doSetWithLockCheck(key, value)
|
return m.doSetWithLockCheck(key, value)
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -147,7 +156,7 @@ func (m *Map) GetOrSet(key interface{}, value interface{}) interface{} {
|
|||||||
// or sets value with return value of callback function <f> if not exist
|
// or sets value with return value of callback function <f> if not exist
|
||||||
// and returns this value.
|
// and returns this value.
|
||||||
func (m *Map) GetOrSetFunc(key interface{}, f func() interface{}) interface{} {
|
func (m *Map) GetOrSetFunc(key interface{}, f func() interface{}) interface{} {
|
||||||
if v := m.Get(key); v == nil {
|
if v, ok := m.Search(key); !ok {
|
||||||
return m.doSetWithLockCheck(key, f())
|
return m.doSetWithLockCheck(key, f())
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -161,7 +170,7 @@ func (m *Map) GetOrSetFunc(key interface{}, f func() interface{}) interface{} {
|
|||||||
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
||||||
// with mutex.Lock of the hash map.
|
// with mutex.Lock of the hash map.
|
||||||
func (m *Map) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} {
|
func (m *Map) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} {
|
||||||
if v := m.Get(key); v == nil {
|
if v, ok := m.Search(key); !ok {
|
||||||
return m.doSetWithLockCheck(key, f)
|
return m.doSetWithLockCheck(key, f)
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -314,13 +323,13 @@ func (m *Map) RLockFunc(f func(m map[interface{}]interface{})) {
|
|||||||
f(m.data)
|
f(m.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flip exchanges key-value of the map, it will change key-value to value-key.
|
// Flip exchanges key-value of the map to value-key.
|
||||||
func (m *Map) Flip() {
|
func (m *Map) Flip() {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
n := make(map[interface{}]interface{}, len(m.data))
|
n := make(map[interface{}]interface{}, len(m.data))
|
||||||
for i, v := range m.data {
|
for k, v := range m.data {
|
||||||
n[v] = i
|
n[v] = k
|
||||||
}
|
}
|
||||||
m.data = n
|
m.data = n
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,15 @@ func (m *IntAnyMap) Sets(data map[int]interface{}) {
|
|||||||
m.mu.Unlock()
|
m.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search searches the map with given <key>.
|
||||||
|
// Second return parameter <found> is true if key was found, otherwise false.
|
||||||
|
func (m *IntAnyMap) Search(key int) (value interface{}, found bool) {
|
||||||
|
m.mu.RLock()
|
||||||
|
value, found = m.data[key]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns the value by given <key>.
|
// Get returns the value by given <key>.
|
||||||
func (m *IntAnyMap) Get(key int) (interface{}) {
|
func (m *IntAnyMap) Get(key int) (interface{}) {
|
||||||
m.mu.RLock()
|
m.mu.RLock()
|
||||||
@ -140,7 +149,7 @@ func (m *IntAnyMap) doSetWithLockCheck(key int, value interface{}) interface{} {
|
|||||||
// GetOrSet returns the value by key,
|
// GetOrSet returns the value by key,
|
||||||
// or set value with given <value> if not exist and returns this value.
|
// or set value with given <value> if not exist and returns this value.
|
||||||
func (m *IntAnyMap) GetOrSet(key int, value interface{}) interface{} {
|
func (m *IntAnyMap) GetOrSet(key int, value interface{}) interface{} {
|
||||||
if v := m.Get(key); v == nil {
|
if v, ok := m.Search(key); !ok {
|
||||||
return m.doSetWithLockCheck(key, value)
|
return m.doSetWithLockCheck(key, value)
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -150,7 +159,7 @@ func (m *IntAnyMap) GetOrSet(key int, value interface{}) interface{} {
|
|||||||
// GetOrSetFunc returns the value by key,
|
// GetOrSetFunc returns the value by key,
|
||||||
// or sets value with return value of callback function <f> if not exist and returns this value.
|
// or sets value with return value of callback function <f> if not exist and returns this value.
|
||||||
func (m *IntAnyMap) GetOrSetFunc(key int, f func() interface{}) interface{} {
|
func (m *IntAnyMap) GetOrSetFunc(key int, f func() interface{}) interface{} {
|
||||||
if v := m.Get(key); v == nil {
|
if v, ok := m.Search(key); !ok {
|
||||||
return m.doSetWithLockCheck(key, f())
|
return m.doSetWithLockCheck(key, f())
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -163,7 +172,7 @@ func (m *IntAnyMap) GetOrSetFunc(key int, f func() interface{}) interface{} {
|
|||||||
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
||||||
// with mutex.Lock of the hash map.
|
// with mutex.Lock of the hash map.
|
||||||
func (m *IntAnyMap) GetOrSetFuncLock(key int, f func() interface{}) interface{} {
|
func (m *IntAnyMap) GetOrSetFuncLock(key int, f func() interface{}) interface{} {
|
||||||
if v := m.Get(key); v == nil {
|
if v, ok := m.Search(key); !ok {
|
||||||
return m.doSetWithLockCheck(key, f)
|
return m.doSetWithLockCheck(key, f)
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -317,7 +326,7 @@ func (m *IntAnyMap) RLockFunc(f func(m map[int]interface{})) {
|
|||||||
f(m.data)
|
f(m.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flip exchanges key-value of the map, it will change key-value to value-key.
|
// Flip exchanges key-value of the map to value-key.
|
||||||
func (m *IntAnyMap) Flip() {
|
func (m *IntAnyMap) Flip() {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
@ -101,6 +101,15 @@ func (m *IntIntMap) Sets(data map[int]int) {
|
|||||||
m.mu.Unlock()
|
m.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search searches the map with given <key>.
|
||||||
|
// Second return parameter <found> is true if key was found, otherwise false.
|
||||||
|
func (m *IntIntMap) Search(key int) (value int, found bool) {
|
||||||
|
m.mu.RLock()
|
||||||
|
value, found = m.data[key]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns the value by given <key>.
|
// Get returns the value by given <key>.
|
||||||
func (m *IntIntMap) Get(key int) (int) {
|
func (m *IntIntMap) Get(key int) (int) {
|
||||||
m.mu.RLock()
|
m.mu.RLock()
|
||||||
@ -128,10 +137,7 @@ func (m *IntIntMap) doSetWithLockCheck(key int, value int) int {
|
|||||||
// GetOrSet returns the value by key,
|
// GetOrSet returns the value by key,
|
||||||
// or set value with given <value> if not exist and returns this value.
|
// or set value with given <value> if not exist and returns this value.
|
||||||
func (m *IntIntMap) GetOrSet(key int, value int) int {
|
func (m *IntIntMap) GetOrSet(key int, value int) int {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
v, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
return m.doSetWithLockCheck(key, value)
|
return m.doSetWithLockCheck(key, value)
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -141,10 +147,7 @@ func (m *IntIntMap) GetOrSet(key int, value int) int {
|
|||||||
// GetOrSetFunc returns the value by key,
|
// GetOrSetFunc returns the value by key,
|
||||||
// or sets value with return value of callback function <f> if not exist and returns this value.
|
// or sets value with return value of callback function <f> if not exist and returns this value.
|
||||||
func (m *IntIntMap) GetOrSetFunc(key int, f func() int) int {
|
func (m *IntIntMap) GetOrSetFunc(key int, f func() int) int {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
v, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
return m.doSetWithLockCheck(key, f())
|
return m.doSetWithLockCheck(key, f())
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -157,20 +160,17 @@ func (m *IntIntMap) GetOrSetFunc(key int, f func() int) int {
|
|||||||
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
||||||
// with mutex.Lock of the hash map.
|
// with mutex.Lock of the hash map.
|
||||||
func (m *IntIntMap) GetOrSetFuncLock(key int, f func() int) int {
|
func (m *IntIntMap) GetOrSetFuncLock(key int, f func() int) int {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
val, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
if v, ok := m.data[key]; ok {
|
if v, ok = m.data[key]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
val = f()
|
v = f()
|
||||||
m.data[key] = val
|
m.data[key] = v
|
||||||
return val
|
return v
|
||||||
} else {
|
} else {
|
||||||
return val
|
return v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,7 +300,7 @@ func (m *IntIntMap) RLockFunc(f func(m map[int]int)) {
|
|||||||
f(m.data)
|
f(m.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flip exchanges key-value of the map, it will change key-value to value-key.
|
// Flip exchanges key-value of the map to value-key.
|
||||||
func (m *IntIntMap) Flip() {
|
func (m *IntIntMap) Flip() {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
@ -102,6 +102,15 @@ func (m *IntStrMap) Sets(data map[int]string) {
|
|||||||
m.mu.Unlock()
|
m.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search searches the map with given <key>.
|
||||||
|
// Second return parameter <found> is true if key was found, otherwise false.
|
||||||
|
func (m *IntStrMap) Search(key int) (value string, found bool) {
|
||||||
|
m.mu.RLock()
|
||||||
|
value, found = m.data[key]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns the value by given <key>.
|
// Get returns the value by given <key>.
|
||||||
func (m *IntStrMap) Get(key int) string {
|
func (m *IntStrMap) Get(key int) string {
|
||||||
m.mu.RLock()
|
m.mu.RLock()
|
||||||
@ -129,10 +138,7 @@ func (m *IntStrMap) doSetWithLockCheck(key int, value string) string {
|
|||||||
// GetOrSet returns the value by key,
|
// GetOrSet returns the value by key,
|
||||||
// or set value with given <value> if not exist and returns this value.
|
// or set value with given <value> if not exist and returns this value.
|
||||||
func (m *IntStrMap) GetOrSet(key int, value string) string {
|
func (m *IntStrMap) GetOrSet(key int, value string) string {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
v, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
return m.doSetWithLockCheck(key, value)
|
return m.doSetWithLockCheck(key, value)
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -142,10 +148,7 @@ func (m *IntStrMap) GetOrSet(key int, value string) string {
|
|||||||
// GetOrSetFunc returns the value by key,
|
// GetOrSetFunc returns the value by key,
|
||||||
// or sets value with return value of callback function <f> if not exist and returns this value.
|
// or sets value with return value of callback function <f> if not exist and returns this value.
|
||||||
func (m *IntStrMap) GetOrSetFunc(key int, f func() string) string {
|
func (m *IntStrMap) GetOrSetFunc(key int, f func() string) string {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
v, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
return m.doSetWithLockCheck(key, f())
|
return m.doSetWithLockCheck(key, f())
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -158,20 +161,17 @@ func (m *IntStrMap) GetOrSetFunc(key int, f func() string) string {
|
|||||||
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
||||||
// with mutex.Lock of the hash map.
|
// with mutex.Lock of the hash map.
|
||||||
func (m *IntStrMap) GetOrSetFuncLock(key int, f func() string) string {
|
func (m *IntStrMap) GetOrSetFuncLock(key int, f func() string) string {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
val, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
if v, ok := m.data[key]; ok {
|
if v, ok = m.data[key]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
val = f()
|
v = f()
|
||||||
m.data[key] = val
|
m.data[key] = v
|
||||||
return val
|
return v
|
||||||
} else {
|
} else {
|
||||||
return val
|
return v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +301,7 @@ func (m *IntStrMap) RLockFunc(f func(m map[int]string)) {
|
|||||||
f(m.data)
|
f(m.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flip exchanges key-value of the map, it will change key-value to value-key.
|
// Flip exchanges key-value of the map to value-key.
|
||||||
func (m *IntStrMap) Flip() {
|
func (m *IntStrMap) Flip() {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
@ -104,6 +104,15 @@ func (m *StrAnyMap) Sets(data map[string]interface{}) {
|
|||||||
m.mu.Unlock()
|
m.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search searches the map with given <key>.
|
||||||
|
// Second return parameter <found> is true if key was found, otherwise false.
|
||||||
|
func (m *StrAnyMap) Search(key string) (value interface{}, found bool) {
|
||||||
|
m.mu.RLock()
|
||||||
|
value, found = m.data[key]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns the value by given <key>.
|
// Get returns the value by given <key>.
|
||||||
func (m *StrAnyMap) Get(key string) interface{} {
|
func (m *StrAnyMap) Get(key string) interface{} {
|
||||||
m.mu.RLock()
|
m.mu.RLock()
|
||||||
@ -139,7 +148,7 @@ func (m *StrAnyMap) doSetWithLockCheck(key string, value interface{}) interface{
|
|||||||
// GetOrSet returns the value by key,
|
// GetOrSet returns the value by key,
|
||||||
// or set value with given <value> if not exist and returns this value.
|
// or set value with given <value> if not exist and returns this value.
|
||||||
func (m *StrAnyMap) GetOrSet(key string, value interface{}) interface{} {
|
func (m *StrAnyMap) GetOrSet(key string, value interface{}) interface{} {
|
||||||
if v := m.Get(key); v == nil {
|
if v, ok := m.Search(key); !ok {
|
||||||
return m.doSetWithLockCheck(key, value)
|
return m.doSetWithLockCheck(key, value)
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -150,7 +159,7 @@ func (m *StrAnyMap) GetOrSet(key string, value interface{}) interface{} {
|
|||||||
// or sets value with return value of callback function <f> if not exist
|
// or sets value with return value of callback function <f> if not exist
|
||||||
// and returns this value.
|
// and returns this value.
|
||||||
func (m *StrAnyMap) GetOrSetFunc(key string, f func() interface{}) interface{} {
|
func (m *StrAnyMap) GetOrSetFunc(key string, f func() interface{}) interface{} {
|
||||||
if v := m.Get(key); v == nil {
|
if v, ok := m.Search(key); !ok {
|
||||||
return m.doSetWithLockCheck(key, f())
|
return m.doSetWithLockCheck(key, f())
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -164,7 +173,7 @@ func (m *StrAnyMap) GetOrSetFunc(key string, f func() interface{}) interface{} {
|
|||||||
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
||||||
// with mutex.Lock of the hash map.
|
// with mutex.Lock of the hash map.
|
||||||
func (m *StrAnyMap) GetOrSetFuncLock(key string, f func() interface{}) interface{} {
|
func (m *StrAnyMap) GetOrSetFuncLock(key string, f func() interface{}) interface{} {
|
||||||
if v := m.Get(key); v == nil {
|
if v, ok := m.Search(key); !ok {
|
||||||
return m.doSetWithLockCheck(key, f)
|
return m.doSetWithLockCheck(key, f)
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -317,7 +326,7 @@ func (m *StrAnyMap) RLockFunc(f func(m map[string]interface{})) {
|
|||||||
f(m.data)
|
f(m.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flip exchanges key-value of the map, it will change key-value to value-key.
|
// Flip exchanges key-value of the map to value-key.
|
||||||
func (m *StrAnyMap) Flip() {
|
func (m *StrAnyMap) Flip() {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
@ -103,6 +103,15 @@ func (m *StrIntMap) Sets(data map[string]int) {
|
|||||||
m.mu.Unlock()
|
m.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search searches the map with given <key>.
|
||||||
|
// Second return parameter <found> is true if key was found, otherwise false.
|
||||||
|
func (m *StrIntMap) Search(key string) (value int, found bool) {
|
||||||
|
m.mu.RLock()
|
||||||
|
value, found = m.data[key]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns the value by given <key>.
|
// Get returns the value by given <key>.
|
||||||
func (m *StrIntMap) Get(key string) int {
|
func (m *StrIntMap) Get(key string) int {
|
||||||
m.mu.RLock()
|
m.mu.RLock()
|
||||||
@ -130,10 +139,7 @@ func (m *StrIntMap) doSetWithLockCheck(key string, value int) int {
|
|||||||
// GetOrSet returns the value by key,
|
// GetOrSet returns the value by key,
|
||||||
// or set value with given <value> if not exist and returns this value.
|
// or set value with given <value> if not exist and returns this value.
|
||||||
func (m *StrIntMap) GetOrSet(key string, value int) int {
|
func (m *StrIntMap) GetOrSet(key string, value int) int {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
v, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
return m.doSetWithLockCheck(key, value)
|
return m.doSetWithLockCheck(key, value)
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -144,10 +150,7 @@ func (m *StrIntMap) GetOrSet(key string, value int) int {
|
|||||||
// or sets value with return value of callback function <f> if not exist
|
// or sets value with return value of callback function <f> if not exist
|
||||||
// and returns this value.
|
// and returns this value.
|
||||||
func (m *StrIntMap) GetOrSetFunc(key string, f func() int) int {
|
func (m *StrIntMap) GetOrSetFunc(key string, f func() int) int {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
v, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
return m.doSetWithLockCheck(key, f())
|
return m.doSetWithLockCheck(key, f())
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -161,20 +164,17 @@ func (m *StrIntMap) GetOrSetFunc(key string, f func() int) int {
|
|||||||
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
||||||
// with mutex.Lock of the hash map.
|
// with mutex.Lock of the hash map.
|
||||||
func (m *StrIntMap) GetOrSetFuncLock(key string, f func() int) int {
|
func (m *StrIntMap) GetOrSetFuncLock(key string, f func() int) int {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
val, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
if v, ok := m.data[key]; ok {
|
if v, ok = m.data[key]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
val = f()
|
v = f()
|
||||||
m.data[key] = val
|
m.data[key] = v
|
||||||
return val
|
return v
|
||||||
} else {
|
} else {
|
||||||
return val
|
return v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ func (m *StrIntMap) RLockFunc(f func(m map[string]int)) {
|
|||||||
f(m.data)
|
f(m.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flip exchanges key-value of the map, it will change key-value to value-key.
|
// Flip exchanges key-value of the map to value-key.
|
||||||
func (m *StrIntMap) Flip() {
|
func (m *StrIntMap) Flip() {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
@ -102,6 +102,15 @@ func (m *StrStrMap) Sets(data map[string]string) {
|
|||||||
m.mu.Unlock()
|
m.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search searches the map with given <key>.
|
||||||
|
// Second return parameter <found> is true if key was found, otherwise false.
|
||||||
|
func (m *StrStrMap) Search(key string) (value string, found bool) {
|
||||||
|
m.mu.RLock()
|
||||||
|
value, found = m.data[key]
|
||||||
|
m.mu.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns the value by given <key>.
|
// Get returns the value by given <key>.
|
||||||
func (m *StrStrMap) Get(key string) string {
|
func (m *StrStrMap) Get(key string) string {
|
||||||
m.mu.RLock()
|
m.mu.RLock()
|
||||||
@ -129,10 +138,7 @@ func (m *StrStrMap) doSetWithLockCheck(key string, value string) string {
|
|||||||
// GetOrSet returns the value by key,
|
// GetOrSet returns the value by key,
|
||||||
// or set value with given <value> if not exist and returns this value.
|
// or set value with given <value> if not exist and returns this value.
|
||||||
func (m *StrStrMap) GetOrSet(key string, value string) string {
|
func (m *StrStrMap) GetOrSet(key string, value string) string {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
v, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
return m.doSetWithLockCheck(key, value)
|
return m.doSetWithLockCheck(key, value)
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -143,10 +149,7 @@ func (m *StrStrMap) GetOrSet(key string, value string) string {
|
|||||||
// or sets value with return value of callback function <f> if not exist
|
// or sets value with return value of callback function <f> if not exist
|
||||||
// and returns this value.
|
// and returns this value.
|
||||||
func (m *StrStrMap) GetOrSetFunc(key string, f func() string) string {
|
func (m *StrStrMap) GetOrSetFunc(key string, f func() string) string {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
v, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
return m.doSetWithLockCheck(key, f())
|
return m.doSetWithLockCheck(key, f())
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
@ -160,20 +163,17 @@ func (m *StrStrMap) GetOrSetFunc(key string, f func() string) string {
|
|||||||
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
||||||
// with mutex.Lock of the hash map.
|
// with mutex.Lock of the hash map.
|
||||||
func (m *StrStrMap) GetOrSetFuncLock(key string, f func() string) string {
|
func (m *StrStrMap) GetOrSetFuncLock(key string, f func() string) string {
|
||||||
m.mu.RLock()
|
if v, ok := m.Search(key); !ok {
|
||||||
val, ok := m.data[key]
|
|
||||||
m.mu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
if v, ok := m.data[key]; ok {
|
if v, ok = m.data[key]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
val = f()
|
v = f()
|
||||||
m.data[key] = val
|
m.data[key] = v
|
||||||
return val
|
return v
|
||||||
} else {
|
} else {
|
||||||
return val
|
return v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +303,7 @@ func (m *StrStrMap) RLockFunc(f func(m map[string]string)) {
|
|||||||
f(m.data)
|
f(m.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flip exchanges key-value of the map, it will change key-value to value-key.
|
// Flip exchanges key-value of the map to value-key.
|
||||||
func (m *StrStrMap) Flip() {
|
func (m *StrStrMap) Flip() {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
8
g/container/gtree/gtree.go
Normal file
8
g/container/gtree/gtree.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
|
// If a copy of the MIT was not distributed with this file,
|
||||||
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
|
// Package gtree provides concurrent-safe/unsafe tree containers.
|
||||||
|
package gtree
|
@ -8,6 +8,7 @@ package gtree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/gogf/gf/g/container/gvar"
|
||||||
"github.com/gogf/gf/g/internal/rwmutex"
|
"github.com/gogf/gf/g/internal/rwmutex"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,8 +28,8 @@ type RedBlackTree struct {
|
|||||||
|
|
||||||
// RedBlackTreeNode is a single element within the tree
|
// RedBlackTreeNode is a single element within the tree
|
||||||
type RedBlackTreeNode struct {
|
type RedBlackTreeNode struct {
|
||||||
Key interface{}
|
key interface{}
|
||||||
Value interface{}
|
value interface{}
|
||||||
color color
|
color color
|
||||||
left *RedBlackTreeNode
|
left *RedBlackTreeNode
|
||||||
right *RedBlackTreeNode
|
right *RedBlackTreeNode
|
||||||
@ -69,27 +70,27 @@ func (tree *RedBlackTree) Sets(data map[interface{}]interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// doSet inserts key-value item into the tree.
|
// doSet inserts key-value item into the tree without mutex.
|
||||||
func (tree *RedBlackTree) doSet(key interface{}, value interface{}) {
|
func (tree *RedBlackTree) doSet(key interface{}, value interface{}) {
|
||||||
insertedNode := (*RedBlackTreeNode)(nil)
|
insertedNode := (*RedBlackTreeNode)(nil)
|
||||||
if tree.root == nil {
|
if tree.root == nil {
|
||||||
// Assert key is of comparator's type for initial tree
|
// Assert key is of comparator's type for initial tree
|
||||||
tree.comparator(key, key)
|
tree.comparator(key, key)
|
||||||
tree.root = &RedBlackTreeNode{Key: key, Value: value, color: red}
|
tree.root = &RedBlackTreeNode{key: key, value: value, color: red}
|
||||||
insertedNode = tree.root
|
insertedNode = tree.root
|
||||||
} else {
|
} else {
|
||||||
node := tree.root
|
node := tree.root
|
||||||
loop := true
|
loop := true
|
||||||
for loop {
|
for loop {
|
||||||
compare := tree.comparator(key, node.Key)
|
compare := tree.comparator(key, node.key)
|
||||||
switch {
|
switch {
|
||||||
case compare == 0:
|
case compare == 0:
|
||||||
node.Key = key
|
//node.key = key
|
||||||
node.Value = value
|
node.value = value
|
||||||
return
|
return
|
||||||
case compare < 0:
|
case compare < 0:
|
||||||
if node.left == nil {
|
if node.left == nil {
|
||||||
node.left = &RedBlackTreeNode{Key: key, Value: value, color: red}
|
node.left = &RedBlackTreeNode{key: key, value: value, color: red}
|
||||||
insertedNode = node.left
|
insertedNode = node.left
|
||||||
loop = false
|
loop = false
|
||||||
} else {
|
} else {
|
||||||
@ -97,7 +98,7 @@ func (tree *RedBlackTree) doSet(key interface{}, value interface{}) {
|
|||||||
}
|
}
|
||||||
case compare > 0:
|
case compare > 0:
|
||||||
if node.right == nil {
|
if node.right == nil {
|
||||||
node.right = &RedBlackTreeNode{Key: key, Value: value, color: red}
|
node.right = &RedBlackTreeNode{key: key, value: value, color: red}
|
||||||
insertedNode = node.right
|
insertedNode = node.right
|
||||||
loop = false
|
loop = false
|
||||||
} else {
|
} else {
|
||||||
@ -113,22 +114,132 @@ func (tree *RedBlackTree) doSet(key interface{}, value interface{}) {
|
|||||||
|
|
||||||
// Get searches the node in the tree by <key> and returns its value or nil if key is not found in tree.
|
// Get searches the node in the tree by <key> and returns its value or nil if key is not found in tree.
|
||||||
func (tree *RedBlackTree) Get(key interface{}) (value interface{}) {
|
func (tree *RedBlackTree) Get(key interface{}) (value interface{}) {
|
||||||
node := tree.Search(key)
|
value, _ = tree.Search(key)
|
||||||
if node != nil {
|
return
|
||||||
return node.Value
|
}
|
||||||
|
|
||||||
|
// doSetWithLockCheck checks whether value of the key exists with mutex.Lock,
|
||||||
|
// if not exists, set value to the map with given <key>,
|
||||||
|
// or else just return the existing value.
|
||||||
|
//
|
||||||
|
// When setting value, if <value> is type of <func() interface {}>,
|
||||||
|
// it will be executed with mutex.Lock of the hash map,
|
||||||
|
// and its return value will be set to the map with <key>.
|
||||||
|
//
|
||||||
|
// It returns value with given <key>.
|
||||||
|
func (tree *RedBlackTree) doSetWithLockCheck(key interface{}, value interface{}) interface{} {
|
||||||
|
tree.mu.Lock()
|
||||||
|
defer tree.mu.Unlock()
|
||||||
|
if node := tree.doSearch(key); node != nil {
|
||||||
|
return node.value
|
||||||
}
|
}
|
||||||
return nil
|
if f, ok := value.(func() interface {}); ok {
|
||||||
|
value = f()
|
||||||
|
}
|
||||||
|
tree.doSet(key, value)
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrSet returns the value by key,
|
||||||
|
// or set value with given <value> if not exist and returns this value.
|
||||||
|
func (tree *RedBlackTree) GetOrSet(key interface{}, value interface{}) interface{} {
|
||||||
|
if v, ok := tree.Search(key); !ok {
|
||||||
|
return tree.doSetWithLockCheck(key, value)
|
||||||
|
} else {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrSetFunc returns the value by key,
|
||||||
|
// or sets value with return value of callback function <f> if not exist
|
||||||
|
// and returns this value.
|
||||||
|
func (tree *RedBlackTree) GetOrSetFunc(key interface{}, f func() interface{}) interface{} {
|
||||||
|
if v, ok := tree.Search(key); !ok {
|
||||||
|
return tree.doSetWithLockCheck(key, f())
|
||||||
|
} else {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOrSetFuncLock returns the value by key,
|
||||||
|
// or sets value with return value of callback function <f> if not exist
|
||||||
|
// and returns this value.
|
||||||
|
//
|
||||||
|
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f>
|
||||||
|
// with mutex.Lock of the hash map.
|
||||||
|
func (tree *RedBlackTree) GetOrSetFuncLock(key interface{}, f func() interface{}) interface{} {
|
||||||
|
if v, ok := tree.Search(key); !ok {
|
||||||
|
return tree.doSetWithLockCheck(key, f)
|
||||||
|
} else {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVar returns a gvar.Var with the value by given <key>.
|
||||||
|
// The returned gvar.Var is un-concurrent safe.
|
||||||
|
func (tree *RedBlackTree) GetVar(key interface{}) *gvar.Var {
|
||||||
|
return gvar.New(tree.Get(key), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVarOrSet returns a gvar.Var with result from GetVarOrSet.
|
||||||
|
// The returned gvar.Var is un-concurrent safe.
|
||||||
|
func (tree *RedBlackTree) GetVarOrSet(key interface{}, value interface{}) *gvar.Var {
|
||||||
|
return gvar.New(tree.GetOrSet(key, value), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVarOrSetFunc returns a gvar.Var with result from GetOrSetFunc.
|
||||||
|
// The returned gvar.Var is un-concurrent safe.
|
||||||
|
func (tree *RedBlackTree) GetVarOrSetFunc(key interface{}, f func() interface{}) *gvar.Var {
|
||||||
|
return gvar.New(tree.GetOrSetFunc(key, f), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVarOrSetFuncLock returns a gvar.Var with result from GetOrSetFuncLock.
|
||||||
|
// The returned gvar.Var is un-concurrent safe.
|
||||||
|
func (tree *RedBlackTree) GetVarOrSetFuncLock(key interface{}, f func() interface{}) *gvar.Var {
|
||||||
|
return gvar.New(tree.GetOrSetFuncLock(key, f), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIfNotExist sets <value> to the map if the <key> does not exist, then return true.
|
||||||
|
// It returns false if <key> exists, and <value> would be ignored.
|
||||||
|
func (tree *RedBlackTree) SetIfNotExist(key interface{}, value interface{}) bool {
|
||||||
|
if !tree.Contains(key) {
|
||||||
|
tree.doSetWithLockCheck(key, value)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIfNotExistFunc sets value with return value of callback function <f>, then return true.
|
||||||
|
// It returns false if <key> exists, and <value> would be ignored.
|
||||||
|
func (tree *RedBlackTree) SetIfNotExistFunc(key interface{}, f func() interface{}) bool {
|
||||||
|
if !tree.Contains(key) {
|
||||||
|
tree.doSetWithLockCheck(key, f())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIfNotExistFuncLock sets value with return value of callback function <f>, then return true.
|
||||||
|
// It returns false if <key> exists, and <value> would be ignored.
|
||||||
|
//
|
||||||
|
// SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that
|
||||||
|
// it executes function <f> with mutex.Lock of the hash map.
|
||||||
|
func (tree *RedBlackTree) SetIfNotExistFuncLock(key interface{}, f func() interface{}) bool {
|
||||||
|
if !tree.Contains(key) {
|
||||||
|
tree.doSetWithLockCheck(key, f)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contains checks whether <key> exists in the tree.
|
// Contains checks whether <key> exists in the tree.
|
||||||
func (tree *RedBlackTree) Contains(key interface{}) bool {
|
func (tree *RedBlackTree) Contains(key interface{}) bool {
|
||||||
return tree.Search(key) != nil
|
_, ok := tree.Search(key)
|
||||||
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the node from the tree by <key>.
|
// doRemove removes the node from the tree by <key> without mutex.
|
||||||
func (tree *RedBlackTree) Remove(key interface{}) (value interface{}) {
|
func (tree *RedBlackTree) doRemove(key interface{}) (value interface{}) {
|
||||||
tree.mu.Lock()
|
|
||||||
defer tree.mu.Unlock()
|
|
||||||
child := (*RedBlackTreeNode)(nil)
|
child := (*RedBlackTreeNode)(nil)
|
||||||
node := tree.doSearch(key)
|
node := tree.doSearch(key)
|
||||||
if node == nil {
|
if node == nil {
|
||||||
@ -136,8 +247,8 @@ func (tree *RedBlackTree) Remove(key interface{}) (value interface{}) {
|
|||||||
}
|
}
|
||||||
if node.left != nil && node.right != nil {
|
if node.left != nil && node.right != nil {
|
||||||
p := node.left.maximumNode()
|
p := node.left.maximumNode()
|
||||||
node.Key = p.Key
|
node.key = p.key
|
||||||
node.Value = p.Value
|
node.value = p.value
|
||||||
node = p
|
node = p
|
||||||
}
|
}
|
||||||
if node.left == nil || node.right == nil {
|
if node.left == nil || node.right == nil {
|
||||||
@ -156,10 +267,26 @@ func (tree *RedBlackTree) Remove(key interface{}) (value interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tree.size--
|
tree.size--
|
||||||
value = node.Value
|
value = node.value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove removes the node from the tree by <key>.
|
||||||
|
func (tree *RedBlackTree) Remove(key interface{}) (value interface{}) {
|
||||||
|
tree.mu.Lock()
|
||||||
|
defer tree.mu.Unlock()
|
||||||
|
return tree.doRemove(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes batch deletes values of the tree by <keys>.
|
||||||
|
func (tree *RedBlackTree) Removes(keys []interface{}) {
|
||||||
|
tree.mu.Lock()
|
||||||
|
defer tree.mu.Unlock()
|
||||||
|
for key := range keys {
|
||||||
|
tree.doRemove(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// IsEmpty returns true if tree does not contain any nodes.
|
// IsEmpty returns true if tree does not contain any nodes.
|
||||||
func (tree *RedBlackTree) IsEmpty() bool {
|
func (tree *RedBlackTree) IsEmpty() bool {
|
||||||
return tree.Size() == 0
|
return tree.Size() == 0
|
||||||
@ -174,9 +301,7 @@ func (tree *RedBlackTree) Size() int {
|
|||||||
|
|
||||||
// Keys returns all keys in asc order.
|
// Keys returns all keys in asc order.
|
||||||
func (tree *RedBlackTree) Keys() []interface{} {
|
func (tree *RedBlackTree) Keys() []interface{} {
|
||||||
tree.mu.RLock()
|
keys := make([]interface{}, tree.Size())
|
||||||
defer tree.mu.RUnlock()
|
|
||||||
keys := make([]interface{}, tree.size)
|
|
||||||
index := 0
|
index := 0
|
||||||
tree.IteratorAsc(func(key, value interface{}) bool {
|
tree.IteratorAsc(func(key, value interface{}) bool {
|
||||||
keys[index] = key
|
keys[index] = key
|
||||||
@ -188,9 +313,7 @@ func (tree *RedBlackTree) Keys() []interface{} {
|
|||||||
|
|
||||||
// Values returns all values in asc order based on the key.
|
// Values returns all values in asc order based on the key.
|
||||||
func (tree *RedBlackTree) Values() []interface{} {
|
func (tree *RedBlackTree) Values() []interface{} {
|
||||||
tree.mu.RLock()
|
values := make([]interface{}, tree.Size())
|
||||||
defer tree.mu.RUnlock()
|
|
||||||
values := make([]interface{}, tree.size)
|
|
||||||
index := 0
|
index := 0
|
||||||
tree.IteratorAsc(func(key, value interface{}) bool {
|
tree.IteratorAsc(func(key, value interface{}) bool {
|
||||||
values[index] = key
|
values[index] = key
|
||||||
@ -202,9 +325,7 @@ func (tree *RedBlackTree) Values() []interface{} {
|
|||||||
|
|
||||||
// Map returns all key-value items as map.
|
// Map returns all key-value items as map.
|
||||||
func (tree *RedBlackTree) Map() map[interface{}]interface{} {
|
func (tree *RedBlackTree) Map() map[interface{}]interface{} {
|
||||||
tree.mu.RLock()
|
m := make(map[interface{}]interface{}, tree.Size())
|
||||||
defer tree.mu.RUnlock()
|
|
||||||
m := make(map[interface{}]interface{}, tree.size)
|
|
||||||
tree.IteratorAsc(func(key, value interface{}) bool {
|
tree.IteratorAsc(func(key, value interface{}) bool {
|
||||||
m[key] = value
|
m[key] = value
|
||||||
return true
|
return true
|
||||||
@ -249,7 +370,7 @@ func (tree *RedBlackTree) Floor(key interface{}) (floor *RedBlackTreeNode) {
|
|||||||
found := false
|
found := false
|
||||||
node := tree.root
|
node := tree.root
|
||||||
for node != nil {
|
for node != nil {
|
||||||
compare := tree.comparator(key, node.Key)
|
compare := tree.comparator(key, node.key)
|
||||||
switch {
|
switch {
|
||||||
case compare == 0:
|
case compare == 0:
|
||||||
return node
|
return node
|
||||||
@ -277,7 +398,7 @@ func (tree *RedBlackTree) Ceiling(key interface{}) (ceiling *RedBlackTreeNode) {
|
|||||||
found := false
|
found := false
|
||||||
node := tree.root
|
node := tree.root
|
||||||
for node != nil {
|
for node != nil {
|
||||||
compare := tree.comparator(key, node.Key)
|
compare := tree.comparator(key, node.key)
|
||||||
switch {
|
switch {
|
||||||
case compare == 0:
|
case compare == 0:
|
||||||
return node
|
return node
|
||||||
@ -308,7 +429,7 @@ func (tree *RedBlackTree) IteratorAsc(f func (key, value interface{}) bool) {
|
|||||||
if node == nil {
|
if node == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !f(node.Key, node.Value) {
|
if !f(node.key, node.value) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if node.right != nil {
|
if node.right != nil {
|
||||||
@ -322,7 +443,7 @@ func (tree *RedBlackTree) IteratorAsc(f func (key, value interface{}) bool) {
|
|||||||
old := node
|
old := node
|
||||||
for node.parent != nil {
|
for node.parent != nil {
|
||||||
node = node.parent
|
node = node.parent
|
||||||
if tree.comparator(old.Key, node.Key) <= 0 {
|
if tree.comparator(old.key, node.key) <= 0 {
|
||||||
goto loop
|
goto loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -345,7 +466,7 @@ func (tree *RedBlackTree) IteratorDesc(f func (key, value interface{}) bool) {
|
|||||||
if node == nil {
|
if node == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !f(node.Key, node.Value) {
|
if !f(node.key, node.value) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if node.left != nil {
|
if node.left != nil {
|
||||||
@ -359,7 +480,7 @@ func (tree *RedBlackTree) IteratorDesc(f func (key, value interface{}) bool) {
|
|||||||
old := node
|
old := node
|
||||||
for node.parent != nil {
|
for node.parent != nil {
|
||||||
node = node.parent
|
node = node.parent
|
||||||
if tree.comparator(old.Key, node.Key) >= 0 {
|
if tree.comparator(old.key, node.key) >= 0 {
|
||||||
goto loop
|
goto loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -393,15 +514,41 @@ func (tree *RedBlackTree) Print() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (node *RedBlackTreeNode) String() string {
|
func (node *RedBlackTreeNode) String() string {
|
||||||
return fmt.Sprintf("%v", node.Key)
|
return fmt.Sprintf("%v", node.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search searches the tree with given <key>.
|
// Search searches the tree with given <key>.
|
||||||
// It returns the node if found or otherwise nil.
|
// Second return parameter <found> is true if key was found, otherwise false.
|
||||||
func (tree *RedBlackTree) Search(key interface{}) *RedBlackTreeNode {
|
func (tree *RedBlackTree) Search(key interface{}) (value interface{}, found bool) {
|
||||||
tree.mu.RLock()
|
tree.mu.RLock()
|
||||||
defer tree.mu.RUnlock()
|
defer tree.mu.RUnlock()
|
||||||
return tree.doSearch(key)
|
node := tree.doSearch(key)
|
||||||
|
if node != nil {
|
||||||
|
return node.value, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flip exchanges key-value of the tree to value-key.
|
||||||
|
// Note that you should guarantee the value is the same type as key,
|
||||||
|
// or else the comparator would panic.
|
||||||
|
//
|
||||||
|
// If the type of value is different with key, you pass the new <comparator>.
|
||||||
|
func (tree *RedBlackTree) Flip(comparator...func(v1, v2 interface{}) int) {
|
||||||
|
t := (*RedBlackTree)(nil)
|
||||||
|
if len(comparator) > 0 {
|
||||||
|
t = NewRedBlackTree(comparator[0], !tree.mu.IsSafe())
|
||||||
|
} else {
|
||||||
|
t = NewRedBlackTree(tree.comparator, !tree.mu.IsSafe())
|
||||||
|
}
|
||||||
|
tree.IteratorAsc(func(key, value interface{}) bool {
|
||||||
|
t.doSet(value, key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
tree.mu.Lock()
|
||||||
|
tree.root = t.root
|
||||||
|
tree.size = t.size
|
||||||
|
tree.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tree *RedBlackTree) output(node *RedBlackTreeNode, prefix string, isTail bool, str *string) {
|
func (tree *RedBlackTree) output(node *RedBlackTreeNode, prefix string, isTail bool, str *string) {
|
||||||
@ -432,19 +579,16 @@ func (tree *RedBlackTree) output(node *RedBlackTreeNode, prefix string, isTail b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search searches the tree with given <key>.
|
// Search searches the tree with given <key> without mutex.
|
||||||
// It returns the node if found or otherwise nil.
|
// It returns the node if found or otherwise nil.
|
||||||
func (tree *RedBlackTree) doSearch(key interface{}) *RedBlackTreeNode {
|
func (tree *RedBlackTree) doSearch(key interface{}) *RedBlackTreeNode {
|
||||||
node := tree.root
|
node := tree.root
|
||||||
for node != nil {
|
for node != nil {
|
||||||
compare := tree.comparator(key, node.Key)
|
compare := tree.comparator(key, node.key)
|
||||||
switch {
|
switch {
|
||||||
case compare == 0:
|
case compare == 0: return node
|
||||||
return node
|
case compare < 0: node = node.left
|
||||||
case compare < 0:
|
case compare > 0: node = node.right
|
||||||
node = node.left
|
|
||||||
case compare > 0:
|
|
||||||
node = node.right
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
// Copyright 2018-2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the MIT License.
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
// If a copy of the MIT was not distributed with this file,
|
// If a copy of the MIT was not distributed with this file,
|
||||||
@ -33,18 +33,6 @@ func New(value interface{}, unsafe...bool) *Var {
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRead returns a read-only interface object with given <value>.
|
|
||||||
// The param <unsafe> used to specify whether using Var in un-concurrent-safety,
|
|
||||||
// which is false in default, means concurrent-safe.
|
|
||||||
func NewRead(value interface{}, unsafe...bool) VarRead {
|
|
||||||
return VarRead(New(value, unsafe...))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadOnly returns a read-only interface object of <v>.
|
|
||||||
func (v *Var) ReadOnly() VarRead {
|
|
||||||
return VarRead(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set sets <value> to <v>, and returns the old value.
|
// Set sets <value> to <v>, and returns the old value.
|
||||||
func (v *Var) Set(value interface{}) (old interface{}) {
|
func (v *Var) Set(value interface{}) (old interface{}) {
|
||||||
if v.safe {
|
if v.safe {
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
|
||||||
//
|
|
||||||
// This Source Code Form is subject to the terms of the MIT License.
|
|
||||||
// If a copy of the MIT was not distributed with this file,
|
|
||||||
// You can obtain one at https://github.com/gogf/gf.
|
|
||||||
|
|
||||||
package gvar
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gogf/gf/g/os/gtime"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Read-only interface.
|
|
||||||
type VarRead interface {
|
|
||||||
Val() interface{}
|
|
||||||
IsNil() bool
|
|
||||||
Bytes() []byte
|
|
||||||
String() string
|
|
||||||
Bool() bool
|
|
||||||
Int() int
|
|
||||||
Int8() int8
|
|
||||||
Int16() int16
|
|
||||||
Int32() int32
|
|
||||||
Int64() int64
|
|
||||||
Uint() uint
|
|
||||||
Uint8() uint8
|
|
||||||
Uint16() uint16
|
|
||||||
Uint32() uint32
|
|
||||||
Uint64() uint64
|
|
||||||
Float32() float32
|
|
||||||
Float64() float64
|
|
||||||
Interface() interface{}
|
|
||||||
|
|
||||||
Ints() []int
|
|
||||||
Floats() []float64
|
|
||||||
Strings() []string
|
|
||||||
Interfaces() []interface{}
|
|
||||||
|
|
||||||
Time(format ...string) time.Time
|
|
||||||
TimeDuration() time.Duration
|
|
||||||
GTime(format...string) *gtime.Time
|
|
||||||
Struct(objPointer interface{}, attrMapping ...map[string]string) error
|
|
||||||
}
|
|
@ -1,3 +1,9 @@
|
|||||||
|
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the MIT License.
|
||||||
|
// If a copy of the MIT was not distributed with this file,
|
||||||
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
package gvar_test
|
package gvar_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -9,22 +15,6 @@ import (
|
|||||||
"github.com/gogf/gf/g/test/gtest"
|
"github.com/gogf/gf/g/test/gtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadOnly(t *testing.T) {
|
|
||||||
gtest.Case(t, func() {
|
|
||||||
obj := gvar.New(nil, true)
|
|
||||||
var result string
|
|
||||||
|
|
||||||
switch obj.ReadOnly().(type) {
|
|
||||||
case gvar.VarRead:
|
|
||||||
result = "yes"
|
|
||||||
default:
|
|
||||||
result = "no"
|
|
||||||
}
|
|
||||||
|
|
||||||
gtest.Assert(result, "yes")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSet(t *testing.T) {
|
func TestSet(t *testing.T) {
|
||||||
gtest.Case(t, func() {
|
gtest.Case(t, func() {
|
||||||
objOne := gvar.New("old", true)
|
objOne := gvar.New("old", true)
|
||||||
|
@ -32,7 +32,7 @@ func init() {
|
|||||||
// 规则:
|
// 规则:
|
||||||
// 1、命令行参数以小写字母格式,使用: gf.包名.变量名 传递;
|
// 1、命令行参数以小写字母格式,使用: gf.包名.变量名 传递;
|
||||||
// 2、环境变量参数以大写字母格式,使用: GF_包名_变量名 传递;
|
// 2、环境变量参数以大写字母格式,使用: GF_包名_变量名 传递;
|
||||||
func Get(key string, def...interface{}) gvar.VarRead {
|
func Get(key string, def...interface{}) *gvar.Var {
|
||||||
value := interface{}(nil)
|
value := interface{}(nil)
|
||||||
if len(def) > 0 {
|
if len(def) > 0 {
|
||||||
value = def[0]
|
value = def[0]
|
||||||
|
@ -76,7 +76,7 @@ func (r *Request) Get(key string, def...interface{}) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 建议都用该参数替代参数获取
|
// 建议都用该参数替代参数获取
|
||||||
func (r *Request) GetVar(key string, def...interface{}) gvar.VarRead {
|
func (r *Request) GetVar(key string, def...interface{}) *gvar.Var {
|
||||||
return r.GetRequestVar(key, def...)
|
return r.GetRequestVar(key, def...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ func (r *Request) SetParam(key string, value interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取请求流程共享变量
|
// 获取请求流程共享变量
|
||||||
func (r *Request) GetParam(key string, def...interface{}) gvar.VarRead {
|
func (r *Request) GetParam(key string, def...interface{}) *gvar.Var {
|
||||||
if r.params != nil {
|
if r.params != nil {
|
||||||
if v, ok := r.params[key]; ok {
|
if v, ok := r.params[key]; ok {
|
||||||
return gvar.New(v, true)
|
return gvar.New(v, true)
|
||||||
|
@ -26,7 +26,7 @@ func (r *Request) GetRequest(key string, def...interface{}) []string {
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Request) GetRequestVar(key string, def...interface{}) gvar.VarRead {
|
func (r *Request) GetRequestVar(key string, def...interface{}) *gvar.Var {
|
||||||
value := r.GetRequest(key, def...)
|
value := r.GetRequest(key, def...)
|
||||||
if value != nil {
|
if value != nil {
|
||||||
return gvar.New(value[0], true)
|
return gvar.New(value[0], true)
|
||||||
|
@ -113,7 +113,7 @@ func (s *Session) Get(key string, def...interface{}) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取SESSION,建议都用该方法获取参数
|
// 获取SESSION,建议都用该方法获取参数
|
||||||
func (s *Session) GetVar(key string, def...interface{}) gvar.VarRead {
|
func (s *Session) GetVar(key string, def...interface{}) *gvar.Var {
|
||||||
return gvar.NewRead(s.Get(key, def...), true)
|
return gvar.NewRead(s.Get(key, def...), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ func (c *Config) Get(pattern string, def...interface{}) interface{} {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetVar(pattern string, def...interface{}) gvar.VarRead {
|
func (c *Config) GetVar(pattern string, def...interface{}) *gvar.Var {
|
||||||
if j := c.getJson(); j != nil {
|
if j := c.getJson(); j != nil {
|
||||||
return gvar.New(j.Get(pattern, def...), true)
|
return gvar.New(j.Get(pattern, def...), true)
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ func (c *gCmdOption) Get(key string, def...string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetVar returns the option value as gvar.VarRead object specified by <key>,
|
// GetVar returns the option value as *gvar.Var object specified by <key>,
|
||||||
// if value does not exist, then returns <def> as its default value.
|
// if value does not exist, then returns <def> as its default value.
|
||||||
func (c *gCmdOption) GetVar(key string, def...string) gvar.VarRead {
|
func (c *gCmdOption) GetVar(key string, def...string) *gvar.Var {
|
||||||
return gvar.NewRead(c.Get(key, def...), true)
|
return gvar.NewRead(c.Get(key, def...), true)
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ func (c *gCmdValue) Get(index int, def...string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetVar returns value by index <index> as gvar.VarRead object,
|
// GetVar returns value by index <index> as *gvar.Var object,
|
||||||
// if value does not exist, then returns <def> as its default value.
|
// if value does not exist, then returns <def> as its default value.
|
||||||
func (c *gCmdValue) GetVar(index int, def...string) gvar.VarRead {
|
func (c *gCmdValue) GetVar(index int, def...string) *gvar.Var {
|
||||||
return gvar.NewRead(c.Get(index, def...), true)
|
return gvar.NewRead(c.Get(index, def...), true)
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,17 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/gogf/gf/g/container/gtree"
|
"github.com/gogf/gf/g/container/gtree"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
tree := gtree.New(func(v1, v2 interface{}) int {
|
tree := gtree.NewRedBlackTree(func(v1, v2 interface{}) int {
|
||||||
return v1.(int) - v2.(int)
|
return v1.(int) - v2.(int)
|
||||||
})
|
})
|
||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 20; i++ {
|
||||||
tree.Set(i, i)
|
tree.Set(i, i*10)
|
||||||
}
|
}
|
||||||
tree.Print()
|
tree.Print()
|
||||||
tree.IteratorAsc(func(key, value interface{}) bool {
|
tree.Flip()
|
||||||
fmt.Println(key)
|
tree.Print()
|
||||||
return true
|
|
||||||
})
|
|
||||||
fmt.Println()
|
|
||||||
tree.IteratorDesc(func(key, value interface{}) bool {
|
|
||||||
fmt.Println(key)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user