[英]How do I deal with Scala collections generically?
I have realized that my typical way of passing Scala collections around could use some improvement. 我已经意识到我传递Scala集合的典型方式可以使用一些改进。
def doSomethingCool(theFoos: List[Foo]) = { /* insert cool stuff here */ }
// if I happen to have a List
doSomethingCool(theFoos)
// but elsewhere I may have a Vector, Set, Option, ...
doSomethingCool(theFoos.toList)
I tend to write my library functions to take a List
as the parameter type, but I'm certain that there's something more general I can put there to avoid all the occasional .toList
calls I have in the application code. 我倾向于编写我的库函数来将
List
作为参数类型,但我确信有一些更通用的东西我可以放在那里以避免我在应用程序代码中偶尔的.toList
调用。 This is especially annoying since my doSomethingCool
function typically only needs to call map
, flatMap
and filter
, which are defined on all the collection types. 这尤其令人讨厌,因为我的
doSomethingCool
函数通常只需要调用map
, flatMap
和filter
,它们都是在所有集合类型上定义的。
What are my options for that 'something more general'? 对于那种“更普遍的东西”,我有哪些选择?
Here are more general traits, each of which extends the previous one: 以下是更一般的特征,每个特征都扩展了前一个特征:
GenTraversableOnce
GenTraversable
GenIterable
GenSeq
The traits above do not specify whether the collection is sequential or parallel. 上述特征未指定集合是顺序还是并行。 If your code requires that things be executed sequentially (typically, if your code has side effects of any kind), they are too general for it.
如果您的代码要求按顺序执行某些操作(通常,如果您的代码具有任何类型的副作用),则它们过于笼统。
The following traits mandate sequential execution: 以下特征要求顺序执行:
TraversableOnce
Traversable
Iterable
Seq
LinearSeq
The first one, TraversableOnce
only allows you to call one method on the collection. 第一个,
TraversableOnce
只允许您在集合上调用一个方法。 After that, the collection has been "used". 之后,该集合已被“使用”。 In exchange, it is general enough to accept iterators as well as collections.
作为交换,它通常足以接受迭代器和集合。
Traversable
is a pretty general collection that has most methods. Traversable
是一个非常通用的集合,拥有大多数方法。 There are some things it cannot do, however, in which case you need to go to Iterable
. 但有些事情是不能做的,在这种情况下你需要去
Iterable
。
All Iterable
implement the iterator
method, which allows you to get an Iterator
for that collection. 所有
Iterable
实现了iterator
方法,它允许您获取该集合的Iterator
。 This gives it the capability for a few methods not present in Traversable
. 这使它能够使用
Traversable
不存在的一些方法。
A Seq[A]
implements the function Int => A
, which means you can access any element by its index. Seq[A]
实现函数Int => A
,这意味着您可以通过索引访问任何元素。 This is not guaranteed to be efficient, but it is a guarantee that each element has an index, and that you can make assertions about what that index is going to be. 这不能保证有效,但它保证每个元素都有一个索引,并且您可以对该索引的内容进行断言。 Contrast this with
Map
and Set
, where you cannot tell what the index of an element is. 将其与
Map
和Set
对比,您无法分辨元素的索引。
A LinearSeq
is a Seq
that provides fast head
, tail
, isEmpty
and prepend. LinearSeq
是一个提供快速head
, tail
, isEmpty
和prepend的Seq
。 This is as close as you can get to a List
without actually using a List
explicitly. 这是尽可能接近
List
而不实际明确使用List
。
Alternatively, you could have an IndexedSeq
, which has fast indexed access (something List
does not provide). 或者,您可以拥有一个
IndexedSeq
,它具有快速索引访问权限( List
不提供)。
See also this question and this FAQ based on it. 另请参阅此问题以及基于此的常见问题解答 。
The most obvious one is to use Traversable
as the most general trait which will have the goodies you want. 其中最明显的是使用
Traversable
作为,这将有你想要的东西最一般的特质。 However, I think you are generally better sticking to: 但是,我认为你通常更好地坚持:
Seq
IndexedSeq
Set
Map
A Seq
will cover List
, Vector
etc, IndexedSeq
will cover Vector
etc etc. I found myself not using Iterable
because I often need (or want) to know the size of the thing I have and back pre scala-2.8 Iterable
did not provide access to this , so I kept having to turn things into sequences anyway! Seq
将覆盖List
, Vector
等, IndexedSeq
将覆盖Vector
等等。我发现自己不使用Iterable
因为我经常需要(或想要)知道我拥有的东西的大小并且返回预scala-2.8 Iterable
没有提供访问权限对此 ,所以我总是不得不把事情变成序列!
Looks like Traversable
and Iterable
now have size
methods so maybe I should go back to using them! 看起来像
Traversable
和Iterable
现在有size
方法,所以也许我应该回去使用它们! Of course you could start "going mad" with GenTraversableOnce
but that is not likely to aid in readability. 当然,您可以使用
GenTraversableOnce
开始“疯狂”,但这不太可能有助于提高可读性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.