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 }