github.com/searKing/golang/go@v1.2.74/container/slice/findanyindex.go (about)

     1  // Copyright 2020 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package slice
     6  
     7  import (
     8  	"sync"
     9  
    10  	"github.com/searKing/golang/go/util/object"
    11  )
    12  
    13  // FindAnyFunc returns an {@link interface{}} describing some element of the stream, or an
    14  // empty {@code Optional} if the stream is empty.
    15  func FindAnyIndexFunc(s interface{}, f func(interface{}) bool) int {
    16  	return findAnyIndexFunc(Of(s), f, true)
    17  }
    18  
    19  // findAnyFunc is the same as FindAnyFunc.
    20  func findAnyIndexFunc(s []interface{}, f func(interface{}) bool, truth bool) int {
    21  	object.RequireNonNil(s, "findAnyIndexFunc called on nil slice")
    22  	object.RequireNonNil(f, "findAnyIndexFunc called on nil callfn")
    23  	var findc chan int
    24  	findc = make(chan int)
    25  	defer close(findc)
    26  	var mu sync.Mutex
    27  	var wg sync.WaitGroup
    28  	var found bool
    29  	hasFound := func() bool {
    30  		mu.Lock()
    31  		defer mu.Unlock()
    32  		return found
    33  	}
    34  	for idx, r := range s {
    35  		if hasFound() {
    36  			break
    37  		}
    38  
    39  		wg.Add(1)
    40  		go func(rr interface{}) {
    41  			defer wg.Done()
    42  			foundYet := func() bool {
    43  				mu.Lock()
    44  				defer mu.Unlock()
    45  				return found
    46  			}()
    47  			if foundYet {
    48  				return
    49  			}
    50  			if f(rr) == truth {
    51  				mu.Lock()
    52  				defer mu.Unlock()
    53  				if found {
    54  					return
    55  				}
    56  				found = true
    57  				findc <- idx
    58  				return
    59  			}
    60  		}(r)
    61  	}
    62  	go func() {
    63  		defer close(findc)
    64  		wg.Done()
    65  	}()
    66  	out, ok := <-findc
    67  	if ok {
    68  		return out
    69  	}
    70  	return -1
    71  }