add gtree.RedBlackTree container

This commit is contained in:
John 2019-05-10 13:38:06 +08:00
parent b15d8bdd2e
commit abaef9ba87
21 changed files with 334 additions and 229 deletions

View File

@ -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
} }

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View 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

View File

@ -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

View File

@ -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 {

View File

@ -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
}

View File

@ -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)

View File

@ -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]

View File

@ -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...)
} }

View File

@ -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)

View File

@ -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)

View File

@ -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)
} }

View File

@ -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)
} }

View File

@ -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)
} }

View File

@ -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)
} }

View File

@ -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
})
} }