Vip*_*pin 4 java java-8 java-stream
地图结构和数据如下
Map<String, BigDecimal>
Run Code Online (Sandbox Code Playgroud)
现在我想要在范围内对值进行分组,输出的范围为键,元素的数量为值.如下所示:
我们如何使用java流做到这一点?
你可以这样做:
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}
我找不到更好的方法来检查大小数,但你可以考虑如何改进它:)也许做一个外部方法来做那个技巧
您可以使用常规范围的解决方案,例如
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(不含)”等范围。