Scala按类型过滤集合并保留目标类型的最优方法对比
在Scala中按类型过滤集合的最佳实践
嘿,这个问题问到点子上了!在Scala里过滤集合并保留目标类型,确实有几种写法,咱们来拆解你给出的两种方案,再聊聊更地道的最佳实践。
首先看你给出的两种实现:
1. 自定义Typed提取器的写法
val list = List(1,"two",3,"four") object Typed { def unapply[A](a: A) = Some(a) } val list1 = for { Typed(i: Int) <- list } yield i
这个写法利用了提取器(Extractor)的特性,通过Typed对象的unapply方法把每个元素“拆包”,再通过模式匹配筛选出Int类型的元素。好处是for推导式的语法看起来比较直观,但缺点也很明显:需要额外定义一个无意义的Typed辅助对象,属于没必要的冗余代码——毕竟Scala本身就有更简洁的方式实现同样的效果。
2. flatMap + 模式匹配的写法
val list2 = list.flatMap { case i: Int => List(i) case _ => Nil }
这种写法就清爽多了:利用flatMap的特性,匹配到Int类型的元素就返回包含它的单元素列表,否则返回空列表Nil,最终所有符合条件的元素会被扁平成一个List[Int]。这个方案不需要额外定义任何对象,完全依赖标准库方法,逻辑清晰,代码也不算冗长。如果只能在你给出的两种里选,这个肯定是更优的。
更推荐的最佳实践:使用collect方法
其实Scala标准库专门为这种“过滤+类型转换/提取”的场景提供了collect方法,这才是最地道、最简洁的写法:
val list3 = list.collect { case i: Int => i }
collect方法接收一个偏函数(Partial Function),它会自动过滤掉那些不匹配偏函数的元素,同时把匹配的元素按照偏函数的逻辑转换(这里就是直接返回i),最终返回的集合类型就是目标类型List[Int]。
为什么collect是最佳选择?
- 代码最简洁:一行搞定,没有多余的逻辑或辅助对象
- 语义最明确:
collect的名字本身就传达了“收集符合条件的元素”的意图,可读性拉满 - 类型安全:编译器会自动推导返回的集合类型,不需要手动指定
- 性能高效:和
flatMap一样,都是一次遍历完成操作,没有额外开销
总结
- 如果只能在你给出的两种方案中选择,flatMap的写法更优,避免了冗余的辅助对象定义
- 但更推荐直接使用标准库的
collect方法,这是Scala处理此类场景的标准做法,也是业界公认的最佳实践
内容的提问来源于stack exchange,提问作者frhack
相关产品推荐
相关产品推荐

