我正在阅读流抽象的java 8 API,但我不太理解这句话:
中间操作返回一个新流.他们总是懒惰; 执行诸如filter()之类的中间操作实际上并不执行任何过滤,而是创建一个新流,当遍历时,该流包含与给定谓词匹配的初始流的元素.在执行管道的终端操作之前,不会开始遍历管道源.
当过滤操作创建新流时,该流是否包含已过滤的元素?似乎理解流仅在遍历时才包含元素,即具有终端操作.但是,包含过滤流的内容是什么?我糊涂了!!!
说我要创建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) 环境: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 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()缺少?
恕我直言,将结果转换为列表比数组更常见.我可以忍受这一点,但称这种丑陋是令人讨厌的.
有任何想法吗?
我想将对象流的流转换为单个对象流.我知道我必须使用这种flatMap方法,但我无法实现这一点,请看:
Stream<Stream<Object>> objectStreams = ...
Stream<Object> flatMappedStream = objectStreams.flatMap( ... );
Run Code Online (Sandbox Code Playgroud)
有人可以帮帮我吗?
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 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)
后者更容易实现.将它设计为前者的考虑是什么?
我想知道何时可以IntStream.range有效使用.我有三个原因,我不确定它有多大用处IntStream.range.
(请将开头和结尾视为整数.)
如果我想要一个数组,[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()非常缓慢.
我使用MersenneTwister来重排数组.(我在网上下载了MersenneTwister课程.)我认为没有办法IntStream使用MersenneTwister 进行随机播放.
我不认为刚开int从数字start到end-1是很有用的.我可以使用for(int i = start; i < end; i++),这似乎更容易,而不是慢.
你能告诉我什么时候应该选择IntStream.range吗?
我感觉不到Java 8 Streams map()和mapToObj()方法之间的区别.在两者中我们都可以创建对象并将对象返回到流,所以为什么这些方法存在为两个,而不仅仅是一个.
你能用例子给我解释一下吗?
我正在开发一款在 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) …