查找地图对象范围内的元素数量

Vip*_*pin 4 java java-8 java-stream

地图结构和数据如下

Map<String, BigDecimal>
Run Code Online (Sandbox Code Playgroud)
  • A,12
  • B,23
  • C,67
  • D,99

现在我想要在范围内对值进行分组,输出的范围为键,元素的数量为值.如下所示:

  • 0-25,2
  • 26-50,0
  • 51-75,1
  • 76-100,1

我们如何使用java流做到这一点?

Ves*_*dov 6

你可以这样做:

public class MainClass {
    public static void main(String[] args) {
        Map<String, BigDecimal> aMap=new HashMap<>();

        aMap.put("A",new BigDecimal(12));
        aMap.put("B",new BigDecimal(23));
        aMap.put("C",new BigDecimal(67));
        aMap.put("D",new BigDecimal(99));
         Map<String, Long> o =  aMap.entrySet().stream().collect(Collectors.groupingBy( a ->{
             //Do the logic here to return the group by function
             if(a.getValue().compareTo(new BigDecimal(0))>0 &&
                     a.getValue().compareTo(new BigDecimal(25))<0)
                 return "0-25";

             if(a.getValue().compareTo(new BigDecimal(26))>0 &&
                     a.getValue().compareTo(new BigDecimal(50))<0)
                 return "26-50";

             if(a.getValue().compareTo(new BigDecimal(51))>0 &&
                     a.getValue().compareTo(new BigDecimal(75))<0)
                 return "51-75";
             if(a.getValue().compareTo(new BigDecimal(76))>0 &&
                     a.getValue().compareTo(new BigDecimal(100))<0)
                 return "76-100";

             return "not-found";
         }, Collectors.counting()));

         System.out.print("Result="+o);


    }

}
Run Code Online (Sandbox Code Playgroud)

结果是:结果= {0-25 = 2,761-100 = 1,51-75 = 1}

我找不到更好的方法来检查大小数,但你可以考虑如何改进它:)也许做一个外部方法来做那个技巧


Hol*_*ger 5

您可以使用常规范围的解决方案,例如

BigDecimal range = BigDecimal.valueOf(25);
inputMap.values().stream()
        .collect(Collectors.groupingBy(
            bd -> bd.subtract(BigDecimal.ONE).divide(range, 0, RoundingMode.DOWN),
            TreeMap::new, Collectors.counting()))
        .forEach((group,count) -> {
            group = group.multiply(range);
            System.out.printf("%3.0f - %3.0f: %s%n",
                              group.add(BigDecimal.ONE), group.add(range), count);
        });
Run Code Online (Sandbox Code Playgroud)

这将打印:

BigDecimal range = BigDecimal.valueOf(25);
inputMap.values().stream()
        .collect(Collectors.groupingBy(
            bd -> bd.subtract(BigDecimal.ONE).divide(range, 0, RoundingMode.DOWN),
            TreeMap::new, Collectors.counting()))
        .forEach((group,count) -> {
            group = group.multiply(range);
            System.out.printf("%3.0f - %3.0f: %s%n",
                              group.add(BigDecimal.ONE), group.add(range), count);
        });
Run Code Online (Sandbox Code Playgroud)

(不使用不规则范围0 - 25

或具有明确范围的解决方案:

TreeMap<BigDecimal,String> ranges = new TreeMap<>();
ranges.put(BigDecimal.ZERO,        " 0 - 25");
ranges.put(BigDecimal.valueOf(26), "26 - 50");
ranges.put(BigDecimal.valueOf(51), "51 - 75");
ranges.put(BigDecimal.valueOf(76), "76 - 99");
ranges.put(BigDecimal.valueOf(100),">= 100 ");

inputMap.values().stream()
        .collect(Collectors.groupingBy(
            bd -> ranges.floorEntry(bd).getValue(), TreeMap::new, Collectors.counting()))
        .forEach((group,count) -> System.out.printf("%s: %s%n", group, count));
Run Code Online (Sandbox Code Playgroud)
  1 -  25: 2
 51 -  75: 1
 76 - 100: 1
Run Code Online (Sandbox Code Playgroud)

这也可以扩展到打印不存在的范围:

Map<BigDecimal, Long> groupToCount = inputMap.values().stream()
    .collect(Collectors.groupingBy(bd -> ranges.floorKey(bd), Collectors.counting()));
ranges.forEach((k, g) -> System.out.println(g+": "+groupToCount.getOrDefault(k, 0L)));
Run Code Online (Sandbox Code Playgroud)
TreeMap<BigDecimal,String> ranges = new TreeMap<>();
ranges.put(BigDecimal.ZERO,        " 0 - 25");
ranges.put(BigDecimal.valueOf(26), "26 - 50");
ranges.put(BigDecimal.valueOf(51), "51 - 75");
ranges.put(BigDecimal.valueOf(76), "76 - 99");
ranges.put(BigDecimal.valueOf(100),">= 100 ");

inputMap.values().stream()
        .collect(Collectors.groupingBy(
            bd -> ranges.floorEntry(bd).getValue(), TreeMap::new, Collectors.counting()))
        .forEach((group,count) -> System.out.printf("%s: %s%n", group, count));
Run Code Online (Sandbox Code Playgroud)

但要注意,把数值为范围,例如像“0 - 25”和“26 - 50”才有意义,如果我们谈论的整数,25和26之间排除值,提高为什么你正在使用的问题BigDecimal,而不是的BigInteger。对于十进制数,您通常会使用“0(含)- 25(不含)”和“25(含)- 50(不含)”等范围。