You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从TreeMap中随机获取键值对并移除后重复操作?

问题描述

我需要从TreeMap中随机获取一个键值对,通过随机生成器选中键并展示对应的值。这个TreeMap的键是字符串类型,值是double类型,比如myMap.put("CanSoupWt", 1.0)。

我是Java编程新手,写的代码比较繁琐,想要实现的逻辑是:从TreeMap里随机取出一组键值对,移除它之后,对剩下的TreeMap重复这个操作,直到达到重量限制。

以下是我尝试的代码:

package traditional_pantry_sep08_2022;

import java.util.ArrayList;
import java.util.TreeMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class Main2 {

    public static void main(String[] args) {
        // 选择优先级最高的罐头食品
        double v_Can_Soup_Wt = 0.95;
        double v_Can_Peas_Wt = 0.95;
        double v_Can_Mix_Wt = 0.95;
        double v_Can_Meat_Wt = 0.95;
        double v_Can_Corn_Wt = 0.95;
        double v_Can_Green_Wt = 0.95;
        double v_Can_Veggies_Wt = 0.95;
        double v_Can_Apple_Wt = 0.95;
        
        double v_Can_Soup_Qty = 0;
        double v_Can_Peas_Qty = 0;
        double v_Can_Mix_Qty = 0; 
        double v_Can_Meat_Qty = 0;
        double v_Can_Corn_Qty = 0;
        double v_Can_Green_Qty = 0;
        double v_Can_Veggies_Qty = 0;
        double v_Can_Apple_Qty = 0;
                
        double household = 2;
        double v_Can_Tot_Wt = 0;

        // 根据家庭人数设置罐头总重量上限
        double v_Can_Tot_MaxWt = 14 + (4 * (household -1));

        // 根据家庭人数设置每种罐头的最大数量
        double v_Can_Soup_MaxQty = 5 + (2 * (household - 1));
        double v_Can_Peas_MaxQty = 5 + (2 * (household - 1));
        double v_Can_Mix_MaxQty = 5 + (2 * (household - 1));
        double v_Can_Meat_MaxQty = 5 + (2 * (household - 1));
        double v_Can_Corn_MaxQty = 5 + (2 * (household - 1));
        double v_Can_Green_MaxQty = 5 + (2 * (household - 1));
        double v_Can_Veggies_MaxQty = 5 + (2 * (household - 1));
        double v_Can_Apple_MaxQty = 5 + (2 * (household - 1));

        // 随机选择罐头直到达到重量上限
        // 将罐头重量存入TreeMap
        TreeMap<String, Double> canall = new TreeMap<String, Double>();
        canall.put("CanSoupWt", v_Can_Soup_Wt);
        canall.put("CanPeasWt", v_Can_Peas_Wt);
        canall.put("CanMixWt", v_Can_Mix_Wt);
        canall.put("CanMeatWt", v_Can_Meat_Wt);
        canall.put("CanCornWt", v_Can_Corn_Wt);
        canall.put("CanGreenWt", v_Can_Green_Wt);
        canall.put("CanVeggiesWt", v_Can_Veggies_Wt);
        canall.put("CanAppleWt", v_Can_Apple_Wt);
        
        // 打印TreeMap
        System.out.println("The TreeMap is : " + canall);
            
        // 从TreeMap中随机选择一个罐头
        do {        
            Object[] crunchifyKeys = canall.keySet().toArray();
            Object key = crunchifyKeys[new Random().nextInt(crunchifyKeys.length)];
            System.out.println("************ Random Value ************\n" + key + " :: " + canall.get(key));
            List<Map.Entry<String, Double>> list = new ArrayList<Map.Entry<String, Double>>(canall.entrySet()); 
            System.out.println("The TreeMap is : " + canall);       
            
            // 选取最大数量的罐头
            if (key == "CanSoupWt") {
                do {
                    v_Can_Soup_Qty++;
                    v_Can_Tot_Wt = v_Can_Tot_Wt + (v_Can_Soup_Wt * v_Can_Soup_Qty);
                }           
                while (v_Can_Soup_Qty < v_Can_Soup_MaxQty /*&& v_Can_Tot_Wt < v_Can_Tot_MaxWt*/);
                if (v_Can_Tot_Wt > v_Can_Tot_MaxWt) {
                    v_Can_Soup_Qty--;
                }       
                canall.remove("CanSoupWt"); // 移除已选项目
            }   
            else if (key == "CanPeasWt") {
                do {
                    v_Can_Peas_Qty++;
                    v_Can_Tot_Wt = v_Can_Tot_Wt + (v_Can_Peas_Wt * v_Can_Peas_Qty); 
                }           
                while (v_Can_Peas_Qty < v_Can_Peas_MaxQty /*&& v_Can_Tot_Wt < v_Can_Tot_MaxWt*/);
                if (v_Can_Tot_Wt > v_Can_Tot_MaxWt) {
                    v_Can_Peas_Qty--;
                }
                canall.remove("CanPeasWt"); // 移除已选项目
            }   
            else if (key == "CanMixWt") {
                do {
                    v_Can_Mix_Qty++;
                    v_Can_Tot_Wt = v_Can_Tot_Wt + (v_Can_Mix_Wt * v_Can_Mix_Qty);
                }           
                while (v_Can_Mix_Qty < v_Can_Mix_MaxQty /*&& v_Can_Tot_Wt < v_Can_Tot_MaxWt*/);
                if (v_Can_Tot_Wt > v_Can_Tot_MaxWt) {
                    v_Can_Mix_Qty--;
                }
                canall.remove("CanMixWt"); // 移除已选项目
            }                       
            else if (key == "CanMeatWt") {
                do {
                    v_Can_Meat_Qty++;
                    v_Can_Tot_Wt = v_Can_Tot_Wt + (v_Can_Meat_Wt * v_Can_Meat_Qty);
                }           
                while ( v_Can_Meat_Wt < v_Can_Meat_MaxQty /*&& v_Can_Tot_Wt < v_Can_Tot_MaxWt*/);
                if (v_Can_Tot_Wt > v_Can_Tot_MaxWt) {
                    v_Can_Meat_Qty--;
                }   
                canall.remove("CanMeatWt"); // 移除已选项目          
            }
            else if (key == "CanCornWt") {
                do {
                    v_Can_Corn_Qty++;
                    v_Can_Tot_Wt = v_Can_Tot_Wt + (v_Can_Corn_Wt * v_Can_Corn_Qty);
                }           
                while (v_Can_Corn_Wt < v_Can_Corn_MaxQty /*&& v_Can_Tot_Wt < v_Can_Tot_MaxWt*/);
                if (v_Can_Tot_Wt > v_Can_Tot_MaxWt) {
                    v_Can_Corn_Qty--;
                }   
                canall.remove("CanCornWt"); // 移除已选项目
            }
            else if (key == "CanGreenWt") {
                do {
                    v_Can_Green_Qty++;
                    v_Can_Tot_Wt = v_Can_Tot_Wt + (v_Can_Green_Wt * v_Can_Green_Qty);
                }           
                while (v_Can_Green_Wt < v_Can_Green_MaxQty /*&& v_Can_Tot_Wt < v_Can_Tot_MaxWt*/);
                if (v_Can_Tot_Wt > v_Can_Tot_MaxWt) {
                    v_Can_Green_Qty--;
                }   
                canall.remove("CanGreenWt"); // 移除已选项目 
            }
            else if (key == "CanVeggiesWt") {
                do {
                    v_Can_Veggies_Qty++;
                    v_Can_Tot_Wt = v_Can_Tot_Wt + (v_Can_Veggies_Wt * v_Can_Veggies_Qty);
                }           
                while (v_Can_Veggies_Wt < v_Can_Veggies_MaxQty /*&& v_Can_Tot_Wt < v_Can_Tot_MaxWt*/);
                if (v_Can_Tot_Wt > v_Can_Tot_MaxWt) {
                    v_Can_Veggies_Qty--;
                }   
                canall.remove("CanVeggiesWt"); // 移除已选项目           
            }       
            else if (key == "CanAppleWt") {
                do {
                    v_Can_Apple_Qty++;
                    v_Can_Tot_Wt = v_Can_Tot_Wt + (v_Can_Apple_Wt * v_Can_Apple_Qty);
                }           
                while (v_Can_Apple_Wt < v_Can_Apple_MaxQty /*&& v_Can_Tot_Wt < v_Can_Tot_MaxWt*/);
                if (v_Can_Tot_Wt > v_Can_Tot_MaxWt) {
                    v_Can_Apple_Qty--;
                }   
                canall.remove("CanAppleWt"); // 移除已选项目         
            }
            v_Can_Tot_Wt = (v_Can_Soup_Wt * v_Can_Soup_Qty) + (v_Can_Peas_Wt * v_Can_Peas_Qty) 
                + (v_Can_Mix_Wt * v_Can_Mix_Qty) + (v_Can_Meat_Wt * v_Can_Meat_Qty) 
                + (v_Can_Corn_Wt * v_Can_Corn_Qty)+ (v_Can_Green_Wt * v_Can_Green_Qty) 
                + (v_Can_Veggies_Wt * v_Can_Veggies_Qty) + (v_Can_Apple_Wt * v_Can_Apple_Qty);
        }
        while (v_Can_Tot_Wt < v_Can_Tot_MaxWt);
        
        System.out.println("Household Members: " +household);
        System.out.println("Can Soup Qty: " +v_Can_Soup_Qty);
        System.out.println("Can Peas Qty: " +v_Can_Peas_Qty);
        System.out.println("Can Mix Beans Qty: " +v_Can_Mix_Qty);
        System.out.println("Can Meat Qty: " +v_Can_Meat_Qty);
        System.out.println("Can Corn Qty: " +v_Can_Corn_Qty);
        System.out.println("Can Green Qty: " +v_Can_Green_Qty);
        System.out.println("Can Veggies Qty: " +v_Can_Veggies_Qty);
        System.out.println("Can Apple Qty: " +v_Can_Apple_Qty);
        System.out.println("Can Food Total Weight: " +v_Can_Tot_Wt);
        System.out.println("Can Food Maximum Weight: " +v_Can_Tot_MaxWt);
        // 打印TreeMap
        System.out.println("The TreeMap is : " + canall);
    }       
}
关键问题与优化方案

1. 字符串比较错误

原代码用key == "CanSoupWt"比较字符串,Java中==比较的是对象引用地址,不是内容,必须用"CanSoupWt".equals(key)才能正确判断字符串相等,否则会出现逻辑失效的问题。

2. 重复代码冗余

大量重复的if-else逻辑可以用Map存储罐头的数量和最大值,避免冗余的循环和判断,大幅简化代码。

3. Random对象复用

每次循环新建Random对象既浪费资源,还会影响随机性,建议提前创建一个全局的Random实例重复使用。

4. 重量计算逻辑错误

原代码内部do-while循环的重量计算有误:v_Can_Tot_Wt = v_Can_Tot_Wt + (v_Can_Soup_Wt * v_Can_Soup_Qty)会重复累加之前的数量,正确的应该是每次加单个罐头的重量:v_Can_Tot_Wt += v_Can_Soup_Wt。

5. 随机访问效率优化

每次从TreeMap的keySet转数组效率较低,可以提前把键存入List,直接通过随机索引访问,移除时同时操作List和TreeMap。

优化后的代码示例
package traditional_pantry_sep08_2022;

import java.util.*;

public class Main2 {
    public static void main(String[] args) {
        // 罐头重量配置
        Map<String, Double> canWeights = new HashMap<>();
        canWeights.put("CanSoup", 0.95);
        canWeights.put("CanPeas", 0.95);
        canWeights.put("CanMix", 0.95);
        canWeights.put("CanMeat", 0.95);
        canWeights.put("CanCorn", 0.95);
        canWeights.put("CanGreen", 0.95);
        canWeights.put("CanVeggies", 0.95);
        canWeights.put("CanApple", 0.95);

        // 存储每种罐头的数量
        Map<String, Integer> canQuantities = new HashMap<>();
        for (String canType : canWeights.keySet()) {
            canQuantities.put(canType, 0);
        }

        double household = 2;
        double totalWeight = 0;
        double maxTotalWeight = 14 + (4 * (household - 1));
        int maxPerCan = 5 + (2 * (int)(household - 1));

        // 初始化可选择的罐头列表
        List<String> availableCans = new ArrayList<>(canWeights.keySet());
        Random random = new Random();

        // 随机选择直到达到重量上限或无罐头可选
        while (totalWeight < maxTotalWeight && !availableCans.isEmpty()) {
            // 随机选一个罐头类型
            int randomIndex = random.nextInt(availableCans.size());
            String selectedCan = availableCans.get(randomIndex);
            double weightPerCan = canWeights.get(selectedCan);
            System.out.printf("************ 随机选中 ************\n%s :: %.2f\n", selectedCan, weightPerCan);

            // 计算能加的最大数量
            int currentQty = canQuantities.get(selectedCan);
            int addQty = 0;
            while (currentQty + addQty < maxPerCan) {
                double newWeight = totalWeight + weightPerCan * (addQty + 1);
                if (newWeight > maxTotalWeight) {
                    break;
                }
                addQty++;
            }

            // 更新数量和总重量
            canQuantities.put(selectedCan, currentQty + addQty);
            totalWeight += weightPerCan * addQty;

            // 移除已选罐头
            availableCans.remove(randomIndex);
            System.out.println("当前总重量: " + totalWeight);
        }

        // 输出结果
        System.out.println("\n家庭人数: " + household);
        for (Map.Entry<String, Integer> entry : canQuantities.entrySet()) {
            System.out.printf("%s 数量: %d\n", entry.getKey(), entry.getValue());
        }
        System.out.println("罐头总重量: " + totalWeight);
        System.out.println("罐头最大重量限制: " + maxTotalWeight);
    }
}

内容的提问来源于stack exchange,提问作者Ben Morrow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 17:20:36