Java Stream:有没有一种方法可以一次迭代两个元素而不是一个?

假设我们有这个流

Stream.of("a", "b", "err1", "c", "d", "err2", "e", "f", "g", "h", "err3", "i", "j");

我想在地图中保存几对相邻的字符串,其中第一个以“ err”开头。

我想到的就是这样

Map<String, String> map = new HashMap<>();

Stream.of("a", "b", "err1", "c", "d", "err2", "e", "f", "g", "h", "err3", "i", "j")

.reduce((acc, next) -> {

if (acc.startsWith("err"))

map.put(acc,next);

if (next.startsWith("err"))

return next;

else

return "";

});

但是我对它并不完全满意,主要有两个原因

  1. 我在“滥用” reduce功能。在Stream API中,每个函数都有其明确的定义明确的目的:max应该计算最大值,filter应该根据条件进行过滤,reduce应该产生递增的累加值,依此类推。
  2. 这样做会使我无法使用Streams强大的机制:如果我想将搜索范围限制在前两个结果中,该怎么办?

在这里,我reduce之所以使用它,是因为(据我所知),它是唯一使您可以比较几个值的函数,以某种方式,它们可以返回类似于“当前值”和“下一个值”的概念。

有没有更直接的方法?是什么让您可以在每次迭代中考虑多个值来迭代流?

编辑

我正在考虑的是某种机制,在给定当前元素的情况下,您可以为每次迭代定义要考虑的“元素窗口”。

就像是

<R> Stream<R> mapMoreThanOne(

int elementsBeforeCurrent,

int elementsAfterCurrent,

Function<List<? super T>, ? extends R> mapper);

代替

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

那将是对当前API的强大“升级”。

编辑2

我感谢人们提出他们的解决方案所付出的努力,但问题本身不是算法。通过将流,索引,临时变量放在一起以存储先前的值来实现我的目标,有多种方法…但是我想知道Stream

API中是否有某种方法专门用于处理当前元素以外的任务而不破坏“流范式”。像这样

List<String> list =

Stream.of("a", "b", "err1", "c", "d", "err2", "e", "f", "g", "h", "err3", "i", "j")

.filterFunctionImWonderingIfExist(/*filters couples of elements*/)

.limit(2)

.collect(Collectors.toList());

有了答案,我认为除非使用StreamEx库,否则没有“清晰快捷”的解决方案

回答:

您可以Collector为此任务建立自定义。

Map<String, String> map = 

Stream.of("a", "b", "err1", "c", "d", "err2", "e", "f", "g", "h", "err3", "i", "j")

.collect(MappingErrors.collector());

与:

private static final class MappingErrors {

private Map<String, String> map = new HashMap<>();

private String first, second;

public void accept(String str) {

first = second;

second = str;

if (first != null && first.startsWith("err")) {

map.put(first, second);

}

}

public MappingErrors combine(MappingErrors other) {

throw new UnsupportedOperationException("Parallel Stream not supported");

}

public Map<String, String> finish() {

return map;

}

public static Collector<String, ?, Map<String, String>> collector() {

return Collector.of(MappingErrors::new, MappingErrors::accept, MappingErrors::combine, MappingErrors::finish);

}

}

在此收集器中,保留了两个运行元素。每次String接受a时,它们都会更新,如果第一个以开头"err",则会将这两个元素添加到地图中。


另一个解决方案是使用StreamEx库,该库提供一种pairMap将给定功能应用于此流的每个相邻元素对的方法。在下面的代码中,如果第一个元素以开头"err"null则该操作将返回一个由该对的第一个和第二个元素组成的String数组。null然后将元素过滤掉,并将Stream收集到地图中。

Map<String, String> map = 

StreamEx.of("a", "b", "err1", "c", "d", "err2", "e", "f", "g", "h", "err3", "i", "j")

.pairMap((s1, s2) -> s1.startsWith("err") ? new String[] { s1, s2 } : null)

.nonNull()

.toMap(a -> a[0], a -> a[1]);

System.out.println(map);

以上是 Java Stream:有没有一种方法可以一次迭代两个元素而不是一个? 的全部内容, 来源链接: utcz.com/qa/418373.html

回到顶部