标签: java-stream

当.stream().parallel()做同样的事情时,为什么Collection.parallelStream()存在?

在Java 8中,Collection接口扩展了两个返回的方法Stream<E>:stream()返回一个顺序流,并parallelStream()返回一个可能并行的流.流本身也有一个parallel()返回等效并行流的方法(将当前流变为并行或创建新流).

复制有明显的缺点:

  • 这令人困惑.一个问题,如果parallelStream()可能返回顺序流,是否需要同时调用parallelStream().parallel()以确保流是并行的.如果无法保证parallelStream(),为什么会存在?反过来也是混乱 - 如果parallelStream()返回顺序流,则可能有一个原因(例如,并行流是性能陷阱的固有顺序数据结构); Stream.parallel()应该为这样的流做什么?(parallel()的规范不允许使用UnsupportedOperationException.)

  • 如果现有实现具有类似命名的方法且返回类型不兼容,则向接口添加方法会产生冲突.除了stream()之外,添加parallelStream()会使得收益微不足道的风险增加一倍.(注意,parallelStream()只是名为parallel(),但我不知道它是否被重命名以避免名称冲突或其他原因.)

为什么在调用Collection.stream()时才存在Collection.parallelStream().parallel()做同样的事情?

java java-8 java-stream

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

布尔值流,是真的吗?

我想使用parallelStream并行化以下代码:

boolean anyTrue() {
  for (Element e : setOfE) {
    if (eval(e)) {
      return true;
    }
  }
  return false;
}
Run Code Online (Sandbox Code Playgroud)

以下是否可以在并行流上使用并定期进行短路评估?

setOfE.parallelStream().map(e -> eval(e)).reduce(false, (a,b) -> a || b))
Run Code Online (Sandbox Code Playgroud)

java parallel-processing lambda java-8 java-stream

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

用流映射的Java 8列表

我有一个List<Item>集合.我需要将其转换Map<Integer, Item> 为映射的键必须是集合中项的索引.我无法弄清楚如何使用流来做到这一点.就像是:

items.stream().collect(Collectors.toMap(...));
Run Code Online (Sandbox Code Playgroud)

有帮助吗?

由于这个问题被确定为可能重复,我需要补充一点,我的具体问题是 - 如何获取列表中项目的位置并将其作为键值

java collections dictionary java-8 java-stream

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

如何将String拆分为字符串流?

将String拆分为Stream 的最佳方法是什么?

我看到了这些变化:

  1. Arrays.stream("b,l,a".split(","))
  2. Stream.of("b,l,a".split(","))
  3. Pattern.compile(",").splitAsStream("b,l,a")

我的优先事项是:

  • 稳健性
  • 可读性
  • 性能

一个完整的,可编译的例子:

import java.util.Arrays;
import java.util.regex.Pattern;
import java.util.stream.Stream;

public class HelloWorld {

    public static void main(String[] args) {
        stream1().forEach(System.out::println);
        stream2().forEach(System.out::println);
        stream3().forEach(System.out::println);
    }

    private static Stream<String> stream1() {
        return Arrays.stream("b,l,a".split(","));
    }

    private static Stream<String> stream2() {
        return Stream.of("b,l,a".split(","));
    }

    private static Stream<String> stream3() {
        return Pattern.compile(",").splitAsStream("b,l,a");
    }

}
Run Code Online (Sandbox Code Playgroud)

java regex split java-stream

49
推荐指数
1
解决办法
3万
查看次数

Java 8是否缺少Stream.concat处理流的varags?

目前我们Stream.concat在Java 8中有以下内容:

public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b);
Run Code Online (Sandbox Code Playgroud)

我很惊讶为什么没有版本采取varargs Stream<? extends T>

目前我的代码编写如下:

Stream<Integer> resultStream = Stream.concat(stream1, Stream.concat(stream2, Stream.of(element)))
        .filter(x -> x != 0)
        .filter(x -> x != 1)
        .filter(x -> x != 2);
Run Code Online (Sandbox Code Playgroud)

如果提供此签名的varargs:

public static <T> Stream<T> concat(Stream<? extends T>... streams);
Run Code Online (Sandbox Code Playgroud)

然后我可以更清楚地写出:

Stream<Integer> resultStream = Stream.concat(
                stream1,
                stream2,
                Stream.of(element)
        )
        .filter(x -> x != 0)
        .filter(x -> x != 1)
        .filter(x -> x != 2);
Run Code Online (Sandbox Code Playgroud)

没有各种嵌套Stream.concat调用.

还是有其他原因没有提供? …

java java-8 java-stream

48
推荐指数
3
解决办法
1万
查看次数

从java8流创建番石榴MultiMap的最简洁方法

我有一个List<Foo>并且想要一个Multimap<String, Foo>我们Foo根据他们的getId()功能对其进行分组的地方.

我正在使用Java 8,它几乎可以做到:

List<Foo> foos = ...
Map<String, List<Foo>> foosById = foos.stream().collect(groupingBy(Foo::getId));
Run Code Online (Sandbox Code Playgroud)

但是,我有大量的代码需要一个,MultiMap<String, Foo>所以这并没有为我节省任何东西,我回到使用for循环来创建我的MultiMap.我错过了一个很好的"功能性"方式吗?

guava java-8 java-stream

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

Java8流顺序和并行执行产生不同的结果?

在Java8中运行以下流示例:

    System.out.println(Stream
        .of("a", "b", "c", "d", "e", "f")
        .reduce("", (s1, s2) -> s1 + "/" + s2)
    );
Run Code Online (Sandbox Code Playgroud)

收益率:

/a/b/c/d/e/f
Run Code Online (Sandbox Code Playgroud)

这是 - 当然 - 毫不奇怪.由于http://docs.oracle.com/javase/8/docs/api/index.html?overview-summary.html,流顺序执行还是并行执行无关紧要:

除了标识为显式非确定性的操作(例如findAny())之外,流是顺序执行还是并行执行不应更改计算结果.

AFAIK reduce()是确定性的并且(s1, s2) -> s1 + "/" + s2是关联的,因此添加parallel()应该产生相同的结果:

    System.out.println(Stream
            .of("a", "b", "c", "d", "e", "f")
            .parallel()
            .reduce("", (s1, s2) -> s1 + "/" + s2)
    );
Run Code Online (Sandbox Code Playgroud)

但是我机器上的结果是:

/a//b//c//d//e//f
Run Code Online (Sandbox Code Playgroud)

这有什么不对?

BTW:使用(首选).collect(Collectors.joining("/"))而不是为顺序和并行执行reduce(...)产生相同的结果a/b/c/d/e/f.

JVM详细信息:

java.specification.version: 1.8
java.version: 1.8.0_31
java.vm.version: 25.31-b07
java.runtime.version: 1.8.0_31-b13
Run Code Online (Sandbox Code Playgroud)

java lambda java-8 java-stream

48
推荐指数
2
解决办法
3030
查看次数

Java 8流不可预测的性能下降没有明显的原因

我正在使用Java 8流来迭代包含子列表的列表.外部列表大小在100到1000之间(不同的测试运行),内部列表大小始终为5.

有2个基准测试运行显示意外的性能偏差.

package benchmark;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;

import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

@Threads(32)
@Warmup(iterations = 25)
@Measurement(iterations = 5)
@State(Scope.Benchmark)
@Fork(1)
@BenchmarkMode(Mode.Throughput)
public class StreamBenchmark {
    @Param({"700", "600", "500", "400", "300", "200", "100"})
    int outerListSizeParam;
    final static int INNER_LIST_SIZE = 5;
    List<List<Integer>> list;

    Random rand() {
        return ThreadLocalRandom.current();
    }

    final BinaryOperator<Integer> reducer = (val1, val2) -> val1 + val2;

    final Supplier<List<Integer>> supplier = () -> IntStream
            .range(0, INNER_LIST_SIZE)
            .mapToObj(ptr -> rand().nextInt(100))
            .collect(Collectors.toList());

    @Setup …
Run Code Online (Sandbox Code Playgroud)

java performance lambda java-stream jmh

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

为什么Files.lines(和类似的Streams)不会自动关闭?

Stream的javadoc说明:

Streams有一个BaseStream.close()方法并实现AutoCloseable,但几乎所有的流实例实际上都不需要在使用后关闭.通常,只有源为IO通道的流(例如Files.lines(Path,Charset)返回的流)才需要关闭.大多数流都由集合,数组或生成函数支持,不需要特殊的资源管理.(如果流确实需要关闭,则可以在try-with-resources语句中将其声明为资源.)

因此,绝大多数情况下,人们可以在单行中使用Streams,collection.stream().forEach(System.out::println);但是对于Files.lines和其他资源支持的流,必须使用try-with-resources语句或泄漏资源.

这让我觉得容易出错并且不必要.因为Streams只能迭代一次,所以在我看来,没有一个迭代后Files.lines不应该关闭输出的情况,因此实现应该只是在任何终端操作结束时隐式调用close .我错了吗?

java stream resource-leak java-8 java-stream

48
推荐指数
3
解决办法
9075
查看次数

是否有一种干净(和安全的)方法来乘以Java中的地图值?

我有一个Map<String, Double>,并希望将地图中的所有值乘以2,比方说,但是将空值保持为空.

我显然可以使用for循环来做到这一点,但是想知道是否有更清洁的方法呢?

Map<String, Double> someMap = someMapFunction();
Map<String, Double> adjustedMap = new Hashmap<>();
if (someMap != null) {
    for (Map.Entry<String,Double> pair : someMap.entryset()) {
        if (pair.getValue() == null) {
            adjustedMap.put(pair.getKey(), pair.getValue());
        } else {
            adjustedMap.put(pair.getKey(), pair.getValue()*2)
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

有时候返回的地图someMapFunction是一个不可变的地图,所以这不能用就地做Map.replaceAll.我无法想出一个更清洁的流解决方案.

java java-8 java-stream

48
推荐指数
4
解决办法
4608
查看次数