Java Apply stream可筛选出除一个元素之外满足条件的所有元素
我有以下课程:Java Apply stream可筛选出除一个元素之外满足条件的所有元素,java,java-8,java-stream,Java,Java 8,Java Stream,我有以下课程: public class Offer { private final OfferType type; private final BigDecimal price; // constructor, getters and setters } 和枚举类型: public enum OfferType { STANDARD, BONUS; } 我的用例是,有一个报价列表作为输入,我想过滤掉所有的标准报价,除了最便宜的报价。所以对于下面的输入数据
public class Offer {
private final OfferType type;
private final BigDecimal price;
// constructor, getters and setters
}
和枚举类型:
public enum OfferType {
STANDARD, BONUS;
}
我的用例是,有一个报价列表作为输入,我想过滤掉所有的标准报价,除了最便宜的报价。所以对于下面的输入数据
List<Offer> offers = Arrays.asList(new Offer(OfferType.STANDARD, BigDecimal.valueOf(10.0)),
new Offer(OfferType.STANDARD, BigDecimal.valueOf(20.0)),
new Offer(OfferType.STANDARD, BigDecimal.valueOf(30.0)),
new Offer(OfferType.BONUS, BigDecimal.valueOf(5.0)),
new Offer(OfferType.BONUS, BigDecimal.valueOf(5.0)));
是否有允许这样做的单行语句(使用streams或任何第三方库) List result=offers.stream().filter(e->OfferType.BONUS==e.getType()).collect(toList());
List<Offer> result = offers.stream().filter(e -> OfferType.BONUS == e.getType()).collect(toList());
offers.stream().filter(e -> OfferType.STANDARD == e.getType()).findAny().ifPresent(result::add);
offers.stream().filter(e->OfferType.STANDARD==e.getType()).findAny().ifPresent(结果::添加);
不使用单流操作,但:
List<Offer> some = offers.stream()
.filter(x -> x.getType() != OfferType.STANDARD)
.collect(Collectors.toCollection(ArrayList::new));
offers.stream()
.filter(x -> x.getType() == OfferType.STANDARD)
.min(Comparator.comparing(Offer::getPrice))
.ifPresent(some::add);
List some=offers.stream()
.filter(x->x.getType()!=OfferType.STANDARD)
.collect(收集器.toCollection(ArrayList::new));
offers.stream()
.filter(x->x.getType()==OfferType.STANDARD)
.min(比较器比较(报价::getPrice))
.ifPresent(一些::添加);
如果您发现自己经常这样做,您可能会选择一个自定义收集器:
public static Collector<Offer, ?, List<Offer>> minCollector() {
class Acc {
Offer min = null;
List<Offer> result = new ArrayList<>();
void add(Offer offer) {
if (offer.getType() == OfferType.STANDARD) {
if (min == null) {
min = offer;
} else {
min = offer.getPrice()
.compareTo(min.getPrice()) > 0 ? min : offer;
}
} else {
result.add(offer);
}
}
Acc combine(Acc another) {
this.min = reduceMin(this.min, another.min);
result.addAll(another.result);
return this;
}
List<Offer> finisher() {
result.add(min);
return result;
}
private Offer reduceMin(Offer left, Offer right) {
return Collections.min(Arrays.asList(left, right),
Comparator.nullsLast(Comparator.comparing(Offer::getPrice)));
}
}
return Collector.of(Acc::new, Acc::add, Acc::combine, Acc::finisher);
}
公共静态收集器minCollector(){
等级Acc{
Offer min=null;
列表结果=新建ArrayList();
无效添加(报价){
if(offer.getType()==OfferType.STANDARD){
if(min==null){
最小=报价;
}否则{
min=offer.getPrice()
.compareTo(min.getPrice())>0?min:报价;
}
}否则{
结果。添加(报价);
}
}
Acc联合收割机(Acc另一个){
this.min=reduceMin(this.min,另一个.min);
result.addAll(另一个.result);
归还这个;
}
列表整理器(){
结果:添加(分钟);
返回结果;
}
私人报价减少(报价左,报价右){
返回Collections.min(Arrays.asList(左、右),
nullsLast(Comparator.comparing(Offer::getPrice));
}
}
返回收集器of(Acc::new、Acc::add、Acc::combine、Acc::finisher);
}
其用途是:
List<Offer> result = offers.stream()
.collect(minCollector());
List result=offers.stream()
.collect(minCollector());
是否有单行语句(使用streams或任何第三方)
图书馆)允许这样做吗
把事情分两次做,可读性会更好
1) 计算标准
类型优惠的最便宜价格:
Optional<Offer> minPriceOffer =
offers.stream()
.filter(o -> o.getType() == OfferType.STANDARD)
.min(Comparator.comparing(Offer::getPrice));
以下是两条流:
标准
报价,对其进行排序,并将其限制为1个元素(最低价格)List<Offer> result = offers.stream()
.collect(Collectors.groupingBy(Offer::getType))
.entrySet()
.stream()
.flatMap(entry -> entry.getKey() == OfferType.STANDARD ?
entry.getValue().stream()
.sorted(Comparator.comparing(Offer::getPrice))
.limit(1)
: entry.getValue().stream())
.collect(Collectors.toList());
List result=offers.stream()
.collect(收集器.groupingBy(Offer::getType))
.entrySet()
.stream()
.flatMap(entry->entry.getKey()==OfferType.STANDARD?
entry.getValue().stream()
.sorted(Comparator.comparing(Offer::getPrice))
.限额(1)
:entry.getValue().stream())
.collect(Collectors.toList());
我想过滤掉所有标准的,除了最便宜的。-你这么说是什么意思?“标准的”是指“类型字段上有价值的OfferType.standard”和“最便宜的”是指“标准报价中价格最低的”那么type=奖金如何成为你预期产出的一部分呢?@NicholasK,我不知道你是怎么理解我的描述的,但我的目的是输出所有的奖金优惠,只有一个标准优惠,价格最低,排序+限制(1)
最好是min
@Eugene我想这是与你的答案的比较。只要可能,我总是选择运行一次流。这个解决方案避免在提供的@nullpointer上运行两个流,我可以很好地使用min
,但是我需要一个流,因为这是flatMap
@ernest_k得到它的一个参数,为了.min(Comparator.comparating(Offer::getPrice)).stream()
(Java9+.min(Comparator.comparating(Offer::getPrice))而忽略了它
是你打败我的地方:)@nullpointer。。或者是一个自定义收集器,但编写它却花了一段时间,这正是我所依赖的简单for循环方法List result=new ArrayList();BigDecimal最小值=BigDecimal.0;for(Offer-Offer:offers){switch(Offer.getType()){case-STANDARD:if(Offer.getPrice().compareTo(min)<0){min=Offer.getPrice();}break;case-BONUS:default:result.add(Offer);break;}}result.add(新报价(OfferType.STANDARD,min))代码>。类似的累加器。@FedericoPeraltaSchaffner我的错误解释-删除了注释,在所有合并器运行后,将运行finisher,此时该min将被放入结果中。您注意到任何min都可能为空!(我错过了)。。。变量可以是BinaryOperator.minBy(Comparator.nullslat(Comparator.comparating(Offer::getPrice)))。应用(左、右)
,因为我们只想排除标准报价(而不是其他类型)的价格。.min(Offer::getPrice)
不起作用;您需要.min(Comparator.comparating(Offer::getPrice))
。另一方面,您可以简化第二个谓词:.filter(o->o.getType()!=OfferType.STANDARD | | o.getPrice().equals(minPriceOffer.get().getPrice())
。您不需要isPresent()
,因为当遇到OfferType.STANDARD
时,可选项不能为空。原则上,您也可以使用filter(o->o.getType()!=OfferType.STANDARD
List<Offer> offersFiltered =
offers.stream()
.filter(o -> {
if (o.getType() == OfferType.STANDARD
&& !o.getPrice().equals(minPriceOffer.get().getPrice()))
return false;
// else
return true;
}
)
.collect(toList();
List<Offer> result = offers.stream()
.collect(Collectors.groupingBy(Offer::getType))
.entrySet()
.stream()
.flatMap(entry -> entry.getKey() == OfferType.STANDARD ?
entry.getValue().stream()
.sorted(Comparator.comparing(Offer::getPrice))
.limit(1)
: entry.getValue().stream())
.collect(Collectors.toList());