kotlin

问 题
 

在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中处理可空或空列表的惯用方法 

原文地址:https://www.cnblogs.com/vana/p/10201245.html