collect 看似简单,实际上是个泛型方法,返回什么类型全靠推断。这篇验证它什么时候报错、能收集成哪些类型、收集成 Result 时何时停止、同一份数据在不同类型里语义怎么变,以及 size_hint 如何影响 Vec 的预分配。
源码:
1 | fn main() {
2 | let v = (1..4).map(|x| x * 2).collect();
3 | println!("{:?}", v);
4 | }
编译:失败
error[E0283]: type annotations needed
--> <实验目录>/src/u64a.rs:2:9
|
2 | let v = (1..4).map(|x| x * 2).collect();
| ^ ------- type must be known at this point
|
= note: the type must implement `FromIterator<i32>`
note: required by a bound in `collect`
--> <rust 标准库源码>/library/core/src/iter/traits/iterator.rs:2077:19
|
2077 | fn collect<B: FromIterator<Self::Item>>(self) -> B
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
help: consider giving `v` an explicit type
|
2 | let v: Vec<_> = (1..4).map(|x| x * 2).collect();
| ++++++++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0283`.
编译:成功
运行(退出码 0):
标注变量类型 [1, 2, 3] / turbofish [1, 2, 3] / turbofish+占位符 [1, 4, 9] / 靠函数返回类型 [2, 4, 6]
HashMap(排序后显示): [("a", 1), ("bb", 2), ("ccc", 3)]
BTreeSet<char>: {'e', 'h', 'l', 'o'}
String 可以从 char / &str / String 收集: rust rust ab
Box<[i32]>: [1, 2, 3]
partition: [2, 4, 6] [1, 3, 5]
unzip: [1, 2] ['a', 'b']
collect 成 (): Ok(()) 编译:成功
运行(退出码 0):
Result<Vec<_>,_>: Err(ParseIntError { kind: InvalidDigit }) 闭包只被调用了 3 次(共 5 个元素)
全部成功: Some([1, 2, 3]) 调用 3 次
Option 的 sum: None / Some(4) 编译:成功
运行(退出码 0):
Vec 保留 3 个: [("a", 1), ("b", 2), ("a", 3)]
BTreeMap 重复键后者覆盖前者,剩 2 个: {"a": 3, "b": 2}
HashSet 只取键,剩 2 个
HashMap 里 a = 3HashMap 与 BTreeMap 的区别见BTreeMap 与 HashMap 对比。
编译:成功
运行(退出码 0):
map: alloc 1 realloc 0 size_hint (10000, Some(10000)) len 10000 cap 10000
filter: alloc 1 realloc 11 size_hint (0, Some(10000)) len 5000 cap 8192
filter+map: alloc 1 realloc 11 len 5000 cap 8192Vec 的扩容规则见Vec 扩容机制。