3 回答
TA贡献1856条经验 获得超11个赞
这是一个仅遍历列表一次的解决方案,在最后为您提供第一个红色和蓝色玩具。我们可以过滤掉所有其他不相关的颜色,然后创建一个映射,其键是玩具是否是红色,值是符合给定条件的第一个玩具。它看起来是这样的。
Map<Boolean, Toy> firstRedAndBlueToysMap = toyList.stream()
.filter(t -> t.isBlue() || t.isRed())
.collect(Collectors.toMap(Toy::isRed, t -> t, (a, b) -> a));
Toy firstRedToy = firstRedAndBlueToysMap.get(true);
Toy firstBlueToy = firstRedAndBlueToysMap.get(false);
这是解决您问题的一步法。
RedBlueExtravaganza firstRedAndBlueToyPair = toyList.stream()
.filter(t -> t.isBlue() || t.isRed())
.collect(Collectors.collectingAndThen(Collectors.toMap(Toy::isRed,
t -> t, (a, b) -> a),
m -> new RedBlueExtravaganza(m.get(true), m.get(false))));
PS 为此,您需要在RedBlueExtravaganza类中拥有以下构造函数,与上面提供的构造函数相反。
public RedBlueExtravaganza(Toy rt, Toy bt) {
if (!(rt instanceof RedToy) || !(bt instanceof BlueToy))
throw new IllegalArgumentException();
// remainder omitted.
}
TA贡献1966条经验 获得超4个赞
类似的解决方案可以是减少并列出为“元组(或其他)”
List<Toy> reduceToList = toyList.stream()
.filter(t -> t.isBlue() || t.isRed())
.map(t -> Arrays.asList(t, t))
.reduce(Arrays.asList(null, null), (a, c) -> a.get(0) == null && c.get(0).isRed() ?
Arrays.asList(c.get(0), a.get(1)) : (a.get(1) == null && c.get(1).isBlue() ?
Arrays.asList(a.get(0), c.get(1)) : a)
);
如果两个值都不为空,那么您可以映射到RedBlueExtravaganza
TA贡献1906条经验 获得超10个赞
我首先想到的一种方法是使用 2 个流分别查找第一个红色和蓝色玩具对象。然后通过使用将它们合并到一个流中,Stream.concat()以便您可以为此添加更多操作。
代码片段
RedBlueExtravaganza firstRedBlueList = Stream
.concat(
toyList.stream().filter(t -> t.isRed())
.findFirst()
.map(Collections::singletonList)
.orElseGet(Collections::emptyList)
.stream(),
toyList.stream().filter(t -> t.isBlue())
.findFirst()
.map(Collections::singletonList)
.orElseGet(Collections::emptyList)
.stream())
.map(x -> {
RedToy rt = new RedToy();
BlueToy bt = new BlueToy();
...
return new RedBlueExtravaganza(rt, bt);})
.findFirst()
.get();
添加回答
举报