GO如何模拟流操作实现示例探究
作者:小雷学编程 Jacksonlei
前言
本篇主要是做一个记录,希望对您有用
首先,你可能看到过类似的JAVA 代码如下 :
return Optional.ofNullable(list).flatMap(list -> list.stream()
.filter(Objects::nonNull)
.filter(i -> stockCode.equals(i.id()))
.map(this::mathod)
.findFirst())
.orElse(null);时间有限我们今天尝试着模拟一下部分方法,感受一下。
集合
首先我们需要一个集合如下:
var okgoarch = List{
"arm",
"arm64",
"loong64",
"mips64",
"mips64le",
"ppc64",
"riscv64",
"sparc64",
}过滤的方法
接下来我们需要尝试写一个过滤的方法这个方法应该要接受一个方法,并且这个方法的需要接受的类型应该是一个泛型类型,返回值是BOOL ,然后我们对集合的每个元素都操作,所以大概样子就出来:
func (ls List) Filter(fk Predicate[string]) List {
if fk == nil {
return nil
}
var res List
for _, nod := range ls {
if fk(nod) {
res = append(res, nod)
}
}
return res
}
type Predicate[P any] func(n P) bool可能有心细的朋友已经发现了 List 这个类,是我自己定义的,要是别的类型呢?往下看
type List []string
定个接口来处理通用类型
LIST 实际上就是我定义的类似,为了方便使用,这里有个问题,我如果定义的是别的类型是不是就不管用了,所以我们需要定个接口来处理通用类型,所以接口就出来了:
type Stream[T any] interface {
Filter(pre Predicate[T]) bool
}但是又有一个问题,如果别的类型实现的方法可能返回不是BOOL 怎么办,那么接口就长成下面这样,虽然不太可能为了实现拓展我还是愿意这么做,如下:
type Stream[T, OUT any] interface {
Filter(pre Predicate[T]) OUT
}测试对字符串切片过滤的逻辑
到这里一个简单的对字符串切片过滤的逻辑就完成了,我们测试一下:
var okgoarch = List{
"arm",
"arm64",
"loong64",
"mips64",
"mips64le",
"ppc64",
"riscv64",
"sparc64",
}
lss := okgoarch.
Filter(func(n string) bool { return n == "sparc64" || n == "mips64le" })
fmt.Printf("%+v\n", lss)
//[mips64le sparc64]貌似还算成功过,接下来我尝试实现一个稍微复杂点的方法。
stream.map(()->{}) 等操作
定义一个方法结构
我们都知道MAP的流操作方法需要接受一个方法类型作为入参,GO函数式编程很好的解决了这个问题,首先我们需要先定义一个方法结构,它大概长这样:
type Function[F any, OUT any] func(n F) OUT
这里定义方法入参和出参都是泛型类型,我暂且认为MAP操作就是对集合的每个元素都进行一个方法操作,那么它的方法可能长这样:
func (ls List) Map(fk Function[string, string]) List {
if fk == nil {
return nil
}
var res List
for _, nod := range ls {
res = append(res, fk(nod))
}
return res
}完整接口
同样,如果是通用类型需要一个接口支持,不然切片可以用MAP,其他类型却不行,所以接口我们加一个定义,完整接口如下:
type Stream[T, F2, OUT any] interface {</code><code> Filter(pre Predicate[T]) OUT</code><code> Map(function Function[T, F2]) OUT</code><code>}按照上面同样的方法我定义了Sorted 方法和 字符串Joins方法,如下 :
type Stream[T, F2, OUT any] interface {
Filter(pre Predicate[T]) OUT
Map(function Function[T, F2]) OUT
}同样也要加上接口哦,字符串切片排序比较简单。到这里字符串切片的方法就定义完了
测试一下
ls := okgoarch.
Filter(func(n string) bool { return n == "sparc64" || n == "mips64le" }).
Map(strings.ToTitle).
Sorted(). //按照ascii码表排序
joins(":")
fmt.Printf("%+v\n",
[arm arm64 loong64 mips64 mips64le ppc64 riscv64 sparc64]
ls)字符串切片可以,是否别的类型也可以
我尝试用了一个结构体切片来说明同样的思路我直接贴代码了:
type Person struct {
Name string
Age int
}
type ByAgeNameCompare []Person
func (a ByAgeNameCompare) Len() int { return len(a) }
func (a ByAgeNameCompare) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAgeNameCompare) Less(i, j int) bool {
if a[i].Age == a[j].Age {
return a[i].Name < a[j].Name //DESC
}
return a[i].Age < a[j].Age //ASC
}
type Persons []Person
func (ls Persons) Sorted() Persons {
sort.Sort(ByAgeNameCompare(ls))
return ls
}
func (ls Persons) Filter(fk Predicate[Person]) Persons {
if fk == nil {
return nil
}
var res Persons
for _, nod := range ls {
if fk(nod) {
res = append(res, nod)
}
}
return res
}
func (ls Persons) Map(fk Function[Person, any]) any {
if fk == nil {
return nil
}
var res []any
for _, nod := range ls {
res = append(res, fk(nod))
}
return res
}
func (ls Persons) Map1(fk Function[Person, Person]) Persons {
if fk == nil {
return nil
}
var res Persons
for _, nod := range ls {
res = append(res, fk(nod))
}
return res
}以上代码是结构体切片类型的实现,结构体类型可以自己定义,例如JAVA某个子类型的stream 流接口的实现一样
完整代码
type Predicate[P any] func(n P) bool
type Function[F any, OUT any] func(n F) OUT
type List []string
type Stream[T, F2, OUT any] interface {
Filter(pre Predicate[T]) OUT
Map(function Function[T, F2]) OUT
Sorted() OUT
}
func (ls List) Filter(fk Predicate[string]) List {
if fk == nil {
return nil
}
var res List
for _, nod := range ls {
if fk(nod) {
res = append(res, nod)
}
}
return res
}
func (ls List) Map(fk Function[string, string]) List {
if fk == nil {
return nil
}
var res List
for _, nod := range ls {
res = append(res, fk(nod))
}
return res
}
func (ls List) joins(delim string) string {
return strings.Join(ls, delim)
}
func (ls List) Sorted() List {
sort.Strings(ls)
return ls
}
type Person struct {
Name string
Age int
}
type ByAgeNameCompare []Person
func (a ByAgeNameCompare) Len() int { return len(a) }
func (a ByAgeNameCompare) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAgeNameCompare) Less(i, j int) bool {
if a[i].Age == a[j].Age {
return a[i].Name < a[j].Name //DESC
}
return a[i].Age < a[j].Age //ASC
}
type Persons []Person
func (ls Persons) Sorted() Persons {
sort.Sort(ByAgeNameCompare(ls))
return ls
}
func (ls Persons) Filter(fk Predicate[Person]) Persons {
if fk == nil {
return nil
}
var res Persons
for _, nod := range ls {
if fk(nod) {
res = append(res, nod)
}
}
return res
}
func (ls Persons) Map(fk Function[Person, any]) any {
if fk == nil {
return nil
}
var res []any
for _, nod := range ls {
res = append(res, fk(nod))
}
return res
}
func (ls Persons) Map1(fk Function[Person, Person]) Persons {
if fk == nil {
return nil
}
var res Persons
for _, nod := range ls {
res = append(res, fk(nod))
}
return res
}
func main() {
var okgoarch = List{
"arm",
"arm64",
"loong64",
"mips64",
"mips64le",
"ppc64",
"riscv64",
"sparc64",
}
lss := okgoarch.
Filter(func(n string) bool { return n == "sparc64" || n == "mips64le" })
fmt.Printf("%+v\n", lss)
fmt.Printf("%+v\n", okgoarch)
ls := okgoarch.
Filter(func(n string) bool { return n == "sparc64" || n == "mips64le" }).
Map(strings.ToTitle).
Sorted(). //按照ascii码表排序
joins(":")
fmt.Printf("%+v\n", ls)
peoples := Persons{
{"Alice", 30},
{"Bob", 25},
{"Charlie", 35},
{"Dark", 75},
}
psvar := peoples.
Filter(func(n Person) bool { return n.Name != "Charlie" }).
Map(func(n Person) any {
return n.Name
})
fmt.Printf("%+v\n", psvar)
psvar1 := peoples.
Filter(func(n Person) bool { return n.Name != "Charlie" }).
Map1(func(n Person) Person {
n.Name = n.Name + "pick"
return n
}).Sorted()
fmt.Printf("%+v", psvar1)
}
[mips64le sparc64]
[arm arm64 loong64 mips64 mips64le ppc64 riscv64 sparc64]
MIPS64LE:SPARC64
[Alice Bob Dark]
[{Name:Bobpick Age:25} {Name:Alicepick Age:30} {Name:Darkpick Age:75}]以上就是GO如何模拟流操作实现示例探究的详细内容,更多关于GO模拟流操作的资料请关注脚本之家其它相关文章!
