java8 filter 取反,Java 8流“不能在静态上下文中使用它".

I am new to java8 stream & sorry about the stupid question . Here is my code which i am trying to create a map of id & value, but i am getting this error, not able to fix. Can anyone help me what is the alternative?

public static Map findIdMaxValue(){

Map> attrIdAttrValueCountMap = new HashMap<>();

Map attrIdMaxValueMap = new HashMap<>();

attrIdAttrValueCountMap.forEach((attrId, attrValueCountMap) -> {

attrValueCountMap.entrySet().stream().sorted(this::compareAttrValueCountEntry).findFirst().ifPresent(e -> {

attrIdMaxValueMap.put(attrId, e.getKey());

});

});

}

and sorting method

public static int compareAttrValueCountEntry(Map.Entry e1, Map.Entry e2) {

int diff = e1.getValue() - e2.getValue();

if (diff != 0) {

return -diff;

}

return e1.getKey().compareTo(e2.getKey());

}

I am getting this error

"Cannot use this in a static context"

解决方案

There are several issues with your code. While this::compareAttrValueCountEntry would be easy to

fix by changing it to ContainingClassName::compareAttrValueCountEntry, this method is unnecessary

as there are several factory methods like Map.Entry.comparingByKey, Map.Entry.comparingByValue,

Comparator.reversed and Comparator.thenComparing, which can be combined to achieve the same goal

This guards you from the errors made within compareAttrValueCountEntry. It’s tempting to compare int

values by subtracting, but this is error prone as the difference between two int values doesn’t always

fit into the int range, so overflows can occur. Also, negating the result for reversing the order is

broken, as the value might be Integer.MIN_VALUE, which has no positive counterpart, hence, negating it

will overflow back to Integer.MIN_VALUE instead of changing the sign.

Instead of looping via forEach to add to another map, you may use a cleaner stream operation producing

the map and you can simplify sorted(…).findFirst() to min(…) which in not only shorter, but a

potentially cheaper operation.

Putting it together, we get

Map attrIdMaxValueMap =

attrIdAttrValueCountMap.entrySet().stream()

.filter(e -> !e.getValue().isEmpty())

.collect(Collectors.toMap(Map.Entry::getKey,

e -> e.getValue().entrySet().stream()

.min(Map.Entry.comparingByValue().reversed()

.thenComparing(Map.Entry.comparingByKey())).get().getKey()));

Note that I prepended a filter operation rejecting empty maps, which ensures that there will always be

a matching element, so there is no need to deal with ifPresent or such alike. Instead, Optional.get

can be called unconditionally.

Since this method is called findIdMaxValue, there might be a desire to reflect that by calling max

on the Stream instead of min, wich is only a matter of which comparator to reverse:

Map attrIdMaxValueMap =

attrIdAttrValueCountMap.entrySet().stream()

.filter(e -> !e.getValue().isEmpty())

.collect(Collectors.toMap(Map.Entry::getKey,

e -> e.getValue().entrySet().stream()

.max(Map.Entry.comparingByValue()

.thenComparing(Map.Entry.comparingByKey(Comparator.reverseOrder())))

.get().getKey()));

Unfortunately, such constructs hit the limitations of the type inference, which requires us to either,

use nested constructs (like Map.Entry.comparingByKey(Comparator.reverseOrder()) instead of

Map.Entry.comparingByKey().reversed()) or to insert explicit types, like with

Map.Entry.comparingByValue(). In the second variant, reversing the second comparator,

we are hitting the litimation twice…

In this specific case, there might be a point in creating the comparator only once, keeping it in a variable and reuse it within the stream operation:

Comparator> valueOrMinKey

= Map.Entry.comparingByValue()

.thenComparing(Map.Entry.comparingByKey(Comparator.reverseOrder()));

Map attrIdMaxValueMap =

attrIdAttrValueCountMap.entrySet().stream()

.filter(e -> !e.getValue().isEmpty())

.collect(Collectors.toMap(Map.Entry::getKey,

e -> e.getValue().entrySet().stream().max(valueOrMinKey).get().getKey()));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值