github.com/searKing/golang/go@v1.2.74/container/stream/reference_pipeline.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 stream
     6  
     7  import (
     8  	"context"
     9  	"sort"
    10  	"strconv"
    11  	"sync"
    12  
    13  	"github.com/searKing/golang/go/container/stream/op/find"
    14  	"github.com/searKing/golang/go/container/stream/op/match"
    15  	"github.com/searKing/golang/go/container/stream/op/reduce"
    16  	"github.com/searKing/golang/go/container/stream/op/terminal"
    17  	"github.com/searKing/golang/go/error/exception"
    18  	"github.com/searKing/golang/go/util"
    19  	"github.com/searKing/golang/go/util/function/binary"
    20  	"github.com/searKing/golang/go/util/function/consumer"
    21  	"github.com/searKing/golang/go/util/function/predicate"
    22  	"github.com/searKing/golang/go/util/object"
    23  	"github.com/searKing/golang/go/util/optional"
    24  	"github.com/searKing/golang/go/util/spliterator"
    25  )
    26  
    27  type ReferencePipeline struct {
    28  	upstreams []interface{}
    29  
    30  	terminal.AbstractPipeline
    31  }
    32  
    33  func New(upstreams ...interface{}) *ReferencePipeline {
    34  	pipe := &ReferencePipeline{
    35  		upstreams: upstreams,
    36  	}
    37  	pipe.SetDerived(pipe)
    38  	return pipe
    39  }
    40  
    41  func (r *ReferencePipeline) Filter(ctx context.Context, predicate predicate.Predicater) *ReferencePipeline {
    42  	object.RequireNonNil(predicate)
    43  	var sFiltered []interface{}
    44  	for _, u := range r.upstreams {
    45  		select {
    46  		case <-ctx.Done():
    47  			return &ReferencePipeline{}
    48  		default:
    49  		}
    50  		if predicate.Test(u) {
    51  			sFiltered = append(sFiltered, u)
    52  		}
    53  	}
    54  	return New(sFiltered...)
    55  }
    56  
    57  func (r *ReferencePipeline) Map(ctx context.Context, mapper func(interface{}) interface{}) *ReferencePipeline {
    58  	object.RequireNonNil(mapper)
    59  	var sMapped []interface{}
    60  	for _, u := range r.upstreams {
    61  		select {
    62  		case <-ctx.Done():
    63  			return &ReferencePipeline{}
    64  		default:
    65  		}
    66  		sMapped = append(sMapped, mapper(u))
    67  	}
    68  	return New(sMapped...)
    69  }
    70  
    71  func (r *ReferencePipeline) Distinct(ctx context.Context, distincter func(interface{}, interface{}) int) *ReferencePipeline {
    72  	object.RequireNonNil(distincter)
    73  
    74  	sDistinctMap := map[interface{}]struct{}{}
    75  	var sDistinct []interface{}
    76  	for _, u := range r.upstreams {
    77  		select {
    78  		case <-ctx.Done():
    79  			return &ReferencePipeline{}
    80  		default:
    81  		}
    82  		if uu, ok := sDistinctMap[u]; ok {
    83  			if distincter(uu, u) == 0 {
    84  				continue
    85  			}
    86  		}
    87  		sDistinctMap[u] = struct{}{}
    88  		sDistinct = append(sDistinct, u)
    89  	}
    90  	return New(sDistinct...)
    91  }
    92  
    93  func (r *ReferencePipeline) Sorted(lesser func(interface{}, interface{}) int) *ReferencePipeline {
    94  	object.RequireNonNil(lesser)
    95  	sSorted := make([]interface{}, len(r.upstreams))
    96  	copy(sSorted, r.upstreams)
    97  
    98  	less := func(i, j int) bool {
    99  		if lesser(sSorted[i], sSorted[j]) < 0 {
   100  			return true
   101  		}
   102  		return false
   103  	}
   104  	sort.Slice(sSorted, less)
   105  	return New(sSorted...)
   106  
   107  }
   108  
   109  func (r *ReferencePipeline) Peek(ctx context.Context, action consumer.Consumer) *ReferencePipeline {
   110  	object.RequireNonNil(action)
   111  
   112  	for _, u := range r.upstreams {
   113  		select {
   114  		case <-ctx.Done():
   115  			return &ReferencePipeline{}
   116  		default:
   117  		}
   118  		action.Accept(u)
   119  	}
   120  	return r
   121  }
   122  
   123  func (r *ReferencePipeline) Limit(maxSize int) *ReferencePipeline {
   124  	if maxSize < 0 {
   125  		panic(exception.NewIllegalArgumentException1(strconv.Itoa(maxSize)))
   126  	}
   127  	m := len(r.upstreams)
   128  	if m > maxSize {
   129  		m = maxSize
   130  	}
   131  	return &ReferencePipeline{upstreams: r.upstreams[:m]}
   132  }
   133  
   134  func (r *ReferencePipeline) Skip(n int) *ReferencePipeline {
   135  	if n < 0 {
   136  		panic(exception.NewIllegalArgumentException1(strconv.Itoa(n)))
   137  	}
   138  	if n == 0 {
   139  		return r
   140  	}
   141  	m := len(r.upstreams)
   142  	if n > m {
   143  		n = m
   144  	}
   145  	return &ReferencePipeline{upstreams: r.upstreams[n:]}
   146  }
   147  
   148  func (r *ReferencePipeline) TakeWhile(ctx context.Context, predicate predicate.Predicater) *ReferencePipeline {
   149  	object.RequireNonNil(predicate)
   150  
   151  	var sTaken []interface{}
   152  	for _, u := range r.upstreams {
   153  		select {
   154  		case <-ctx.Done():
   155  			return &ReferencePipeline{}
   156  		default:
   157  		}
   158  		if predicate.Test(u) {
   159  			sTaken = append(sTaken, u)
   160  			continue
   161  		}
   162  		break
   163  	}
   164  	return &ReferencePipeline{upstreams: sTaken}
   165  }
   166  
   167  func (r *ReferencePipeline) TakeUntil(ctx context.Context, predicate predicate.Predicater) *ReferencePipeline {
   168  	object.RequireNonNil(predicate)
   169  
   170  	return r.TakeWhile(ctx, predicate.Negate())
   171  }
   172  
   173  func (r *ReferencePipeline) DropWhile(ctx context.Context, predicate predicate.Predicater) *ReferencePipeline {
   174  	object.RequireNonNil(predicate)
   175  
   176  	var sTaken []interface{}
   177  	for _, u := range r.upstreams {
   178  		select {
   179  		case <-ctx.Done():
   180  			return &ReferencePipeline{}
   181  		default:
   182  		}
   183  		if predicate.Test(u) {
   184  			continue
   185  		}
   186  		sTaken = append(sTaken, r)
   187  	}
   188  	return &ReferencePipeline{upstreams: sTaken}
   189  }
   190  
   191  func (r *ReferencePipeline) DropUntil(ctx context.Context, predicate predicate.Predicater) *ReferencePipeline {
   192  	object.RequireNonNil(predicate)
   193  
   194  	return r.DropWhile(ctx, predicate.Negate())
   195  }
   196  
   197  func (r *ReferencePipeline) ForEach(ctx context.Context, action consumer.Consumer) {
   198  	object.RequireNonNil(action)
   199  
   200  	var wg sync.WaitGroup
   201  	for _, u := range r.upstreams {
   202  		select {
   203  		case <-ctx.Done():
   204  			return
   205  		default:
   206  		}
   207  		wg.Add(1)
   208  		go func(uu interface{}) {
   209  			defer wg.Done()
   210  			action.Accept(uu)
   211  		}(u)
   212  	}
   213  	wg.Wait()
   214  }
   215  
   216  func (r *ReferencePipeline) ForEachOrdered(ctx context.Context, action consumer.Consumer) {
   217  	object.RequireNonNil(action)
   218  
   219  	for _, u := range r.upstreams {
   220  		select {
   221  		case <-ctx.Done():
   222  			return
   223  		default:
   224  		}
   225  		action.Accept(u)
   226  	}
   227  }
   228  
   229  func (r *ReferencePipeline) ToSlice(generator func(interface{}) interface{}) []interface{} {
   230  	if generator == nil {
   231  		return r.upstreams
   232  	}
   233  
   234  	downstream := make([]interface{}, len(r.upstreams))
   235  
   236  	for _, u := range r.upstreams {
   237  		downstream = append(downstream, generator(u))
   238  	}
   239  	return downstream
   240  }
   241  
   242  func (r *ReferencePipeline) Reduce(ctx context.Context,
   243  	accumulator binary.BiFunction, combiner binary.BiFunction,
   244  	identity ...interface{}) optional.Optional {
   245  	split := spliterator.NewSliceSpliterator2(spliterator.CharacteristicTODO, append(identity, r.upstreams...))
   246  	return r.Evaluate(ctx, reduce.NewReduceOp3(optional.Empty(), accumulator, combiner), split)
   247  }
   248  
   249  func (r *ReferencePipeline) Max(ctx context.Context, comparator util.Comparator) optional.Optional {
   250  	return r.Reduce(ctx, binary.MaxBy(comparator), nil)
   251  }
   252  
   253  func (r *ReferencePipeline) Min(ctx context.Context, comparator util.Comparator) optional.Optional {
   254  	return r.Reduce(ctx, binary.MinBy(comparator), nil)
   255  }
   256  
   257  func (r *ReferencePipeline) Count(ctx context.Context, comparator util.Comparator) int {
   258  	return len(r.upstreams)
   259  }
   260  
   261  func (r *ReferencePipeline) AnyMatch(ctx context.Context, predicate predicate.Predicater) bool {
   262  	split := spliterator.NewSliceSpliterator2(spliterator.CharacteristicTODO, r.upstreams...)
   263  	return r.Evaluate(ctx, match.NewMatchOp2(match.KindAny, predicate), split).IsPresent()
   264  }
   265  
   266  func (r *ReferencePipeline) AllMatch(ctx context.Context, predicate predicate.Predicater) bool {
   267  	split := spliterator.NewSliceSpliterator2(spliterator.CharacteristicTODO, r.upstreams...)
   268  	return r.Evaluate(ctx, match.NewMatchOp2(match.KindAll, predicate), split).IsPresent()
   269  }
   270  
   271  func (r *ReferencePipeline) NoneMatch(ctx context.Context, predicate predicate.Predicater) bool {
   272  	split := spliterator.NewSliceSpliterator2(spliterator.CharacteristicTODO, r.upstreams...)
   273  	return r.Evaluate(ctx, match.NewMatchOp2(match.KindNone, predicate), split).IsPresent()
   274  }
   275  
   276  func (r *ReferencePipeline) FindFirst(ctx context.Context, predicate predicate.Predicater) optional.Optional {
   277  	split := spliterator.NewSliceSpliterator2(spliterator.CharacteristicTODO, r.upstreams...)
   278  
   279  	return r.Evaluate(ctx, find.NewFindOp2(true, predicate), split)
   280  }
   281  
   282  func (r *ReferencePipeline) FindAny(ctx context.Context, predicate predicate.Predicater) optional.Optional {
   283  	split := spliterator.NewSliceSpliterator2(spliterator.CharacteristicTODO, r.upstreams...)
   284  
   285  	return r.Evaluate(ctx, find.NewFindOp2(false, predicate), split)
   286  }
   287  
   288  func (r *ReferencePipeline) Close() error {
   289  	return nil
   290  }