标签: java-stream

流和懒惰的评估

我正在阅读流抽象的java 8 API,但我不太理解这句话:

中间操作返回一个新流.他们总是懒惰; 执行诸如filter()之类的中间操作实际上并不执行任何过滤,而是创建一个新流,当遍历时,该流包含与给定谓词匹配的初始流的元素.在执行管道的终端操作之前,不会开始遍历管道源.

当过滤操作创建新流时,该流是否包含已过滤的元素?似乎理解流仅在遍历时才包含元素,即具有终端操作.但是,包含过滤流的内容是什么?我糊涂了!!!

java java-8 java-stream

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

使用流迭代n次而不是使用for循环来创建n个项目

说我要创建n个项目.在Java 8之前,我会写:

List<MyClass> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
    list.add(new MyClass());
}
Run Code Online (Sandbox Code Playgroud)

有一种优雅的方式来使用流来创建n个项目吗?
我想到了这个:

List<MyClass> list = Stream.iterate(0, i -> i).limit(10)
    .map(o -> new MyClass()).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

是否有标准/更好的编码方式?

请注意,实际使用情况稍微复杂一些,使用流会更灵活,因为我可以立即通过一行中的其他函数抽取项目,甚至无需创建对列表的引用,例如对它们进行分组:

Stream.iterate(0, i -> i).limit(10).map(o -> new MyClass())
    .collect(Collectors.groupingBy(...));
Run Code Online (Sandbox Code Playgroud)

loops java-8 java-stream

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

这是Files.lines()中的错误,还是我误解了并行流的某些内容?

环境:Ubuntu x86_64(14.10),Oracle JDK 1.8u25

我尝试使用并行流Files.lines()但我想要.skip()第一行(它是带有标题的CSV文件).所以我试着这样做:

try (
    final Stream<String> stream = Files.lines(thePath, StandardCharsets.UTF_8)
        .skip(1L).parallel();
) {
    // etc
}
Run Code Online (Sandbox Code Playgroud)

但是后来一列未能解析成一个int ...

所以我尝试了一些简单的代码.文件问题很简单:

$ cat info.csv 
startDate;treeDepth;nrMatchers;nrLines;nrChars;nrCodePoints;nrNodes
1422758875023;34;54;151;4375;4375;27486
$
Run Code Online (Sandbox Code Playgroud)

代码同样简单:

public static void main(final String... args)
{
    final Path path = Paths.get("/home/fge/tmp/dd/info.csv");
    Files.lines(path, StandardCharsets.UTF_8).skip(1L).parallel()
        .forEach(System.out::println);
}
Run Code Online (Sandbox Code Playgroud)

我系统地得到以下结果(好吧,我只运行了大约20次):

startDate;treeDepth;nrMatchers;nrLines;nrChars;nrCodePoints;nrNodes
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么?


编辑似乎问题或误解比这更根深蒂固(下面的两个例子是由FreeNode的## java编写的):

public static void main(final String... args)
{
    new BufferedReader(new StringReader("Hello\nWorld")).lines()
        .skip(1L).parallel()
        .forEach(System.out::println);

    final Iterator<String> iter
        = Arrays.asList("Hello", "World").iterator();
    final Spliterator<String> spliterator
        = Spliterators.spliteratorUnknownSize(iter, …
Run Code Online (Sandbox Code Playgroud)

java parallel-processing java-8 java-stream

34
推荐指数
3
解决办法
2842
查看次数

为什么Stream没有toList()方法?

使用Java 8流时,采用列表,从中创建流,执行业务并将其转换回来是很常见的.就像是:

 Stream.of(-2,1,2,-5)
        .filter(n -> n > 0)
        .map(n -> n * n)
        .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

为什么' .collect(Collectors.toList())'部分没有捷径/方便的方法?在Stream接口上,有将方法转换为数组的方法toArray(),为什么toList()缺少?

恕我直言,将结果转换为列表比数组更常见.我可以忍受这一点,但称这种丑陋是令人讨厌的.

有任何想法吗?

java java-8 java-stream

34
推荐指数
3
解决办法
4114
查看次数

如何在Java中平面映射流?

我想将对象流的流转换为单个对象流.我知道我必须使用这种flatMap方法,但我无法实现这一点,请看:

Stream<Stream<Object>> objectStreams = ...
Stream<Object> flatMappedStream = objectStreams.flatMap( ... );
Run Code Online (Sandbox Code Playgroud)

有人可以帮帮我吗?

java java-8 java-stream

34
推荐指数
1
解决办法
2万
查看次数

为什么Stream.limit在此代码段中没有按预期工作?

List<Integer> integer = Stream.generate(new Supplier<Integer>() {
    int i = 0 ;

    @Override
    public Integer get() {
        return ++i;
    }
}).filter(j -> j < 5)
  .limit(10)   // Note the call to limit here
  .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

与我的期望相反,collect呼叫永远不会回来.设置limit之前filter产生预期结果.为什么?

java java-8 java-stream

34
推荐指数
4
解决办法
1324
查看次数

为什么Java 8'Collector'类以这种方式设计?

我们知道Java 8引入了一个新的Stream API,并且java.util.stream.Collector是定义如何聚合/收集数据流的接口.

但是,Collector接口的设计如下:

public interface Collector<T, A, R> {
    Supplier<A> supplier();
    BiConsumer<A, T> accumulator();
    BinaryOperator<A> combiner();
    Function<A, R> finisher();
}
Run Code Online (Sandbox Code Playgroud)

为什么它的设计不符合以下规定?

public interface Collector<T, A, R> {
    A supply();
    void accumulate(A accumulator, T value);
    A combine(A left, A right);
    R finish(A accumulator);
}
Run Code Online (Sandbox Code Playgroud)

后者更容易实现.将它设计为前者的考虑是什么?

java java-8 java-stream collectors

34
推荐指数
2
解决办法
2298
查看次数

我什么时候应该在Java中使用IntStream.range?

我想知道何时可以IntStream.range有效使用.我有三个原因,我不确定它有多大用处IntStream.range.

(请将开头和结尾视为整数.)

  1. 如果我想要一个数组,[start, start+1, ..., end-2, end-1]下面的代码要快得多.

    int[] arr = new int[end - start];
    int index = 0;
    for(int i = start; i < end; i++)
        arr[index++] = i;
    
    Run Code Online (Sandbox Code Playgroud)

    这可能是因为toArray()在IntStream.range(start, end).toArray()非常缓慢.

  2. 我使用MersenneTwister来重排数组.(我在网上下载了MersenneTwister课程.)我认为没有办法IntStream使用MersenneTwister 进行随机播放.

  3. 我不认为刚开int从数字start到end-1是很有用的.我可以使用for(int i = start; i < end; i++),这似乎更容易,而不是慢.

你能告诉我什么时候应该选择IntStream.range吗?

java java-8 java-stream

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

地图和mapToObj之间的Java Stream差异

我感觉不到Java 8 Streams map()和mapToObj()方法之间的区别.在两者中我们都可以创建对象并将对象返回到流,所以为什么这些方法存在为两个,而不仅仅是一个.

你能用例子给我解释一下吗?

java java-8 java-stream

34
推荐指数
2
解决办法
8914
查看次数

Java 17 的 parallelStream() 会导致在 Java 16 中正常运行的代码出现严重的性能问题。为什么?

我正在开发一款在 Java 16 上运行的 Jetty Web 应用程序。我尝试将其升级到 Java 17,但完全由一次调用parallelStream().

唯一的变化是 Java 版本从 16 提升到 17,--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED运行时openjdk:16.0.1-jdk-oraclelinux8从openjdk:17.0.1-jdk-oraclelinux8.

我们设法获得了一个线程转储,其中包含许多内容:

"qtp1368594774-200" #200 prio=5 os_prio=0 cpu=475.94ms elapsed=7189.65s tid=0x00007fd49c50cc10 nid=0xd1 waiting on condition  [0x00007fd48fef7000]
   java.lang.Thread.State: WAITING (parking)
    at jdk.internal.misc.Unsafe.park(java.base@17.0.1/Native Method)
    - parking to wait for  <0x00000007b73439a8> (a java.util.stream.ReduceOps$ReduceTask)
    at java.util.concurrent.locks.LockSupport.park(java.base@17.0.1/LockSupport.java:341)
    at java.util.concurrent.ForkJoinTask.awaitDone(java.base@17.0.1/ForkJoinTask.java:468)
    at java.util.concurrent.ForkJoinTask.invoke(java.base@17.0.1/ForkJoinTask.java:687)
    at java.util.stream.ReduceOps$ReduceOp.evaluateParallel(java.base@17.0.1/ReduceOps.java:927)
    at java.util.stream.AbstractPipeline.evaluate(java.base@17.0.1/AbstractPipeline.java:233)
    at java.util.stream.ReferencePipeline.collect(java.base@17.0.1/ReferencePipeline.java:682)
    at com.stackoverflowexample.aMethodThatDoesBlockingIOUsingParallelStream()
Run Code Online (Sandbox Code Playgroud)

导致问题的代码类似于:

list.parallelStream()
.map(this::callRestServiceToGetSomeData)
.collect(Collectors.toUnmodifiableList());
Run Code Online (Sandbox Code Playgroud)

此图显示了从 jdk16(左轴)升级到 jdk17(中间的巨大尖峰),然后删除对parallelStream()仍然在 jdk17(右轴)上的调用之前的线程使用情况:

线程数

Java 17 (openjdk-17.0.1_linux-x64_bin.tar.gz) …

java jetty java-stream java-17

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