Java 8流“无法在静态上下文中使用它”

时间:2017-03-02 01:35:58

标签: java java-8 java-stream

我是java8 stream&的新手抱歉这个愚蠢的问题。这是我的代码,我正在尝试创建一个id&值,但我收到此错误,无法修复。任何人都可以帮助我什么是替代方案?

    public static Map<Integer, String> findIdMaxValue(){
        Map<Integer, Map<String, Integer>> attrIdAttrValueCountMap = new HashMap<>();
        Map<Integer, String> attrIdMaxValueMap = new HashMap<>(); 
                attrIdAttrValueCountMap.forEach((attrId, attrValueCountMap) -> {
                    attrValueCountMap.entrySet().stream().sorted(this::compareAttrValueCountEntry).findFirst().ifPresent(e -> {
                        attrIdMaxValueMap.put(attrId, e.getKey());
                    });
                });
    }

和排序方法

public static int compareAttrValueCountEntry(Map.Entry<String, Integer> e1, Map.Entry<String, Integer> e2) {
    int diff = e1.getValue() - e2.getValue();
    if (diff != 0) {
        return -diff;
    }
    return e1.getKey().compareTo(e2.getKey());
}

我收到此错误

"Cannot use this in a static context"

2 个答案:

答案 0 :(得分:2)

由于方法compareAttrValueCountEntry被声明为静态,

替换方法参考

this::compareAttrValueCountEntry

<Yourclass>::compareAttrValueCountEntry

答案 1 :(得分:1)

您的代码存在一些问题。虽然this::compareAttrValueCountEntry很容易 通过将其更改为ContainingClassName::compareAttrValueCountEntry进行修复,此方法是不必要的 因为有几种工厂方法,如Map.Entry.comparingByKeyMap.Entry.comparingByValueComparator.reversedComparator.thenComparing,可以合并以实现相同的目标

这可以保护您免受compareAttrValueCountEntry内的错误的影响。比较int很有吸引力 减去值,但这很容易出错,因为两个int值之间的差异并不总是如此 适合int范围,因此可能发生溢出。此外,否定撤销订单的结果是 因为价值可能是Integer.MIN_VALUE而没有正面的对应物,因此,否定它 将溢出回Integer.MIN_VALUE而不是更改符号。

您可以使用更清晰的流操作生成,而不是通过forEach循环添加到另一个地图 地图,您可以将sorted(…).findFirst()简化为min(…),这不仅更短,而且更简单 可能更便宜的操作。

把它放在一起,我们得到

Map<Integer, String> attrIdMaxValueMap =
    attrIdAttrValueCountMap.entrySet().stream()
        .filter(e -> !e.getValue().isEmpty())
        .collect(Collectors.toMap(Map.Entry::getKey,
            e -> e.getValue().entrySet().stream()
                .min(Map.Entry.<String, Integer>comparingByValue().reversed()
                        .thenComparing(Map.Entry.comparingByKey())).get().getKey()));

请注意,我在前面添加filter操作,拒绝空地图,这样可以确保始终存在 匹配元素,因此无需处理ifPresent或类似的问题。相反,Optional.get 可以无条件地被召唤。

由于此方法称为findIdMaxValue,因此可能需要通过调用max来反映该方法 在流上而不是min,这只是反转哪个比较器的问题:

Map<Integer, String> attrIdMaxValueMap =
    attrIdAttrValueCountMap.entrySet().stream()
        .filter(e -> !e.getValue().isEmpty())
        .collect(Collectors.toMap(Map.Entry::getKey,
            e -> e.getValue().entrySet().stream()
                .max(Map.Entry.<String, Integer>comparingByValue()
                       .thenComparing(Map.Entry.comparingByKey(Comparator.reverseOrder())))
                .get().getKey()));

不幸的是,这样的结构遇到了类型推断的局限性,这需要我们, 使用嵌套构造(如Map.Entry.comparingByKey(Comparator.reverseOrder())而不是。{ Map.Entry.comparingByKey().reversed())或插入显式类型,例如 Map.Entry.<String, Integer>comparingByValue()。在第二个变体中,反转第二个比较器, 我们两次点击了... ...

在这种特定情况下,创建比较器只需要一次,将其保存在变量中并在流操作中重用它:

Comparator<Map.Entry<String, Integer>> valueOrMinKey
    = Map.Entry.<String, Integer>comparingByValue()
         .thenComparing(Map.Entry.comparingByKey(Comparator.reverseOrder()));

Map<Integer, String> attrIdMaxValueMap =
    attrIdAttrValueCountMap.entrySet().stream()
        .filter(e -> !e.getValue().isEmpty())
        .collect(Collectors.toMap(Map.Entry::getKey,
            e -> e.getValue().entrySet().stream().max(valueOrMinKey).get().getKey()));