相关疑难解决方法(0)

为什么Java Streams一次性关闭?

与C#不同IEnumerable,执行管道可以根据需要执行多次,在Java中,流只能"迭代"一次.

对终端操作的任何调用都会关闭流,使其无法使用.这个"功能"消耗了很多力量.

我想这个的原因不是技术性的.这个奇怪限制背后的设计考虑是什么?

编辑:为了演示我在说什么,请考虑以下C#中的Quick-Sort实现:

IEnumerable<int> QuickSort(IEnumerable<int> ints)
{
  if (!ints.Any()) {
    return Enumerable.Empty<int>();
  }

  int pivot = ints.First();

  IEnumerable<int> lt = ints.Where(i => i < pivot);
  IEnumerable<int> gt = ints.Where(i => i > pivot);

  return QuickSort(lt).Concat(new int[] { pivot }).Concat(QuickSort(gt));
}
Run Code Online (Sandbox Code Playgroud)

现在可以肯定的是,我并不是说这是一个很好的快速排序!然而,它是lambda表达式与流操作相结合的表达能力的一个很好的例子.

它不能用Java完成!我甚至无法询问流是否为空而不使其无法使用.

java api-design java-8 java-stream

231
推荐指数
4
解决办法
4万
查看次数

有没有办法重用一个流?

我正在学习新的Java 8功能,在尝试使用streams(java.util.stream.Stream)和收集器时,我意识到流不能使用两次.

有没有办法重复使用它?

java reusability java-stream

59
推荐指数
5
解决办法
3万
查看次数

制作流副本的最有效方法是什么?

我有一个方法,在流上执行处理.部分处理需要在一个锁的控制下完成 - 一个锁定部分用于处理所有元素 - 但其中一部分没有(并且不应该因为它可能非常耗时).所以我不能只说:

Stream<V> preprocessed = Stream.of(objects).map(this::preProcess);
Stream<V> toPostProcess;
synchronized (lockObj) {
    toPostProcess = preprocessed.map(this::doLockedProcessing);
}
toPostProcess.map(this::postProcess).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

因为调用doLockedProcessing只会在forEach调用终端操作时执行,并且在锁定之外.

所以我认为我需要在每个阶段使用终端操作制作流的副本,以便在正确的时间完成正确的位.就像是:

Stream<V> preprocessed = Stream.of(objects).map(this::preProcess).copy();
Stream<V> toPostProcess;
synchronized (lockObj) {
    toPostProcess = preprocessed.map(this::doLockedProcessing).copy();
}
toPostProcess.map(this::postProcess).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

当然,该copy()方法不存在,但如果确实如此,它将对流执行终端操作并返回包含所有相同元素的新流.

我知道实现这一目标的几种方法:

(1)通过数组(如果元素类型是泛型类型,则不是那么容易):

copy = Stream.of(stream.toArray(String[]::new));
Run Code Online (Sandbox Code Playgroud)

(2)通过列表:

copy = stream.collect(Collectors.toList()).stream();
Run Code Online (Sandbox Code Playgroud)

(3)通过流构建器:

Stream.Builder<V> builder = Stream.builder();
stream.forEach(builder);
copy = builder.build();
Run Code Online (Sandbox Code Playgroud)

我想知道的是:这些方法中哪一种在时间和记忆方面最有效?或者还有另一种方式更好吗?

java java-8 java-stream

6
推荐指数
1
解决办法
148
查看次数

具有记忆功能的 Java8 流

如何在 java8(可能是记忆过程)中重用已经通过流迭代计算出的值?

如果流被重复或再次提供,它将被重新计算。在某些情况下,最好用内存来换取 CPU 时间。从头开始收集所有内容可能不是一个好主意,因为流用于查找满足谓词的第一个项目。

Stream<Integer> all = Stream.of(1,2,3,4,5, ...<many other values>... ).
      map(x->veryLongTimeToComputeFunction(x));
System.out.println("fast find of 2"+all.filter(x->x>1).findFirst());

//both of these two lines generate a "java.lang.IllegalStateException: stream has already been operated upon or closed"
System.out.println("no find"+all.filter(x->x>10).findFirst());
System.out.println("find again"+all.filter(x->x>4).findFirst());
Run Code Online (Sandbox Code Playgroud)

问题类似于复制流以避免“流已被操作或关闭”(java 8)

java memoization java-8 java-stream

5
推荐指数
1
解决办法
1198
查看次数

Java 8流已经被操作或关闭

以下是我的代码:

void deleteTranslationIfUpdated(Stream<MediaTranslation> from, Stream<MediaTranslationDTO> data) {
    Stream<MediaTranslation> newLogos = data
        .map(mediaTranslationMapper::mapToEntity)
        .collect(Collectors.toList())
        .stream();

    from.filter(e ->
        newLogos.noneMatch(it ->
            Objects.equals(e.getLang(), it.getLang()) && Objects.equals(e.getValue().getLink(), it.getValue().getLink())))
        .map(MediaTranslation::getValue)
        .map(Media::getLink)
        .filter(this::isNotHttpLink)
        .forEach(storageService::delete);
}
Run Code Online (Sandbox Code Playgroud)

以上函数从以下函数调用:

@Secured({AuthoritiesConstants.USER})
public BrandDTO update(String id, BrandDTO data) throws EntityNotFound {
    log.debug("Request to update Brand : {} with {}", id, data);
    return Optional.ofNullable(brandRepository.findOne(id))
        .map(from -> {
            mediaService.deleteTranslationIfUpdated(from.getLogo().stream(), data.getLogo().stream());
            return from;
        })
        .map(target -> brandMapper.updateFromDto(data, target))
        .map(brandRepository::save)
        .map(brandMapper::mapToDto)
        .map(this::copyCategoriesInZone)
        .orElseThrow(EntityNotFound::new);
}
Run Code Online (Sandbox Code Playgroud)

每当我这样做,我得到以下错误:

java.lang.IllegalStateException: stream has already been operated upon or closed at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229) …

java lambda java-8 java-stream jhipster

5
推荐指数
1
解决办法
2589
查看次数

与Stream.of()的Java 8错误 - 像流和连接它们?

为什么以下java 8代码在第二次调用get()时显示错误?

    Stream<String> aStream = Stream.concat(Stream.of("A"), Stream.of("B"));
    String a = stream.findFirst().get();
    String b = stream.findFirst().get();
Run Code Online (Sandbox Code Playgroud)

"aStream"流应该看到两个值:"A"和"B".但是,在第一个元素已被消耗之后尝试读取任何内容

    java.lang.IllegalStateException: stream has already been operated upon or closed
Run Code Online (Sandbox Code Playgroud)

这不是Java 8中的错误吗?首先,为什么不消耗的Stream.of()-created流返回OptionalisPresent()==false?第二,为什么不Stream.concatenate()正确连接这样的Stream.of()创建流?

java concatenation illegalstateexception java-stream

1
推荐指数
1
解决办法
95
查看次数