Java 8流“不能在静态上下文中使用它". [英] Java 8 stream "Cannot use this in a static context"

查看:68
本文介绍了Java 8流“不能在静态上下文中使用它".的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是java8流&的新手.对这个愚蠢的问题感到抱歉.这是我正在尝试创建id&的映射的代码.值,但我收到此错误,无法修复.谁能帮我替代方法?

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<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"

推荐答案

您的代码有几个问题.虽然this::compareAttrValueCountEntry很容易 通过将其更改为ContainingClassName::compareAttrValueCountEntry进行修复,则无需使用此方法 因为有几种工厂方法,例如Map.Entry.comparingByKeyMap.Entry.comparingByValueComparator.reversedComparator.thenComparing,可以组合使用以实现相同的目标

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

这可以防止您在compareAttrValueCountEntry中犯的错误.比较int 值相减,但这很容易出错,因为两个int值之间的差并不总是 适合int范围,因此可能发生溢出.此外,求反的结果取反是 损坏,因为该值可能是Integer.MIN_VALUE,没有正值,因此取反 将溢出回到Integer.MIN_VALUE而不是更改符号.

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.

您可以使用更简洁的流操作来生成

而不是通过forEach循环添加到另一张地图 在地图上,您可以将sorted(…).findFirst()简化为min(…),不仅可以将其缩短,而且可以 运营成本可能会更低.

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<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 可以无条件调用.

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.

由于此方法称为findIdMaxValue,因此可能希望通过调用max来反映这一点. 在Stream上而不是min上,这仅是要反转的比较器的问题:

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<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().在第二个变体中,反转第二个比较器, 我们要两次提起诉讼...

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.<String, Integer>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<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()));

这篇关于Java 8流“不能在静态上下文中使用它".的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆