为什么过滤后映射流排序不起作用?

Why is map stream sorted after filtering not working?

我有Map<String,Integer> map。我想对地图进行按键过滤和排序,然后得到他们数量的5%,我有这样一个功能:

public List<String> getValuableSubStr(){
        List<String> result = new ArrayList<>();
        long size = map.entrySet().stream().filter(e -> e.getKey().length() ==3).count();
        map.entrySet().stream()
                      .filter(e -> e.getKey().length() ==3)
                      .sorted(Map.Entry.<String,Integer>comparingByKey().reversed())
                      .limit((size*5)/100)
                      .peek(e -> result.add(e.getKey()));
        return result;

    }

但是在调用该函数后,我得到一个空列表,虽然地图不为空并且 forEach 可以正常打印。我做错了什么?

peek 不是终端操作,因此不会导致对流求值。

使用 forEach 代替 peek

或者,更好的是,直接收集到列表中。

return map.entrySet().stream()
    .filter(e -> e.getKey().length() ==3)
    .sorted(Map.Entry.<String,Integer>comparingByKey().reversed())
    .limit((size*5)/100)
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());

实际上,因为您只处理键:

return map.keySet().stream()
    .filter(e -> e.length() ==3)
    .sorted(Comparator.reverseOrder())
    .limit((size*5)/100)
    .collect(Collectors.toList());

peek 对于调试更有用。看这里:

it's an intermediate operation and we didn't apply a terminal operation

来自 https://www.baeldung.com/java-streams-peek-api

我愿意

public List<String> getValuableSubStr(){
    List<String> result = new ArrayList<>();
    long size = map.entrySet().stream().filter(e -> e.getKey().length() ==3).count();
    return map.entrySet().stream()
                  .filter(e -> e.getKey().length() ==3)
                  .sorted(Map.Entry.<String,Integer>comparingByKey().reversed())
                  .limit((size*5)/100)
                  .map(a -> a.getKey())
                  .collect(Collectors.toList());

}