2017-03-02 78 views
0

我是java8新手流&对于这个愚蠢的问题感到抱歉。这里是我的代码,我试图创建一个ID为&值的地图,但我得到这个错误,无法修复。任何人都可以帮助我选择什么?Java 8流“不能在静态上下文中使用它”

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

尝试使用实际的类名称而不是'this'。 – VHS

+0

我明白了,那么解决方案是什么?我尝试迭代地图并尝试对它进行排序attrValueCountMap.entrySet()。stream()。sorted(this :: compareAttrValueCountEntry) – Sthita

回答

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,有可能是反映通过调用流,而不是minmax ,至极只有一个问题,其中比较逆转的愿望:

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())); 
2

由于compareAttrValueCountEntry声明为static方法,

替代方法参考

this::compareAttrValueCountEntry

<Yourclass>::compareAttrValueCountEntry

+0

我找到了更好的方法http://stackoverflow.com/questions/29567575/sort-map逐值使用的Java-8 – Sthita