Kotlin higher order functions working with containers

原文: Higher Order Functions Woking With Containers

Kotlin标准库中提供了一些高级函数:average(求平均值), count(计算元素个数), distinct(求取唯一结果), filtering(条件过滤), finding(查找), grouping(分组), joining(连接), mapping(映射), min(最小值), max(最大值), partitioning(分区), slicing(切片), sorting(排序), summing, to/from arrays(数组转换), to/from lists(链表转换), to/from maps(Map转换), union, co-iteration等等,让我们更方便更简洁的用小小的一行代码就可以完成Java8里面复杂语法才能实现的功能。

在你想写一个新函数之前全面的浏览一下kotlin.collections的API,它里面已经实现了太多的功能,没准就能找到你需要的。

下面是Java 8Stream.collectkotlin中代码的一个对照:

##Accumulate names into a List(抽取names到一个单独的链表)

1
2
// Java:  
List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());
1
2
// Kotlin:
val list = people.map { it.name } // toList() not needed

##Convert elements to strings and concatenate them, separated by commas

1
2
3
4
// Java:
String joined = things.stream()
.map(Object::toString)
.collect(Collectors.joining(", "));
1
2
// Kotlin:
val joined = things.joinToString(", ")

##Compute sum of salaries of employee

1
2
3
// Java:
int total = employees.stream()
.collect(Collectors.summingInt(Employee::getSalary)));
1
2
// Kotlin:
val total = employees.sumBy { it.salary }

##Group employees by department

1
2
3
4
// Java:
Map<Department, List<Employee>> byDept
= employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
1
2
// Kotlin:
val byDept = employees.groupBy { it.department }

##Compute sum of salaries by department

1
2
3
4
5
// Java:
Map<Department, Integer> totalByDept
= employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
Collectors.summingInt(Employee::getSalary)));
1
2
// Kotlin:
val totalByDept = employees.groupBy { it.dept }.mapValues { it.value.sumBy { it.salary }}

##Partition students into passing and failing

1
2
3
4
// Java:
Map<Boolean, List<Student>> passingFailing =
students.stream()
.collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
1
2
// Kotlin:
val passingFailing = students.partition { it.grade >= PASS_THRESHOLD }

##Names of male members

1
2
3
4
5
6
// Java:
List<String> namesOfMaleMembersCollect = roster
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.map(p -> p.getName())
.collect(Collectors.toList());
1
2
// Kotlin:
val namesOfMaleMembers = roster.filter { it.gender == Person.Sex.MALE }.map { it.name }

##Group names of members in roster by gender

1
2
3
4
5
6
7
8
// Java:
Map<Person.Sex, List<String>> namesByGender =
roster.stream().collect(
Collectors.groupingBy(
Person::getGender,
Collectors.mapping(
Person::getName,
Collectors.toList())));
1
2
// Kotlin:
val namesByGender = roster.groupBy { it.gender }.mapValues { it.value.map { it.name } }

##Filter a list to another list

1
2
3
4
// Java:
List<String> filtered = items.stream()
.filter( item -> item.startsWith("o") )
.collect(Collectors.toList());
1
2
// Kotlin:
val filtered = items.filter { item.startsWith('o') }

##Finding shortest string a list

1
2
3
4
// Java:
String shortest = items.stream()
.min(Comparator.comparing(item -> item.length()))
.get();
1
2
// Kotlin:
val shortest = items.minBy { it.length }

##Counting items in a list after filter is applied

1
2
// Java:
long count = items.stream().filter( item -> item.startsWith("t")).count();
1
2
3
4
// Kotlin:
val count = items.filter { it.startsWith('t') }.size
// but better to not filter, but count with a predicate
val count = items.count { it.startsWith('t') }