累积值和 return 导致 Java 流
Accumulate values and return result in Java stream
我有一个包含 Seed
个元素的集合的 class。 Seed
方法的 return 类型之一是 Optional<Pair<Boolean, Boolean>>
.
我正在尝试遍历所有 seeds
,保持 return 类型 (Optional<Pair<Boolean, Boolean>>
),但我想知道是否至少有 true
值(在任何 Pair
中)并用它覆盖结果。基本上,如果集合是(跳过 Optional
包装器以使事情更简单):[Pair<false, false>
、Pair<false, true>
、Pair<false, false>
] 我想 return 和Optional
的 Pair<false, true>
因为第二个元素有 true
。最后,我感兴趣的是是否有 true
值,仅此而已。
public Optional<Pair<Boolean, Boolean>> hadAnyExposure() {
return seeds.stream()
.map(Seed::hadExposure)
...
}
我正在玩 reduce
但无法想出任何有用的东西。
My question is related with Java streams directly. I can easily do this with a for
loop, but I aimed initially for streams.
您对 reduce
的想法看起来是正确的方法,使用 ||
将每个 Pair
的两边一起减少。 (不确定你的 Optional
语义是什么,所以要在这里过滤掉空的语义,这可能会得到你想要的,但你可能需要调整):
Optional<Pair<Boolean, Boolean>> result = seeds.stream().map(Seed::hadExposure)
.filter(Optional::isPresent)
.map(Optional::get)
.reduce((a, b) -> new Pair<>(a.first || b.first, a.second || b.second));
因为你用 java-11
标记了这个问题,你可以使用 Optional.stream
方法:
public Optional<Pair<Boolean, Boolean>> hadAnyExposure() {
return Optional.of(
seeds.stream()
.flatMap(seed -> seed.hadExposure().stream())
.collect(
() -> new Pair<Boolean, Boolean>(false, false),
(p, seed) -> {
p.setLeft(p.getLeft() || seed.getLeft());
p.setRight(p.getRight() || seed.getRight());
},
(p1, p2) -> {
p1.setLeft(p1.getLeft() || p2.getLeft());
p1.setRight(p1.getRight() || p2.getRight());
}));
}
这首先通过 Optional.stream
方法摆脱了 Optional
(只保留对)然后使用 Stream.collect
到 可变 通过 OR associative 操作减少对。
注意:使用 Stream.reduce
也可以,但会产生很多不必要的中间对。这就是我使用 Stream.collect
的原因。
使用 Collectors.partitioningBy
你可以获得一个带有布尔键的地图,之后你可以轻松地检索使用键 true
索引的值
Optional<Pair<Boolean, Boolean>> collect = Arrays.asList(pair1, pair2, par3).stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.collectingAndThen(Collectors.partitioningBy(p -> p.getFirst() == true || p.getSecond() == true),
m -> m.get(true).stream().findAny()));
直截了当
因为你是 Java 11 岁,你可以使用 Optional::stream
(introduced in Java 9) 摆脱 Optional
包装。作为终端操作,reduce
是你的朋友:
public Optional<Pair<Boolean, Boolean>> hadAnyExposure() {
// wherever the seeds come from
Stream<Optional<Pair<Boolean, Boolean>>> seeds = seeds();
return seeds
.flatMap(Optional::stream)
.reduce((pair1, pair2) -> new Pair<>(
pair1.left() || pair2.left(),
pair1.right() || pair2.right())
);
}
扩展
如果您想更进一步,为您的 Pair
提供一种与另一个 Pair
折叠成新实例的通用方法,您可以使代码更具表现力:
public class Pair<LEFT, RIGHT> {
private final LEFT left;
private final RIGHT right;
// constructor, equals, hashCode, toString, ...
public Pair<LEFT, RIGHT> fold(
Pair<LEFT, RIGHT> other,
BinaryOperator<LEFT> combineLeft,
BinaryOperator<RIGHT> combineRight) {
return new Pair<>(
combineLeft.apply(left, other.left),
combineRight.apply(right, other.right));
}
}
// now you can use fold and Boolean::logicalOr
// https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Boolean.html#logicalOr(boolean,boolean)
public Optional<Pair<Boolean, Boolean>> hadAnyExposure() {
Stream<Optional<Pair<Boolean, Boolean>>> seeds = seeds();
return seeds
.flatMap(Optional::stream)
.reduce((pair1, pair2) -> pair1
.fold(pair2, Boolean::logicalOr, Boolean::logicalOr))
);
}
我可能不会只为这个用例创建 Pair::fold
,但我会被诱惑。 ;)
我有一个包含 Seed
个元素的集合的 class。 Seed
方法的 return 类型之一是 Optional<Pair<Boolean, Boolean>>
.
我正在尝试遍历所有 seeds
,保持 return 类型 (Optional<Pair<Boolean, Boolean>>
),但我想知道是否至少有 true
值(在任何 Pair
中)并用它覆盖结果。基本上,如果集合是(跳过 Optional
包装器以使事情更简单):[Pair<false, false>
、Pair<false, true>
、Pair<false, false>
] 我想 return 和Optional
的 Pair<false, true>
因为第二个元素有 true
。最后,我感兴趣的是是否有 true
值,仅此而已。
public Optional<Pair<Boolean, Boolean>> hadAnyExposure() {
return seeds.stream()
.map(Seed::hadExposure)
...
}
我正在玩 reduce
但无法想出任何有用的东西。
My question is related with Java streams directly. I can easily do this with a
for
loop, but I aimed initially for streams.
您对 reduce
的想法看起来是正确的方法,使用 ||
将每个 Pair
的两边一起减少。 (不确定你的 Optional
语义是什么,所以要在这里过滤掉空的语义,这可能会得到你想要的,但你可能需要调整):
Optional<Pair<Boolean, Boolean>> result = seeds.stream().map(Seed::hadExposure)
.filter(Optional::isPresent)
.map(Optional::get)
.reduce((a, b) -> new Pair<>(a.first || b.first, a.second || b.second));
因为你用 java-11
标记了这个问题,你可以使用 Optional.stream
方法:
public Optional<Pair<Boolean, Boolean>> hadAnyExposure() {
return Optional.of(
seeds.stream()
.flatMap(seed -> seed.hadExposure().stream())
.collect(
() -> new Pair<Boolean, Boolean>(false, false),
(p, seed) -> {
p.setLeft(p.getLeft() || seed.getLeft());
p.setRight(p.getRight() || seed.getRight());
},
(p1, p2) -> {
p1.setLeft(p1.getLeft() || p2.getLeft());
p1.setRight(p1.getRight() || p2.getRight());
}));
}
这首先通过 Optional.stream
方法摆脱了 Optional
(只保留对)然后使用 Stream.collect
到 可变 通过 OR associative 操作减少对。
注意:使用 Stream.reduce
也可以,但会产生很多不必要的中间对。这就是我使用 Stream.collect
的原因。
使用 Collectors.partitioningBy
你可以获得一个带有布尔键的地图,之后你可以轻松地检索使用键 true
Optional<Pair<Boolean, Boolean>> collect = Arrays.asList(pair1, pair2, par3).stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.collectingAndThen(Collectors.partitioningBy(p -> p.getFirst() == true || p.getSecond() == true),
m -> m.get(true).stream().findAny()));
直截了当
因为你是 Java 11 岁,你可以使用 Optional::stream
(introduced in Java 9) 摆脱 Optional
包装。作为终端操作,reduce
是你的朋友:
public Optional<Pair<Boolean, Boolean>> hadAnyExposure() {
// wherever the seeds come from
Stream<Optional<Pair<Boolean, Boolean>>> seeds = seeds();
return seeds
.flatMap(Optional::stream)
.reduce((pair1, pair2) -> new Pair<>(
pair1.left() || pair2.left(),
pair1.right() || pair2.right())
);
}
扩展
如果您想更进一步,为您的 Pair
提供一种与另一个 Pair
折叠成新实例的通用方法,您可以使代码更具表现力:
public class Pair<LEFT, RIGHT> {
private final LEFT left;
private final RIGHT right;
// constructor, equals, hashCode, toString, ...
public Pair<LEFT, RIGHT> fold(
Pair<LEFT, RIGHT> other,
BinaryOperator<LEFT> combineLeft,
BinaryOperator<RIGHT> combineRight) {
return new Pair<>(
combineLeft.apply(left, other.left),
combineRight.apply(right, other.right));
}
}
// now you can use fold and Boolean::logicalOr
// https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Boolean.html#logicalOr(boolean,boolean)
public Optional<Pair<Boolean, Boolean>> hadAnyExposure() {
Stream<Optional<Pair<Boolean, Boolean>>> seeds = seeds();
return seeds
.flatMap(Optional::stream)
.reduce((pair1, pair2) -> pair1
.fold(pair2, Boolean::logicalOr, Boolean::logicalOr))
);
}
我可能不会只为这个用例创建 Pair::fold
,但我会被诱惑。 ;)