使用Java8流对列表的第一个元素执行特定操作

13

我想在我的列表的第一个元素上执行某些操作,并对所有剩余元素执行不同的操作。

以下是我的代码片段:

List<String> tokens = getDummyList();
if (!tokens.isEmpty()) {
    System.out.println("this is first token:" + tokens.get(0));
}
tokens.stream().skip(1).forEach(token -> {
    System.out.println(token);
});

有没有更加清晰的方式来实现这个,最好是使用Java 8的流式API。


我认为你的方法已经很干净简洁了 :) - TheLostMind
1
为了防止空指针异常(NPE),我会检查tokens是否为null - TheLostMind
是的,那只是虚拟代码,用来解释问题。我想知道是否有一种方法可以在流调用中合并if条件,并减少更多的行数。 - vatsal mevada
1
@vatsalmevada 不。 - Louis Wasserman
2个回答

11

表达意图的一种方式是

Spliterator<String> sp = getDummyList().spliterator();
if(sp.tryAdvance(token -> System.out.println("this is first token: "+token))) {
    StreamSupport.stream(sp, false).forEach(System.out::println);
}

该方法可与任意 Collection 一起使用,不仅限于 List,并且在链接更高级的 Stream 操作时可能比基于 skip 的解决方案更有效率。此模式也适用于 Stream 源,即在无法进行多次遍历或可能产生两个不同结果时。

Spliterator<String> sp=getDummyList().stream().filter(s -> !s.isEmpty()).spliterator();
if(sp.tryAdvance(token -> System.out.println("this is first non-empty token: "+token))) {
    StreamSupport.stream(sp, false).map(String::toUpperCase).forEach(System.out::println);
}

然而,对第一个元素的特殊处理可能仍然会导致性能损失,与处理所有流元素相比。

如果你只想执行像forEach这样的操作,你也可以使用一个Iterator

Iterator<String> tokens = getDummyList().iterator();
if(tokens.hasNext())
    System.out.println("this is first token:" + tokens.next());
tokens.forEachRemaining(System.out::println);

1
迭代器应该是我认为可接受的解决方案。+1 - Eugene

8

这样做会更加简洁

    items.stream().limit(1).forEach(v -> System.out.println("first: "+ v));
    items.stream().skip(1).forEach(System.out::println);

那个或者findFirst() - Nick Vanderhoven
2
尝试在相同的流上进行操作会抛出IllegalStateException: stream has already been operated upon or closed异常。 - Bohemian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接