113 lines
3.9 KiB
Java
113 lines
3.9 KiB
Java
package com;
|
||
|
||
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<String,Double> entry){
|
||
this.id=entry.getKey ();
|
||
this.weight=entry.getValue ()*100;
|
||
}
|
||
|
||
public String getId(){
|
||
return id;
|
||
}
|
||
public Double getWeight(){
|
||
return weight;
|
||
}
|
||
}
|