第47项:Stream要优先用Collection作为返回类型

在Java API设计中,选择返回类型是Stream、Iterable还是Collection很重要。Stream虽好,但用户可能需要for-each迭代。Collection是这两者的折衷,提供了stream方法。返回序列的方法应考虑使用者可能想进行流处理或迭代。除非有特殊理由,否则公共API推荐返回Collection,因为它同时支持流和迭代。对于大型或无限序列,避免返回Collection,因为它的size方法受限。
摘要由CSDN通过智能技术生成

  许多方法返回元素序列。 在Java 8之前,这些方法的明显返回类型是集合接口Collection,Set和List;Iterable; 和数组类型。通常,很容易决定返回哪些类型。准确来说是一个集合接口。如果该方法仅用于启用for-each循环或返回的序列无法实现某些Collection方法(通常为contains(Object)),则使用Iterable接口。如果返回的元素是基本类型值或者存在严格的性能要求,则使用数组。在Java 8中,流被添加到平台中,这使得为返回序列的方法选择恰当的返回类型的任务变得非常复杂。

  你可能听说过,流现在是返回一系列元素的公认选择,正如第45项所描述的,流不会使迭代过时:编写好的代码需要适当地组合流和迭代。如果API只返回一个流,而某些用户想要使用for-each循环迭代返回的序列,那么这些用户理所当然会感到不安。特别令人沮丧的是,Stream接口包含Iterable接口中唯一的抽象方法,Stream的此方法规范与Iterable兼容。

  可悲的是,这个问题没有好的解决方法。乍一看,似乎可以将方法引用传递给Stream的迭代器方法。 结果代码可能有点嘈杂和模糊,但并非不合理:

// Won't compile, due to limitations on Java's type inference
for (ProcessHandle ph : ProcessHandle.allProcesses()::iterator) {
   
    // Process the process
}

  不幸的是,如果你尝试编译此代码,你将收到一条错误消息:

Test.java:6: error: method reference not expected here
for (ProcessHandle ph : ProcessHandle.allProcesses()::iterator) {
   
                        ^

  为了使代码编译,你必须将方法引用强制转换为适合参数化的Iterable:

// Hideous workaround to iterate over a stream
for (ProcessHandle ph : (Iterable<ProcessHandle>) ProcessHandle.allProcesses()::iterator)

  此客户端代码有效,但在实践中使用它太嘈杂和模糊。更好的解决方法是使用适配器方法。JDK没有提供这样的方法,但是使用上面的代码片段中使用的相同技术,可以很容易地编写一个方法。请注意,在适配器方法中不需要强制转换,因为Java类型推断在此上下文中正常工作:

// Adapter from Stream<E> to Iterable<E>
public static <E> Iterable<E> iterableOf(Stream<E> stream) {
   
    return stream::iterator;
}

  使用此适配器,你可以使用for-each语句迭代任何流:

for (ProcessHandle p : iterableOf(ProcessHandle.allProcesses())) {
   
    // Process the process
}

  请注意,第34项中的Anagrams程序的流版本使用Files.lines方法读取字典,而迭代版本使用scanner。Files.lines方法优于scanner,它可以在读取文件时悄悄地处理(silently swallows)任何异常。理想情况下,我们也会在迭代版本中使用Files.lines。如果API仅提供对序列的流访问并且他们希望使用for-each语句迭代序列,那么程序员将会做出这种折中的方法【在迭代版本中使用Files.lines】。

  相反,想要使用流管道处理序列的程序员理所当然会因为API仅提供Iterable而感到难过【傲娇】。再提一次JDK没有提供适配器,但编写一个是很容易的:

// Adapter from Iterable<E> to Stream<E>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值