Java 8引入了一个类似Scala的Stream的Stream类,这是一个功能强大的惰性结构,使用它可以非常简洁地执行这样的操作:
def from(n: Int): Stream[Int] = n #:: from(n+1)
def sieve(s: Stream[Int]): Stream[Int] = {
s.head #:: sieve(s.tail filter (_ % s.head != 0))
}
val primes = sieve(from(2))
primes takeWhile(_ < 1000) print // prints all primes less than 1000
Run Code Online (Sandbox Code Playgroud)
我想知道是否有可能在Java 8中这样做,所以我写了这样的东西:
IntStream from(int n) {
return IntStream.iterate(n, m -> m + 1);
}
IntStream sieve(IntStream s) {
int head = s.findFirst().getAsInt();
return IntStream.concat(IntStream.of(head), sieve(s.skip(1).filter(n -> n % head != 0)));
}
IntStream primes …Run Code Online (Sandbox Code Playgroud) 我试图在Java 8中使用新的Stream API生成随机的整数数组.但我还没有清楚地理解这个API.所以我需要帮助.这是我的代码.
Random random = new Random();
IntStream intStream = random.ints(low, high);
int[] array = intStream.limit(limit) // Limit amount of elements
.boxed() // cast to Integer
.toArray();
Run Code Online (Sandbox Code Playgroud)
但是这段代码返回了一些对象.这有什么问题?
在学习Java 8流和lambas时,我尝试用流替换以下嵌套for循环:
List<Long> deskIds = new ArrayList<>();
for(ProvidedService memberService : service.getAllNodesDepthFirst()){
for(Desk d : memberService.getDesks()){
deskIds.add(d.getId());
}
}
Run Code Online (Sandbox Code Playgroud)
循环迭代一个'ProvidedService'对象列表,并为每个对象迭代'Desk'对象的list属性,并将'Id'字段提取到列表中.
我使用流来提出以下代码:
List<Long> deskIds = new ArrayList<>();
service.getAllNodesDepthFirst().stream().forEach(srv -> {
deskIds.addAll(srv.getDesks().stream().map(Desk::getId).collect(Collectors.toList()));
});
Run Code Online (Sandbox Code Playgroud)
这是正确/最佳的方式吗?或者有没有办法在没有第二个嵌套流的情况下执行此操作?
是否可以在消费者中运行方法,如方法引用,但是在传递给使用者的对象上:
Arrays.stream(log.getHandlers()).forEach(h -> h.close());
Run Code Online (Sandbox Code Playgroud)
会是这样的事情:
Arrays.stream(log.getHandlers()).forEach(this::close);
Run Code Online (Sandbox Code Playgroud)
但那不行......
是否有可能使用方法参考,或者是x -> x.method()唯一可以在这里工作的方法?
我的问题可能过于宽泛,可能答案很简单,但我不得不问.
Java 7中是否有(Java 8)流*的等效实现?
我熟悉(Java 8)流,但我的项目要求是使用Java 7.
*不要与inputStream和outputStream混淆.
我如何使用Java Streams执行以下操作?
假设我有以下课程:
class Foo {
Bar b;
}
class Bar {
String id;
String date;
}
Run Code Online (Sandbox Code Playgroud)
我有一个List<Foo>,我想将其转换为Map <Foo.b.id, Map<Foo.b.date, Foo>.即:首先按组Foo.b.id,然后按Foo.b.date.
我正在努力采用以下两步法,但第二步甚至没有编译:
Map<String, List<Foo>> groupById =
myList
.stream()
.collect(
Collectors.groupingBy(
foo -> foo.getBar().getId()
)
);
Map<String, Map<String, Foo>> output = groupById.entrySet()
.stream()
.map(
entry -> entry.getKey(),
entry -> entry.getValue()
.stream()
.collect(
Collectors.groupingBy(
bar -> bar.getDate()
)
)
);
Run Code Online (Sandbox Code Playgroud)
提前致谢.
Javadoc Stream.forEach表示(强调我的):
此操作的行为明确是不确定的.对于并行流管道,此操作不保证遵守流的遭遇顺序,因为这样做会牺牲并行性的好处.对于任何给定元素,可以在任何时间以及库选择的任何线程中执行该动作.如果操作访问共享状态,则它负责提供所需的同步.
Java 9 Early Access Javadoc中提供了相同的文本.
第一句("明确不确定")表明(但没有明确说明)此方法不会保留遭遇顺序.但是明确说明顺序没有保留的下一个句子是以"For parallel stream pipeline"为条件的,如果不管并行性如何应用该句子,那么这个条件就没有了.这让我不确定forEach是否会保留顺序流的顺序.
这个答案指出了流库实现调用的位置.sequential().forEach(downstream).这表明forEach旨在保留顺序流的顺序,但也可能只是库中的错误.
我通过使用forEachOrdered安全的方式回避了我自己的代码中的这种模糊性,但今天我发现NetBeans IDE的"使用功能操作"编辑器提示将转换
for (Foo foo : collection)
foo.bar();
Run Code Online (Sandbox Code Playgroud)
成
collection.stream().forEach((foo) -> {
foo.bar();
});
Run Code Online (Sandbox Code Playgroud)
如果forEach不保留遭遇顺序,则会引入错误.在我报告针对NetBeans的错误之前,我想知道库实际上保证了什么,并由源备份.
我正在寻找权威人士的答案.这可能是图书馆实施中的一个明确的评论,关于Java开发邮件列表的讨论(谷歌没有找到任何东西,但我可能不知道这些神奇的词汇),或者是图书馆设计师的声明(其中我知道两个,Brian Goetz和Stuart Marks,积极参与Stack Overflow).(请不要回答"只是使用forEachOrdered" - 我已经这样做了,但我想知道代码是否错误.)
我正在编写一个自定义java 8收集器,它应该计算具有getValue()方法的POJO的平均值.这是代码:
public static Collector<BoltAggregationData, BigDecimal[], BigDecimal> avgCollector = new Collector<BoltAggregationData, BigDecimal[], BigDecimal>() {
@Override
public Supplier<BigDecimal[]> supplier() {
return () -> {
BigDecimal[] start = new BigDecimal[2];
start[0] = BigDecimal.ZERO;
start[1] = BigDecimal.ZERO;
return start;
};
}
@Override
public BiConsumer<BigDecimal[], BoltAggregationData> accumulator() {
return (a,b) -> {
a[0] = a[0].add(b.getValue());
a[1] = a[1].add(BigDecimal.ONE);
};
}
@Override
public BinaryOperator<BigDecimal[]> combiner() {
return (a,b) -> {
a[0] = a[0].add(b[0]);
a[1] = a[1].add(b[1]);
return a;
};
}
@Override
public Function<BigDecimal[], …Run Code Online (Sandbox Code Playgroud) 假设我有这两个矩阵:
double[][] a = new double[2][2]
a[0][0] = 1
a[0][1] = 2
a[1][0] = 3
a[1][1] = 4
double[][] b = new double[2][2]
b[0][0] = 1
b[0][1] = 2
b[1][0] = 3
b[1][1] = 4
Run Code Online (Sandbox Code Playgroud)
以传统方式,总结这个矩阵我会做一个嵌套for循环:
int rows = a.length;
int cols = a[0].length;
double[][] res = new double[rows][cols];
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++){
res[i][j] = a[i][j] + b[i][j];
}
}
Run Code Online (Sandbox Code Playgroud)
我对流API很新,但我认为这非常适合使用,parallelStream所以我的问题是,如果有办法做到这一点并利用并行处理?
编辑:不确定这是不是正确的地方,但我们走了:使用一些建议我把Stream推到测试.设置如下:经典方法:
public class ClassicMatrix …Run Code Online (Sandbox Code Playgroud) 有没有办法在一次处理中收集匹配和不匹配的流元素?举个例子:
final List<Integer> numbers = Arrays.asList( 1, 2, 3, 4, 5 );
final List<Integer> even = numbers.stream().filter( n -> n % 2 == 0 ).collect( Collectors.toList() );
final List<Integer> odd = numbers.stream().filter( n -> n % 2 != 0 ).collect( Collectors.toList() );
Run Code Online (Sandbox Code Playgroud)
有没有办法避免两次运行数字列表?像"比赛的收藏家和没有比赛的收藏家"这样的东西?