Java-8使用特定范围内的值获取计数

jav*_*ict 4 java collections java-8 java-stream

我有产品列表,想查找特定成本范围内的产品数量,例如,如果productList有10个产品的成本在1-10之间,50在11-100之间以及100在101-1000之间,那么它应该返回一个映射跟随,

“ 1-10”:10“ 11-100”:50“ 101:1000”:100

  class Product {
        long id;
        long cost;
        String name;
        //getters setters
    }  
Run Code Online (Sandbox Code Playgroud)

我尝试了很多事情,但是没有用,列出productList = getProducts();

productList.stream().collect(Collectors.toMap(//logic to get map));
Run Code Online (Sandbox Code Playgroud)

非常感谢您的帮助。

Cod*_*ode 5

您可以如下创建一个Functionfor范围并使用Collectors.groupingBy

Map<String, Long> countByCost = productList.stream()
                .collect(Collectors.groupingBy(costRange, TreeMap::new, Collectors.counting()));

Function<Product, String> costRange = ele -> {
        if(ele.cost >= 1 && ele.cost < 11)
            return "1-10";
        if(ele.cost >= 11 && ele.cost < 101)
            return "11-100";
        if(ele.cost >= 101 && ele.cost < 1001)
            return "101-1000";
        return "others";
 };
Run Code Online (Sandbox Code Playgroud)

更新: 霍尔格(Holger)建议在成本范围内使用更精美的功能,

Function<Product, String> costRange = ele -> {
 if(ele.cost < 1) return "others"; 
long i = ele.cost == 1? 1: (long)Math.pow(10, Math.floor(Math.log10(ele.cost-1))); 
return (i|1)+"-"+(i*10); };
Run Code Online (Sandbox Code Playgroud)

  • 不要“返回null”,而是将它们归为“其他”。 (3认同)
  • 在这里使用`TreeMap`是没有意义的,因为它将按字典顺序而不是数字顺序对键进行排序。此外,必须在使用前定义“ costRange”。代替`if`阶梯,可以使用诸如`Function &lt;Product,String&gt; costRange = ele-&gt; {if(ele.cost &lt;1)return“ others ;; 我长= ele.cost == 1吗?1:(long)Math.pow(10,Math.floor(Math.log10(ele.cost-1))); 返回(i | 1)+“-” +(i * 10); };` (2认同)