在Java 8中,有 Stream.collect 允许集合上的聚合。在Kotlin中,这不以同样的方式存在,除了可能作为stdlib中的扩展函数的集合。但是不清楚不同用例的等效性。
例如,在 Collectors 的JavaDoc顶部是为Java 8编写的示例,当将它们移植到Kolin时,不能使用Java 8类在不同的JDK版本上,所以可能应该写成不同的。
在资源在线显示Kotlin集合的例子,他们通常是微不足道的,并不真正比较相同的用例。什么是很好的例子,真正匹配的案例,如记录为Java 8 Stream.collect ?列表中有:
- 将名称累积到列表中
- 将名称累积到TreeSet
- 将元素转换为字符串并用逗号分隔
- 计算员工的工资总额
- 按部门计算工资总额
- 将学生分成通过和失败
有关上述链接的JavaDoc的详细信息。
注意: >这个问题是由作者故意写和回答的(自我回答的问题),以便常用的Kotlin主题的惯用答案出现在SO中。还要澄清一些为Kotlin的alphas写的,对当前Kotlin不准确的老的答案。
Kotlin stdlib中有用于平均,计数,不同,过滤,查找,分组,连接,映射,最小, ,切片,排序,求和,到/从数组,到/从列表,到/从映射,联合,协同,所有的功能范例等等。所以你可以使用它们来创建一个简单的1-liners,并且没有必要使用更复杂的Java 8语法。
我认为唯一缺少的来自内置的Java 8 Collectors 类是摘要(但在另一个答案这个问题是一个简单的解决方案)。
两者之间缺少的一件事是按计数进行批量处理,这在另一个Stack Overflow answer ,并有一个简单的答案。另一个有趣的情况是这也是从Stack Overflow:惯用语使用Kotlin将溢出序列分成三个列表。如果您想要创建 Stream.collect 以实现其他目的,请参阅自定义流。收集在Kotlin
总是好的探索用于kotlin.collections的API参考作为一个整体,然后创建可能已经存在的新函数。
这里是一些从Java 8 Stream.collect 到Kotlin中的等价类型的转换:
将名称累加到列表中
// Java:
List< String> list = people.stream()。map(Person :: getName).collect(Collectors.toList());
// Kotlin:
val list = people .map {it.name} // toList()不需要
并连接起来,并以逗号分隔
// Java:
String join = things.stream()
.map(Object :: toString)
.collect(Collectors.joining(“,”));
// Kotlin:
val joined = things .joinToString(“,”)
计算员工工资总额 / p>
// Java:
int total = employees.stream()
.collect(Collectors.summingInt(Employee :: getSalary)));
// Kotlin:
val total = .sumBy {it.salary}
按部门分组员工
// Java:
Map< Department,List< Employee> byDept
= employees.stream()
.collect(Collectors.groupingBy(Employee :: getDepartment));
// Kotlin:
val byDept = employees .groupBy {it.department}
按部门计算工资总和 / p>
// Java:
Map< Department,Integer> totalByDept
= employees.stream()
.collect(Collectors.groupingBy(Employee :: getDepartment,
Collectors.summingInt(Employee :: getSalary)));
// Kotlin:
val totalByDept = employees .groupBy {it.dept} .mapValues {it.value.sumBy {it.salary}}
将学生分成传递和失败
// Java:
Map< Boolean,List< Student>> passedFailing =
students.stream()
.collect(Collectors.partitioningBy(s - > s.getGrade()> = PASS_THRESHOLD));
// Kotlin:
val passingFailing = students .partition {it.grade> = PASS_THRESHOLD}
男性成员姓名
// Java:
List< String> namesOfMaleMembersCollect = roster
.stream()
.filter(p - > p.getGender()== Person.Sex.MALE)
.map(p - > p.getName ))
.collect(Collectors.toList());
// Kotlin:
val namesOfMaleMembers = roster .filter {it.gender == Person.Sex.MALE} .map {it.name}
按性别列在成员名单中的成员名称
Map< Person.Sex,List< String>> namesByGender =
roster.stream()。collect(
Collectors.groupingBy(
Person :: getGender,
Collectors.mapping(
Person :: getName,
Collectors.toList())));
// Kotlin:
val namesByGender = roster .groupBy {it.gender} .mapValues {it.value.map {it.name}}
将列表过滤到另一个列表
// Java:
List< String> filtered = items.stream()
.filter(item - > item.startsWith(“o”))
.collect(Collectors.toList
// Kotlin:
val filtered = items .filter {item.startsWith('o')}
/ strong>
// Java:
String shortest = items.stream
.min(Comparator.comparing(item - > item.length()))
.get();
// Kotlin:
val short = items .minBy {it.length}
在应用过滤器后对列表中的项目进行计数
// Java:
long count = items.stream filter(item - > item.startsWith(“t”))。count();
// Kotlin:
val count = items .filter {it.startsWith('t')} .size
//但最好不要过滤,但是使用谓词
val count = items.count {it.startsWith('t') }
并在它上...在所有情况下,没有特殊的折叠,缩小或其他功能需要模仿 Stream.collect 。如果您有其他用例,请在评论中添加它们,我们可以看到!
关于懒惰
想要延迟处理链,可以在链之前使用 asSequence()转换为序列。在函数链的末尾,通常最后还有一个 Sequence 。然后可以使用 toList(), toSet(), toMap c $ c>或一些其他函数来实现 Sequence 结束。
//切换到和从lazy
val someList = items.asSequence()。filter {...} .take(10).map {...} .toList()
//切换到lazy,但sorted()在最后再次出现
val someList = items.asSequence()。filter {...} .take(10).map {... } .sorted()
为什么没有Types?!?
你会注意到Kotlin的例子没有指定类型。这是因为Kotlin具有完整的类型推断,并且在编译时是完全类型安全的。比Java更多,因为它也有可空类型,可以帮助防止可怕的NPE。所以这在Kotlin:
val someList = people.filter {it.age< = 30} .map {it.name }
与以下相同:
val someList:List< String> = people.filter {it.age< = 30} .map {it.name}
Kotlin知道人是什么, people.age 是 Int 因此过滤器表达式只允许与 Int 进行比较, people.name 是 String ,因此 map 步骤产生一个 List< String> (readonly <$现在,如果<$ c>
$ c>人可能 null ,因为在列表<人>?那么:
val someList = people?.filter {it.age< = 30}?map {it.name}
返回 List< String>?将需要为null选中(或使用其他Kotlin运算符作为可空值,请参阅此 Kotlin处理可空值的常用方法以及在Kotlin中处理可空或空列表的惯用方法 )