单次迭代=>从Java到Scala的多个输出集合
我目前正在尝试将一些Java代码转换为Scala代码。挑战在于确保转换后的Scala代码与原来的Java代码相比不会做效率非常低的事情。例如,当尝试转换以下代码时:
class Person {
String name;
Integer age;
Character gender;
}
public class TestJava {
public static void main(String[] args) {
final List<Person> persons = new ArrayList<>();
final List<Person> males = new ArrayList<>();
final List<Person> aNames = new ArrayList<>();
final List<Person> seniors = new ArrayList<>();
for (final Person p: persons) {
if (p.gender == 'm') {
males.add(p);
}
if (p.age >= 60) {
seniors.add(p);
}
if (p.name.startsWith("a")) {
aNames.add(p);
}
}
}
}
因为Java依赖于变异,所以这段代码看起来是合乎逻辑的但是,现在我想将其转换为Scala等价物,而不在集合上循环多次(在本例中为3次)
当然,我可以使用Scala库中的可变List
,并实现与Java相同的功能,但我想知道是否有可能从给定的序列/集合中以函数/Scala方式生成多个集合,而无需对集合进行n
次迭代,其中n
是标准计数。提前谢谢
# 1 楼答案
另一个使用foldLeft的示例,但可能更容易阅读
# 2 楼答案
(List[Person]元组让这看起来很难看,您可能需要为结果定义一个类型别名。)
# 3 楼答案
此解决方案不是纯粹的功能性解决方案,而是更直接的解决方案。在许多情况下,可变集合(如ListBuffer)工作得更好,只要确保不将可变状态泄漏到函数或类之外即可。可读性的好处将使纯度的损失变得值得
# 4 楼答案
对我来说,最惯用的方法是使用
Factory
和Builder
模式,尽管它需要一些样板代码。有些库,如cats或shapeless可能会对您有所帮助,但我对它们并不精通你可以写:
如果您定义了所有这些样板文件:
# 5 楼答案
一种纯粹的功能性和不可变的方法是使用一个通用函数,通过谓词将集合分隔为多个存储桶:
然后,示例用法可以是:
# 6 楼答案
这是相当务实的。对人员列表进行模式匹配,检查每个递归调用中的条件,并根据需要添加到结果中,直到列表用尽。结果是
List
的Person
被填充到Tuple
中测试