我正在尝试将一些
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库中的可变列表,并且实现与Java完成的相同的事情,但是想知道是否可以以功能/ Scala方式从给定的序列/集合生成多个集合,而不会迭代n的集合时间,其中n是标准计数.提前致谢!
解决方法
一个纯粹的功能和不可变的方式是具有通过谓词将集合分成存储桶的通用功能:
case class Person(name: String,age: Int,gender: String) def bucketsByPredicate(people: Seq[Person],predicates: Seq[Person => Boolean]) = { people.foldLeft(predicates.map(predicate => (predicate,List.empty[Person]) )) { case (predicates,person) => predicates.map { case (predicate,members) => (predicate,if(predicate(person)) person :: members else members) } }.map(_._2) }
那么一个例子可以是:
val olderThan60 = (p: Person) => p.age >= 60 val male = (p: Person) => p.gender == "m" val Seq(olderThan60People,malePeople) = bucketsByPredicate(people,Seq(olderThan60,male))