gitlab.com/evatix-go/core@v1.3.55/coredata/corestr/CharHashsetMap.go (about)

     1  package corestr
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"sort"
     7  	"strings"
     8  	"sync"
     9  
    10  	"gitlab.com/evatix-go/core/constants"
    11  	"gitlab.com/evatix-go/core/coredata/corejson"
    12  	"gitlab.com/evatix-go/core/coreindexes"
    13  )
    14  
    15  type CharHashsetMap struct {
    16  	items               map[byte]*Hashset
    17  	eachHashsetCapacity int
    18  	sync.Mutex
    19  }
    20  
    21  func (it *CharHashsetMap) GetChar(
    22  	str string,
    23  ) byte {
    24  	if str != "" {
    25  		return str[coreindexes.First]
    26  	}
    27  
    28  	return emptyChar
    29  }
    30  
    31  func (it *CharHashsetMap) HashsetsCollectionByChars(
    32  	chars ...byte,
    33  ) *HashsetsCollection {
    34  	if it.IsEmpty() {
    35  		return Empty.HashsetsCollection()
    36  	}
    37  
    38  	hashsets := make(
    39  		[]*Hashset,
    40  		0,
    41  		it.Length())
    42  
    43  	for _, char := range chars {
    44  		hashset := it.HashsetByChar(char)
    45  		if hashset == nil ||
    46  			hashset.IsEmpty() {
    47  			continue
    48  		}
    49  
    50  		hashsets = append(hashsets, hashset)
    51  	}
    52  
    53  	return New.HashsetsCollection.UsingHashsetsPointers(hashsets...)
    54  }
    55  
    56  func (it *CharHashsetMap) HashsetsCollectionByStringsFirstChar(
    57  	stringItems ...string,
    58  ) *HashsetsCollection {
    59  	if it.IsEmpty() {
    60  		return Empty.HashsetsCollection()
    61  	}
    62  
    63  	hashsets := make(
    64  		[]*Hashset,
    65  		0,
    66  		it.Length())
    67  
    68  	for _, item := range stringItems {
    69  		char := it.GetChar(item)
    70  		hashset := it.HashsetByChar(char)
    71  
    72  		if hashset == nil || hashset.IsEmpty() {
    73  			continue
    74  		}
    75  
    76  		hashsets = append(hashsets, hashset)
    77  	}
    78  
    79  	return New.HashsetsCollection.UsingHashsetsPointers(hashsets...)
    80  }
    81  
    82  func (it *CharHashsetMap) HashsetsCollection() *HashsetsCollection {
    83  	if it.IsEmpty() {
    84  		return Empty.HashsetsCollection()
    85  	}
    86  
    87  	hashsets := make(
    88  		[]Hashset,
    89  		0,
    90  		it.Length())
    91  
    92  	for _, hashset := range it.items {
    93  		//goland:noinspection ALL
    94  		hashsets = append(hashsets, *hashset)
    95  	}
    96  
    97  	return New.HashsetsCollection.UsingHashsets(hashsets...)
    98  }
    99  
   100  func (it *CharHashsetMap) GetCharOfPtr(
   101  	str *string,
   102  ) byte {
   103  	if str == nil || *str == "" {
   104  		return emptyChar
   105  	}
   106  
   107  	return (*str)[coreindexes.First]
   108  }
   109  
   110  func (it *CharHashsetMap) GetCharsPtrGroups(
   111  	items *[]string,
   112  ) *CharHashsetMap {
   113  	if items == nil || *items == nil {
   114  		return it
   115  	}
   116  
   117  	length := len(*items)
   118  
   119  	if length == 0 {
   120  		return nil
   121  	}
   122  
   123  	hashsetMap := New.CharHashsetMap.Cap(
   124  		length,
   125  		length/3)
   126  
   127  	return hashsetMap.AddStringsPtr(items)
   128  }
   129  
   130  func (it *CharHashsetMap) GetMap() map[byte]*Hashset {
   131  	return it.items
   132  }
   133  
   134  // GetCopyMapLock Sends a copy of items
   135  func (it *CharHashsetMap) GetCopyMapLock() map[byte]*Hashset {
   136  	it.Lock()
   137  	defer it.Unlock()
   138  
   139  	if it.IsEmpty() {
   140  		return map[byte]*Hashset{}
   141  	}
   142  
   143  	// todo fix copying
   144  	return it.items
   145  }
   146  
   147  func (it *CharHashsetMap) SummaryStringLock() string {
   148  	length := it.LengthLock()
   149  	hashsetOfHashset := make(
   150  		[]string,
   151  		length+1)
   152  
   153  	hashsetOfHashset[coreindexes.First] = fmt.Sprintf(
   154  		summaryOfCharHashsetMapLengthFormat,
   155  		it,
   156  		length,
   157  		coreindexes.First)
   158  
   159  	i := 1
   160  	for key, hashset := range it.GetCopyMapLock() {
   161  		hashsetOfHashset[i] = fmt.Sprintf(
   162  			charHashsetMapSingleItemFormat,
   163  			i,
   164  			string(key),
   165  			hashset.LengthLock())
   166  
   167  		i++
   168  	}
   169  
   170  	return strings.Join(
   171  		hashsetOfHashset,
   172  		constants.EmptyString)
   173  }
   174  
   175  func (it *CharHashsetMap) SummaryString() string {
   176  	hashsetOfHashset := make(
   177  		[]string,
   178  		it.Length()+1)
   179  
   180  	hashsetOfHashset[coreindexes.First] = fmt.Sprintf(
   181  		summaryOfCharHashsetMapLengthFormat,
   182  		it,
   183  		it.Length(),
   184  		coreindexes.First)
   185  
   186  	i := 1
   187  	for key, hashset := range it.items {
   188  		hashsetOfHashset[i] = fmt.Sprintf(
   189  			charHashsetMapSingleItemFormat,
   190  			i,
   191  			string(key),
   192  			hashset.Length())
   193  
   194  		i++
   195  	}
   196  
   197  	return strings.Join(
   198  		hashsetOfHashset,
   199  		constants.EmptyString)
   200  }
   201  
   202  func (it *CharHashsetMap) String() string {
   203  	hashsetOfHashset := make(
   204  		[]string,
   205  		it.Length()*2+1)
   206  
   207  	hashsetOfHashset[coreindexes.First] =
   208  		it.SummaryString()
   209  
   210  	i := 1
   211  	for key, hashset := range it.items {
   212  		hashsetOfHashset[i] = fmt.Sprintf(
   213  			charHashsetMapLengthFormat,
   214  			string(key))
   215  
   216  		i++
   217  		hashsetOfHashset[i] = hashset.String()
   218  		i++
   219  	}
   220  
   221  	return strings.Join(
   222  		hashsetOfHashset,
   223  		constants.EmptyString)
   224  }
   225  
   226  func (it *CharHashsetMap) StringLock() string {
   227  	hashsetOfHashset := make(
   228  		[]string,
   229  		it.LengthLock()*2+1)
   230  
   231  	hashsetOfHashset[coreindexes.First] =
   232  		it.SummaryStringLock()
   233  
   234  	i := 1
   235  	for key, hashset := range it.GetCopyMapLock() {
   236  
   237  		hashsetOfHashset[i] = fmt.Sprintf(
   238  			charHashsetMapLengthFormat,
   239  			string(key))
   240  
   241  		i++
   242  
   243  		hashsetOfHashset[i] = hashset.StringLock()
   244  		i++
   245  	}
   246  
   247  	return strings.Join(
   248  		hashsetOfHashset,
   249  		constants.EmptyString)
   250  }
   251  
   252  func (it *CharHashsetMap) List() *[]string {
   253  	list := make([]string, it.AllLengthsSum())
   254  
   255  	i := 0
   256  	for _, hashset := range it.items {
   257  		for s := range hashset.items {
   258  			list[i] = s
   259  			i++
   260  		}
   261  	}
   262  
   263  	return &list
   264  }
   265  
   266  func (it *CharHashsetMap) SortedListAsc() *[]string {
   267  	list := it.List()
   268  	sort.Strings(*list)
   269  
   270  	return list
   271  }
   272  
   273  func (it *CharHashsetMap) SortedListDsc() *[]string {
   274  	list := it.SortedListAsc()
   275  	length := len(*list)
   276  	mid := length / 2
   277  
   278  	for i := 0; i < mid; i++ {
   279  		temp := (*list)[i]
   280  		(*list)[i] = (*list)[length-1-i]
   281  		(*list)[length-1-i] = temp
   282  	}
   283  
   284  	return list
   285  }
   286  
   287  func (it *CharHashsetMap) Print(isPrint bool) {
   288  	if !isPrint {
   289  		return
   290  	}
   291  
   292  	fmt.Println(
   293  		it.String(),
   294  	)
   295  }
   296  
   297  func (it *CharHashsetMap) PrintLock(isPrint bool) {
   298  	if !isPrint {
   299  		return
   300  	}
   301  
   302  	fmt.Println(
   303  		it.StringLock(),
   304  	)
   305  }
   306  
   307  func (it *CharHashsetMap) IsEmpty() bool {
   308  	return it == nil ||
   309  		len(it.items) == 0
   310  }
   311  
   312  func (it *CharHashsetMap) HasItems() bool {
   313  	return it != nil && len(it.items) > 0
   314  }
   315  
   316  func (it *CharHashsetMap) IsEmptyLock() bool {
   317  	it.Lock()
   318  	defer it.Unlock()
   319  
   320  	return it.IsEmpty()
   321  }
   322  
   323  // LengthOfHashsetFromFirstChar Get the char of the string given and get the length of how much is there.
   324  func (it *CharHashsetMap) LengthOfHashsetFromFirstChar(
   325  	str string,
   326  ) int {
   327  	char := it.GetChar(str)
   328  
   329  	hashset, has := it.items[char]
   330  
   331  	if has {
   332  		return hashset.Length()
   333  	}
   334  
   335  	return 0
   336  }
   337  
   338  func (it *CharHashsetMap) Has(
   339  	str string,
   340  ) bool {
   341  	if it.IsEmpty() {
   342  		return false
   343  	}
   344  
   345  	char := it.
   346  		GetChar(str)
   347  
   348  	hashset, has := it.items[char]
   349  
   350  	if has {
   351  		return hashset.Has(str)
   352  	}
   353  
   354  	return false
   355  }
   356  
   357  func (it *CharHashsetMap) HasWithHashset(
   358  	str string,
   359  ) (bool, *Hashset) {
   360  	if it.IsEmpty() {
   361  		return false, New.Hashset.Empty()
   362  	}
   363  
   364  	char := it.
   365  		GetChar(str)
   366  
   367  	hashset, has := it.items[char]
   368  
   369  	if has {
   370  		return hashset.Has(str), hashset
   371  	}
   372  
   373  	return false, New.Hashset.Empty()
   374  }
   375  
   376  func (it *CharHashsetMap) HasWithHashsetLock(
   377  	str string,
   378  ) (bool, *Hashset) {
   379  	it.Lock()
   380  	defer it.Unlock()
   381  
   382  	if it.IsEmpty() {
   383  		return false, New.Hashset.Empty()
   384  	}
   385  
   386  	char := it.
   387  		GetChar(str)
   388  
   389  	hashset, has := it.items[char]
   390  
   391  	if has {
   392  		return hashset.HasLock(str), hashset
   393  	}
   394  
   395  	return false, New.Hashset.Empty()
   396  }
   397  
   398  func (it *CharHashsetMap) LengthOf(char byte) int {
   399  	if it.IsEmpty() {
   400  		return 0
   401  	}
   402  
   403  	hashset, has := it.items[char]
   404  
   405  	if has {
   406  		return hashset.Length()
   407  	}
   408  
   409  	return 0
   410  }
   411  
   412  func (it *CharHashsetMap) LengthOfLock(char byte) int {
   413  	it.Lock()
   414  	defer it.Unlock()
   415  
   416  	if it.IsEmpty() {
   417  		return 0
   418  	}
   419  
   420  	hashset, has := it.items[char]
   421  
   422  	if has {
   423  		return hashset.Length()
   424  	}
   425  
   426  	return 0
   427  }
   428  
   429  // AllLengthsSum All lengths sum.
   430  func (it *CharHashsetMap) AllLengthsSum() int {
   431  	if it.IsEmpty() {
   432  		return 0
   433  	}
   434  
   435  	allLengthsSum := 0
   436  
   437  	for _, hashset := range it.items {
   438  		allLengthsSum += hashset.Length()
   439  	}
   440  
   441  	return allLengthsSum
   442  }
   443  
   444  // AllLengthsSumLock All lengths sum.
   445  func (it *CharHashsetMap) AllLengthsSumLock() int {
   446  	it.Lock()
   447  	defer it.Unlock()
   448  
   449  	if it.IsEmpty() {
   450  		return 0
   451  	}
   452  
   453  	allLengthsSum := 0
   454  
   455  	for _, hashset := range it.items {
   456  		allLengthsSum += hashset.LengthLock()
   457  	}
   458  
   459  	return allLengthsSum
   460  }
   461  
   462  func (it *CharHashsetMap) AddCharCollectionMapItems(
   463  	charCollectionMap *CharCollectionMap,
   464  ) *CharHashsetMap {
   465  	if charCollectionMap == nil ||
   466  		charCollectionMap.IsEmpty() {
   467  		return it
   468  	}
   469  
   470  	it.AddStringsPtr(
   471  		charCollectionMap.List())
   472  
   473  	return it
   474  }
   475  
   476  func (it *CharHashsetMap) AddCollectionItems(
   477  	collectionWithDiffStarts *Collection,
   478  ) *CharHashsetMap {
   479  	if collectionWithDiffStarts == nil ||
   480  		collectionWithDiffStarts.IsEmpty() {
   481  		return it
   482  	}
   483  
   484  	it.AddStrings(
   485  		collectionWithDiffStarts.items...)
   486  
   487  	return it
   488  }
   489  
   490  func (it *CharHashsetMap) AddCollectionItemsAsyncLock(
   491  	collectionWithDiffStarts *Collection,
   492  	onComplete OnCompleteCharHashsetMap,
   493  ) *CharHashsetMap {
   494  	if collectionWithDiffStarts == nil ||
   495  		collectionWithDiffStarts.IsEmpty() {
   496  		return it
   497  	}
   498  
   499  	go it.AddStringsPtrAsyncLock(
   500  		&collectionWithDiffStarts.items,
   501  		onComplete)
   502  
   503  	return it
   504  }
   505  
   506  func (it *CharHashsetMap) Length() int {
   507  	if it.IsEmpty() {
   508  		return 0
   509  	}
   510  
   511  	return len(it.items)
   512  }
   513  
   514  func (it *CharHashsetMap) LengthLock() int {
   515  	it.Lock()
   516  	defer it.Unlock()
   517  
   518  	if it.IsEmpty() {
   519  		return 0
   520  	}
   521  
   522  	return len(it.items)
   523  }
   524  
   525  func (it *CharHashsetMap) IsEqualsPtrLock(
   526  	another *CharHashsetMap,
   527  ) bool {
   528  	it.Lock()
   529  	defer it.Unlock()
   530  
   531  	return it.IsEqualsPtr(
   532  		another)
   533  }
   534  
   535  func (it *CharHashsetMap) IsEqualsPtr(
   536  	another *CharHashsetMap,
   537  ) bool {
   538  	if another == nil {
   539  		return false
   540  	}
   541  
   542  	if another == it {
   543  		return true
   544  	}
   545  
   546  	if another.IsEmpty() && it.IsEmpty() {
   547  		return true
   548  	}
   549  
   550  	if another.IsEmpty() || it.IsEmpty() {
   551  		return false
   552  	}
   553  
   554  	if another.Length() != it.Length() {
   555  		return false
   556  	}
   557  
   558  	leftMap := it.items
   559  	rightMap := another.items
   560  
   561  	for key, hashset := range leftMap {
   562  		rHashset, has := rightMap[key]
   563  
   564  		if !has {
   565  			return false
   566  		}
   567  
   568  		if !rHashset.IsEqualsPtr(hashset) {
   569  			return false
   570  		}
   571  	}
   572  
   573  	return true
   574  }
   575  
   576  func (it *CharHashsetMap) AddLock(
   577  	str string,
   578  ) *CharHashsetMap {
   579  	char := it.GetChar(str)
   580  
   581  	it.Lock()
   582  	hashset, has := it.items[char]
   583  	it.Unlock()
   584  
   585  	if has {
   586  		hashset.AddLock(str)
   587  
   588  		return it
   589  	}
   590  
   591  	newHashset := New.Hashset.Cap(it.eachHashsetCapacity)
   592  	newHashset.Add(str)
   593  
   594  	it.Lock()
   595  	it.items[char] = newHashset
   596  	it.Unlock()
   597  
   598  	return it
   599  }
   600  
   601  func (it *CharHashsetMap) Add(
   602  	str string,
   603  ) *CharHashsetMap {
   604  	char := it.GetChar(str)
   605  
   606  	hashset, has := it.items[char]
   607  
   608  	if has {
   609  		hashset.Add(str)
   610  
   611  		return it
   612  	}
   613  
   614  	newHashset := New.Hashset.Cap(it.eachHashsetCapacity)
   615  	newHashset.Add(str)
   616  	it.items[char] = newHashset
   617  
   618  	return it
   619  }
   620  
   621  func (it *CharHashsetMap) AddStringPtr(
   622  	str *string,
   623  ) *CharHashsetMap {
   624  	char := it.GetCharOfPtr(str)
   625  
   626  	hashset, has := it.items[char]
   627  
   628  	if has {
   629  		hashset.AddPtr(str)
   630  
   631  		return it
   632  	}
   633  
   634  	newHashset := New.Hashset.Cap(it.eachHashsetCapacity)
   635  	newHashset.AddPtr(str)
   636  	it.items[char] = newHashset
   637  
   638  	return it
   639  }
   640  
   641  func (it *CharHashsetMap) AddStringPtrLock(
   642  	str *string,
   643  ) *CharHashsetMap {
   644  	defer it.Unlock()
   645  	char := it.GetCharOfPtr(str)
   646  
   647  	it.Lock()
   648  	hashset, has := it.items[char]
   649  	it.Unlock()
   650  
   651  	if has {
   652  		hashset.AddPtrLock(str)
   653  
   654  		return it
   655  	}
   656  
   657  	newHashset := New.Hashset.Cap(it.eachHashsetCapacity)
   658  	newHashset.AddPtr(str)
   659  
   660  	it.Lock()
   661  	it.items[char] = newHashset
   662  	it.Unlock()
   663  
   664  	return it
   665  }
   666  
   667  // AddSameStartingCharItems Assuming all items starts with same chars
   668  func (it *CharHashsetMap) AddSameStartingCharItems(
   669  	char byte,
   670  	allItemsWithSameChar *[]string,
   671  ) *CharHashsetMap {
   672  	if allItemsWithSameChar == nil ||
   673  		*allItemsWithSameChar == nil {
   674  		return it
   675  	}
   676  
   677  	length := len(*allItemsWithSameChar)
   678  
   679  	if length == 0 {
   680  		return it
   681  	}
   682  
   683  	values, has := it.items[char]
   684  
   685  	if has {
   686  		values.AddStringsPtr(allItemsWithSameChar)
   687  
   688  		return it
   689  	}
   690  
   691  	it.items[char] =
   692  		New.Hashset.StringsPtr(
   693  			allItemsWithSameChar)
   694  
   695  	return it
   696  }
   697  
   698  func (it *CharHashsetMap) AddPtrStringsLock(
   699  	simpleStrings *[]*string,
   700  ) *CharHashsetMap {
   701  	if simpleStrings == nil ||
   702  		*simpleStrings == nil ||
   703  		len(*simpleStrings) == 0 {
   704  		return it
   705  	}
   706  
   707  	for _, item := range *simpleStrings {
   708  		foundHashset := it.GetHashsetLock(
   709  			*item, true)
   710  
   711  		foundHashset.AddPtrLock(item)
   712  	}
   713  
   714  	return it
   715  }
   716  
   717  func (it *CharHashsetMap) AddStringsPtrAsyncLock(
   718  	largeStringsHashset *[]string,
   719  	onComplete OnCompleteCharHashsetMap,
   720  ) *CharHashsetMap {
   721  	if largeStringsHashset == nil ||
   722  		*largeStringsHashset == nil {
   723  		return it
   724  	}
   725  
   726  	length := len(*largeStringsHashset)
   727  
   728  	if length == 0 {
   729  		return it
   730  	}
   731  
   732  	isListIsTooLargeAndHasExistingData :=
   733  		length > RegularCollectionEfficiencyLimit &&
   734  			it.Length() > DoubleLimit
   735  
   736  	if isListIsTooLargeAndHasExistingData {
   737  		return it.
   738  			efficientAddOfLargeItems(
   739  				largeStringsHashset,
   740  				onComplete)
   741  	}
   742  
   743  	wg := &sync.WaitGroup{}
   744  	wg.Add(length)
   745  
   746  	for _, item := range *largeStringsHashset {
   747  		foundHashset := it.GetHashsetLock(
   748  			item,
   749  			true)
   750  
   751  		go foundHashset.AddWithWgLock(
   752  			item,
   753  			wg,
   754  		)
   755  	}
   756  
   757  	wg.Wait()
   758  
   759  	if onComplete != nil {
   760  		onComplete(it)
   761  	}
   762  
   763  	return it
   764  }
   765  
   766  func (it *CharHashsetMap) efficientAddOfLargeItems(
   767  	largeStringsHashset *[]string,
   768  	onComplete OnCompleteCharHashsetMap,
   769  ) *CharHashsetMap {
   770  	allCharsMap := it.
   771  		GetCharsPtrGroups(largeStringsHashset)
   772  
   773  	wg := &sync.WaitGroup{}
   774  	wg.Add(allCharsMap.Length())
   775  
   776  	for key, hashset := range allCharsMap.items {
   777  		foundHashset := it.GetHashsetLock(
   778  			string(key),
   779  			true)
   780  
   781  		go foundHashset.AddHashsetWgLock(
   782  			hashset,
   783  			wg,
   784  		)
   785  	}
   786  
   787  	wg.Wait()
   788  
   789  	if onComplete != nil {
   790  		onComplete(it)
   791  	}
   792  
   793  	return it
   794  }
   795  
   796  func (it *CharHashsetMap) AddStringsPtr(
   797  	items *[]string,
   798  ) *CharHashsetMap {
   799  	if items == nil ||
   800  		*items == nil ||
   801  		len(*items) == 0 {
   802  		return it
   803  	}
   804  
   805  	for _, item := range *items {
   806  		it.AddStringPtr(&item)
   807  	}
   808  
   809  	return it
   810  }
   811  
   812  func (it *CharHashsetMap) AddStrings(
   813  	items ...string,
   814  ) *CharHashsetMap {
   815  	if items == nil ||
   816  		len(items) == 0 {
   817  		return it
   818  	}
   819  
   820  	for _, item := range items {
   821  		it.AddStringPtr(&item)
   822  	}
   823  
   824  	return it
   825  }
   826  
   827  func (it *CharHashsetMap) GetHashset(
   828  	strFirstChar string,
   829  	isAddNewOnEmpty bool,
   830  ) *Hashset {
   831  	char := it.GetChar(strFirstChar)
   832  
   833  	hashset, has := it.items[char]
   834  
   835  	if has {
   836  		return hashset
   837  	}
   838  
   839  	if isAddNewOnEmpty {
   840  		newHashset := New.Hashset.Cap(it.eachHashsetCapacity)
   841  		it.items[char] = newHashset
   842  
   843  		return newHashset
   844  	}
   845  
   846  	return nil
   847  }
   848  
   849  func (it *CharHashsetMap) GetHashsetLock(
   850  	strFirstChar string,
   851  	isAddNewOnEmpty bool,
   852  ) *Hashset {
   853  	it.Lock()
   854  	defer it.Unlock()
   855  
   856  	return it.GetHashset(
   857  		strFirstChar,
   858  		isAddNewOnEmpty)
   859  }
   860  
   861  func (it *CharHashsetMap) AddSameCharsCollection(
   862  	str string,
   863  	stringsWithSameStartChar *Collection,
   864  ) *Hashset {
   865  	isNilOrEmptyHashsetGiven := stringsWithSameStartChar == nil ||
   866  		stringsWithSameStartChar.IsEmpty()
   867  
   868  	foundHashset := it.GetHashset(
   869  		str,
   870  		false)
   871  
   872  	has := foundHashset != nil
   873  	isAddToHashset := has && !isNilOrEmptyHashsetGiven
   874  	hasHashsetHoweverNothingToAdd := has && isNilOrEmptyHashsetGiven
   875  
   876  	if isAddToHashset {
   877  		foundHashset.AddCollection(stringsWithSameStartChar)
   878  
   879  		return foundHashset
   880  	} else if hasHashsetHoweverNothingToAdd {
   881  		return foundHashset
   882  	}
   883  
   884  	char := it.GetChar(str)
   885  
   886  	if isNilOrEmptyHashsetGiven {
   887  		// create new
   888  		newHashset := New.Hashset.Cap(
   889  			it.eachHashsetCapacity)
   890  		it.items[char] = newHashset
   891  
   892  		return newHashset
   893  	}
   894  
   895  	// items exist or stringsWithSameStartChar exists
   896  	//goland:noinspection GoNilness
   897  	toHashset := stringsWithSameStartChar.HashsetAsIs()
   898  	it.items[char] = toHashset
   899  
   900  	return toHashset
   901  }
   902  
   903  func (it *CharHashsetMap) AddSameCharsHashset(
   904  	str string,
   905  	stringsWithSameStartChar *Hashset,
   906  ) *Hashset {
   907  	isNilOrEmptyHashsetGiven := stringsWithSameStartChar == nil ||
   908  		stringsWithSameStartChar.IsEmpty()
   909  
   910  	foundHashset := it.GetHashset(
   911  		str,
   912  		false)
   913  
   914  	has := foundHashset != nil
   915  	isAddToHashset := has && !isNilOrEmptyHashsetGiven
   916  	hasHashsetHoweverNothingToAdd := has && isNilOrEmptyHashsetGiven
   917  
   918  	if isAddToHashset {
   919  		foundHashset.AddHashsetItems(stringsWithSameStartChar)
   920  
   921  		return foundHashset
   922  	} else if hasHashsetHoweverNothingToAdd {
   923  		return foundHashset
   924  	}
   925  
   926  	char := it.GetChar(str)
   927  
   928  	if isNilOrEmptyHashsetGiven {
   929  		// create new
   930  		newHashset := New.Hashset.Cap(
   931  			it.eachHashsetCapacity)
   932  		it.items[char] = newHashset
   933  
   934  		return newHashset
   935  	}
   936  
   937  	// items exist or stringsWithSameStartChar exists
   938  	it.items[char] =
   939  		stringsWithSameStartChar
   940  
   941  	return stringsWithSameStartChar
   942  }
   943  
   944  func (it *CharHashsetMap) AddHashsetItems(
   945  	hashsetWithDiffStarts *Hashset,
   946  ) *CharHashsetMap {
   947  	if hashsetWithDiffStarts == nil ||
   948  		hashsetWithDiffStarts.IsEmpty() {
   949  		return it
   950  	}
   951  
   952  	it.AddStringsPtr(
   953  		hashsetWithDiffStarts.ListPtr())
   954  
   955  	return it
   956  }
   957  
   958  func (it *CharHashsetMap) AddHashsetItemsAsyncLock(
   959  	hashsetWithDiffStarts *Hashset,
   960  	onComplete OnCompleteCharHashsetMap,
   961  ) *CharHashsetMap {
   962  	if hashsetWithDiffStarts == nil ||
   963  		hashsetWithDiffStarts.IsEmpty() {
   964  		return it
   965  	}
   966  
   967  	go it.AddStringsPtrAsyncLock(
   968  		hashsetWithDiffStarts.ListCopyPtrLock(),
   969  		onComplete)
   970  
   971  	return it
   972  }
   973  
   974  func (it *CharHashsetMap) AddSameCharsCollectionLock(
   975  	str string,
   976  	stringsWithSameStartChar *Collection,
   977  ) *Hashset {
   978  	isNilOrEmptyHashsetGiven := stringsWithSameStartChar == nil ||
   979  		stringsWithSameStartChar.IsEmpty()
   980  
   981  	foundHashset := it.GetHashsetLock(
   982  		str,
   983  		false)
   984  	has := foundHashset != nil
   985  	isAddToHashset := has &&
   986  		!isNilOrEmptyHashsetGiven
   987  	hasHashsetHoweverNothingToAdd := has &&
   988  		isNilOrEmptyHashsetGiven
   989  
   990  	if isAddToHashset {
   991  		list := stringsWithSameStartChar.
   992  			ListCopyPtrLock()
   993  
   994  		foundHashset.
   995  			AddStringsPtrLock(&list)
   996  
   997  		return foundHashset
   998  	} else if hasHashsetHoweverNothingToAdd {
   999  		return foundHashset
  1000  	}
  1001  
  1002  	char := it.GetChar(str)
  1003  
  1004  	if isNilOrEmptyHashsetGiven {
  1005  		// create new
  1006  		newHashset := New.Hashset.Cap(
  1007  			it.eachHashsetCapacity)
  1008  		it.Lock()
  1009  		it.items[char] = newHashset
  1010  		it.Unlock()
  1011  
  1012  		return newHashset
  1013  	}
  1014  
  1015  	// items exist or stringsWithSameStartChar exists
  1016  	//goland:noinspection GoNilness
  1017  	hashset := stringsWithSameStartChar.HashsetAsIs()
  1018  	//goland:noinspection GoLinterLocal
  1019  	it.Lock()
  1020  	it.items[char] =
  1021  		hashset
  1022  	it.Unlock()
  1023  
  1024  	return hashset
  1025  }
  1026  
  1027  func (it *CharHashsetMap) AddHashsetLock(
  1028  	str string,
  1029  	stringsWithSameStartChar *Hashset,
  1030  ) *Hashset {
  1031  	isNilOrEmptyHashsetGiven := stringsWithSameStartChar == nil ||
  1032  		stringsWithSameStartChar.IsEmpty()
  1033  
  1034  	foundHashset := it.GetHashsetLock(
  1035  		str,
  1036  		false)
  1037  	has := foundHashset != nil
  1038  	isAddToHashset := has && !isNilOrEmptyHashsetGiven
  1039  	hasHashsetHoweverNothingToAdd := has && isNilOrEmptyHashsetGiven
  1040  
  1041  	if isAddToHashset {
  1042  		//goland:noinspection GoNilness
  1043  		foundHashset.AddStringsPtrLock(
  1044  			stringsWithSameStartChar.ListPtr())
  1045  
  1046  		return foundHashset
  1047  	} else if hasHashsetHoweverNothingToAdd {
  1048  		return foundHashset
  1049  	}
  1050  
  1051  	// current str char, no lock required
  1052  	char := it.GetChar(str)
  1053  
  1054  	if isNilOrEmptyHashsetGiven {
  1055  		// create new
  1056  		newHashset := New.Hashset.Cap(
  1057  			it.eachHashsetCapacity)
  1058  		it.Lock()
  1059  		it.items[char] = newHashset
  1060  		it.Unlock()
  1061  
  1062  		return newHashset
  1063  	}
  1064  
  1065  	// items exist or stringsWithSameStartChar exists
  1066  	it.Lock()
  1067  	it.items[char] =
  1068  		stringsWithSameStartChar
  1069  	it.Unlock()
  1070  
  1071  	return stringsWithSameStartChar
  1072  }
  1073  
  1074  func (it *CharHashsetMap) GetHashsetByChar(
  1075  	char byte,
  1076  ) *Hashset {
  1077  	return it.items[char]
  1078  }
  1079  
  1080  func (it *CharHashsetMap) HashsetByChar(
  1081  	char byte,
  1082  ) *Hashset {
  1083  	hashset := it.items[char]
  1084  
  1085  	return hashset
  1086  }
  1087  
  1088  func (it *CharHashsetMap) HashsetByCharLock(
  1089  	char byte,
  1090  ) *Hashset {
  1091  	it.Lock()
  1092  	hashset := it.items[char]
  1093  	it.Unlock()
  1094  
  1095  	if hashset == nil {
  1096  		return New.Hashset.Empty()
  1097  	}
  1098  
  1099  	return hashset
  1100  }
  1101  
  1102  func (it *CharHashsetMap) HashsetByStringFirstChar(
  1103  	str string,
  1104  ) *Hashset {
  1105  	char := it.GetChar(str)
  1106  
  1107  	return it.HashsetByChar(char)
  1108  }
  1109  
  1110  func (it *CharHashsetMap) HashsetByStringFirstCharLock(
  1111  	str string,
  1112  ) *Hashset {
  1113  	char := it.GetChar(str)
  1114  
  1115  	return it.HashsetByCharLock(char)
  1116  }
  1117  
  1118  func (it *CharHashsetMap) JsonModel() *CharHashsetDataModel {
  1119  	return &CharHashsetDataModel{
  1120  		Items: it.items,
  1121  		EachHashsetCapacity: it.
  1122  			eachHashsetCapacity,
  1123  	}
  1124  }
  1125  
  1126  func (it *CharHashsetMap) JsonModelAny() interface{} {
  1127  	return it.JsonModel()
  1128  }
  1129  
  1130  func (it *CharHashsetMap) AsJsonContractsBinder() corejson.JsonContractsBinder {
  1131  	return it
  1132  }
  1133  
  1134  func (it *CharHashsetMap) AsJsoner() corejson.Jsoner {
  1135  	return it
  1136  }
  1137  
  1138  func (it *CharHashsetMap) AsJsonMarshaller() corejson.JsonMarshaller {
  1139  	return it
  1140  }
  1141  
  1142  func (it *CharHashsetMap) AsJsonParseSelfInjector() corejson.JsonParseSelfInjector {
  1143  	return it
  1144  }
  1145  
  1146  func (it *CharHashsetMap) JsonParseSelfInject(
  1147  	jsonResult *corejson.Result,
  1148  ) error {
  1149  	_, err := it.ParseInjectUsingJson(
  1150  		jsonResult,
  1151  	)
  1152  
  1153  	return err
  1154  }
  1155  
  1156  func (it *CharHashsetMap) ParseInjectUsingJson(
  1157  	jsonResult *corejson.Result,
  1158  ) (*CharHashsetMap, error) {
  1159  	err := jsonResult.Unmarshal(it)
  1160  
  1161  	if err != nil {
  1162  		return Empty.CharHashsetMap(), err
  1163  	}
  1164  
  1165  	return it, nil
  1166  }
  1167  
  1168  // ParseInjectUsingJsonMust Panic if error
  1169  func (it *CharHashsetMap) ParseInjectUsingJsonMust(
  1170  	jsonResult *corejson.Result,
  1171  ) *CharHashsetMap {
  1172  	newUsingJson, err :=
  1173  		it.ParseInjectUsingJson(jsonResult)
  1174  
  1175  	if err != nil {
  1176  		panic(err)
  1177  	}
  1178  
  1179  	return newUsingJson
  1180  }
  1181  
  1182  func (it *CharHashsetMap) MarshalJSON() ([]byte, error) {
  1183  	return json.Marshal(*it.JsonModel())
  1184  }
  1185  
  1186  func (it *CharHashsetMap) UnmarshalJSON(data []byte) error {
  1187  	var dataModel CharHashsetDataModel
  1188  
  1189  	err := json.Unmarshal(data, &dataModel)
  1190  
  1191  	if err == nil {
  1192  		it.items = dataModel.Items
  1193  		it.eachHashsetCapacity =
  1194  			dataModel.EachHashsetCapacity
  1195  	}
  1196  
  1197  	return err
  1198  }
  1199  
  1200  func (it CharHashsetMap) Json() corejson.Result {
  1201  	return corejson.New(it)
  1202  }
  1203  
  1204  func (it CharHashsetMap) JsonPtr() *corejson.Result {
  1205  	return corejson.NewPtr(it)
  1206  }
  1207  
  1208  // RemoveAll remove all existing items, deletes items using delete(*charCollectionMap.items, char), expensive operation
  1209  func (it *CharHashsetMap) RemoveAll() *CharHashsetMap {
  1210  	if it.IsEmpty() {
  1211  		return it
  1212  	}
  1213  
  1214  	return it.Clear()
  1215  }
  1216  
  1217  // Clear points to a new map and collects old pointer and remove all elements from pointer in separate goroutine.
  1218  func (it *CharHashsetMap) Clear() *CharHashsetMap {
  1219  	if it.IsEmpty() {
  1220  		return it
  1221  	}
  1222  
  1223  	tempCollection := it.items
  1224  	it.items = nil
  1225  	it.items = make(map[byte]*Hashset, 0)
  1226  
  1227  	go func() {
  1228  		for char, values := range tempCollection {
  1229  			values.Dispose()
  1230  			values = nil
  1231  
  1232  			delete(tempCollection, char)
  1233  		}
  1234  	}()
  1235  
  1236  	return it
  1237  }