package com.mobai.demo; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.stream.Collectors; import java.util.stream.DoubleStream; /** * @ClassName demo_01 * @Description 描述 * @Author YunFei.Du * @Date 2024/5/27 14:44 */ public class Demo1 { /** * 主函数示例,展示了如何从一个HashMap中提取信息, * 计算权重总和,按权重分配特定数量的节点,并进行相应的排序和归约。 * * @param args 命令行参数(未使用) */ public static void main(String[] args) { // 初始化一个HashMap,存储节点ID及其对应的权重 HashMap< String, Double > nodeMap = new HashMap<> ( ){{ put ( "node_1",0.35 ); put ( "node_2",0.53 ); put ( "node_3",0.17 ); put ( "node_4",0.46 ); }}; // 将节点Map转换为NodeInfo对象的List List< NodeInfo > nodeInfoList = nodeMap.entrySet ( ) .stream ( ).map ( NodeInfo::new ) .toList ( ); System.out.println (nodeInfoList ); // 计算所有节点权重的总和 double sum = nodeInfoList.stream ( ) .flatMapToDouble ( nodeInfo -> DoubleStream.of ( nodeInfo.getWeight ( ) ) ) .sum ( ); System.out.println (sum ); // 根据权重总和计算每个节点的特定比例 BigDecimal spec = new BigDecimal ( 100 ).divide ( new BigDecimal ( sum ), 2, BigDecimal.ROUND_HALF_UP ); // 使用计算出的比例,为每个节点分配整数数量 Map< String, Integer > collect = nodeInfoList.stream ( ).collect ( Collectors.toMap ( NodeInfo::getId, nodeInfo -> spec.multiply ( BigDecimal.valueOf ( nodeInfo.getWeight ( ) ) ).setScale ( 0, RoundingMode.DOWN ).intValue (), (o1, o2) -> o1 ) ); System.out.println (collect ); // 计算已分配节点数量的总和 int reduce = collect.values ( ).stream ( ).reduce ( 0, Integer::sum ); System.out.println (reduce ); // 计算剩余的未分配节点数量 int free=100-reduce; // 为剩余的未分配节点分配数量 nodeInfoList.stream () .sorted ( Comparator.comparingInt ( o->o.getWeight ().intValue () ) ) .limit ( free ) .forEach ( nodeInfo -> { collect.put ( nodeInfo.getId (),collect.get ( nodeInfo.getId ())+1 ); } ); System.out.println (collect ); // 准备一个字符串数组,以存储最终的节点分配结果 String[] nodeArray = new String[100]; int intArrCursor= -1; // 将分配了数量的节点填充到字符串数组中,直到数组满或所有节点都已处理完毕 while (collect.size ()>1){ Iterator< Map.Entry< String, Integer > > specMapIterator = collect.entrySet ( ).iterator ( ); while (specMapIterator.hasNext ()){ Map.Entry< String, Integer > entry = specMapIterator.next ( ); Integer value = entry.getValue ( ); if (value>0){ nodeArray[++intArrCursor] = entry.getKey ( ); entry.setValue ( value-1 ); } if (value==0){ specMapIterator.remove (); } } } System.out.println (collect ); System.out.println (Arrays.toString ( nodeArray ) ); } } class NodeInfo{ private String id; private Double weight; public NodeInfo (String id, Double weight){ this.id=id; this.weight=weight; } public NodeInfo (Map.Entry entry){ this.id=entry.getKey (); this.weight=entry.getValue ()*100; } public String getId(){ return id; } public Double getWeight(){ return weight; } }