【问题标题】:How to get subset of values for a particular key in HashMap<String, Object> initialMap = new HashMap<String, Object>()如何在 HashMap<String, Object> initialMap = new HashMap<String, Object>() 中获取特定键的值子集
【发布时间】:2016-03-18 09:46:54
【问题描述】:

我有一个

HashMap<String, Object> initialMap = new HashMap<String, Object>();

我以这种方式为键设置了字符串值,

error=[e1, e2, e3, e4, e5, e6],[e7, e8, e9, e10, e11, e12],[e13, e14 ,e15, e16, e17, e18],[e19, e20, e21, e22, e23, e24],[e25, e26, e27, e28, e29, e30], status=[s1, s2, s3, s4, s5, s6],[s7, s8 s9, s10, s11, s12],[s13, s14 ,s15, s16, s17, s18],[s19, s20, s21, s22, s23, s24],[s25, s26, s27, s28, s29, s30], data=[[d1, d2, d3, d4, d5, d6],[d7, d8, d9, d10, d11, d12],[d13, d14 ,d15, d16, d17, d18],[d19, d20, d21, d22, d23, d24],[d25, d26, d27, d28, d29, d30]], warning=[w1, w2, w3, w4, w5, w6],[w7, w8, w9, w10, w11, w12],[w13, w14 ,w15, w16, w17, w18],[w19, w20, w21, w22, w23, w24],[w25, w26, w27, w28, w29, w30]}

所以,这里有一个称为错误的键,

我们在下面有这 5 组字符串值。

[e1, e2, e3, e4, e5, e6],[e7, e8, e9, e10, e11, e12],[e13, e14 ,e15, e16, e17, e18],[e19, e20, e21, e22, e23, e24],[e25, e26, e27, e28, e29, e30].

我不需要一个键的所有这 5 个设置值,但我需要使用开始和结束限制,即每个键的值的子集。

假设我的 startLimit=2 和 endLimit=4 那么我应该只得到 2,3,4 组关键错误值,

[e7, e8, e9, e10, e11, e12],[e13, e14 ,e15, e16, e17, e18],[e19, e20, e21, e22, e23, e24]

同样需要为所有其他 3 个键重复。

我尝试过这种方式,但它总是给我一个特定键的所有值。

有什么方法可以获取 hashmap 中特定键的值子集?

这是我试过的代码,

public class MapTest {
        HashMap<String, Object> finalMap = new HashMap<String, Object>();
        int startLimit = 2;
        int endLimit = 4;

        public static void main(String[] args) {
            MapTest mm = new MapTest();
            mm.getData();
        }
        public void getData()
        {
            HashMap<String, Object> initialMap = new HashMap<String, Object>();
            initialMap.put("status","[s1, s2, s3, s4, s5, s6],[s7, s8 s9, s10, s11, s12],[s13, s14 ,s15, s16, s17, s18],[s19, s20, s21, s22, s23, s24],[s25, s26, s27, s28, s29, s30]");
            initialMap.put("data","[[d1, d2, d3, d4, d5, d6],[d7, d8, d9, d10, d11, d12],[d13, d14 ,d15, d16, d17, d18],[d19, d20, d21, d22, d23, d24],[d25, d26, d27, d28, d29, d30]]");
            initialMap.put("warning","[w1, w2, w3, w4, w5, w6],[w7, w8, w9, w10, w11, w12],[w13, w14 ,w15, w16, w17, w18],[w19, w20, w21, w22, w23, w24],[w25, w26, w27, w28, w29, w30]");
            initialMap.put("error","[e1, e2, e3, e4, e5, e6],[e7, e8, e9, e10, e11, e12],[e13, e14 ,e15, e16, e17, e18],[e19, e20, e21, e22, e23, e24],[e25, e26, e27, e28, e29, e30]");

            Set<Entry<String, Object>> entries = initialMap .entrySet();
            for (Iterator<Entry<String, Object>> i = entries.iterator(); i.hasNext(); ) {
                Entry e = (Entry) i.next();
                if(e.getKey().equals("error"))
                {   
                    Object errValue = initialMap.get(e.getKey());
                    //System.out.println("errValue" + errValue);
                    finalMap.put(e.getKey().toString(), errValue);
                }
                if(e.getKey().equals("data"))
                {   
                    Object errValue = initialMap.get(e.getKey());
                    //System.out.println("errValue" + errValue);
                    finalMap.put(e.getKey().toString(), errValue);
                }
                else if(e.getKey().equals("warning"))
                {   
                    Object errValue = initialMap.get(e.getKey());
                    //System.out.println("errValue" + errValue);
                    finalMap.put(e.getKey().toString(), errValue);
                }
                if(e.getKey().equals("status"))
                {   
                    Object errValue = initialMap.get(e.getKey());
                    //System.out.println("errValue" + errValue);
                    finalMap.put(e.getKey().toString(), errValue);
                }
            }
            if(startLimit == 2 && endLimit == 4)
                System.out.println("final map after limiting the data " + finalMap);
        } 
    }

我从上面的程序中以这种方式获取一个键的所有 5 对值,

限制数据后的最终地图

{error=[e1, e2, e3, e4, e5, e6],[e7, e8, e9, e10, e11, e12],[e13, e14 ,e15, e16, e17, e18],[e19, e20, e21, e22, e23, e24],[e25, e26, e27, e28, e29, e30], status=[s1, s2, s3, s4, s5, s6],[s7, s8 s9, s10, s11, s12],[s13, s14 ,s15, s16, s17, s18],[s19, s20, s21, s22, s23, s24],[s25, s26, s27, s28, s29, s30], data=[[d1, d2, d3, d4, d5, d6],[d7, d8, d9, d10, d11, d12],[d13, d14 ,d15, d16, d17, d18],[d19, d20, d21, d22, d23, d24],[d25, d26, d27, d28, d29, d30]], warning=[w1, w2, w3, w4, w5, w6],[w7, w8, w9, w10, w11, w12],[w13, w14 ,w15, w16, w17, w18],[w19, w20, w21, w22, w23, w24],[w25, w26, w27, w28, w29, w30]}

但是我需要这样做,因为我的限制是 2 到 4 对,

限制数据后的最终图{error=[e7, e8, e9, e10, e11, e12],[e13, e14 ,e15, e16, e17, e18],[e19, e20, e21, e22, e23, e24], status=[s7, s8 s9, s10, s11, s12],[s13, s14 ,s15, s16, s17, s18],[s19, s20, s21, s22, s23, s24], data=[[d7, d8, d9, d10, d11, d12],[d13, d14 ,d15, d16, d17, d18],[d19, d20, d21, d22, d23, d24]], warning=[w7, w8, w9, w10, w11, w12],[w13, w14 ,w15, w16, w17, w18],[w19, w20, w21, w22, w23, w24]}

谁能帮我解决这个问题?

谢谢

【问题讨论】:

    标签: java loops hashmap concurrenthashmap linkedhashmap


    【解决方案1】:

    我在您的代码中发现了 2 个大问题:

    1. startLimit 和 endLimit 不用于过滤从initialMap 提取的数据,但它们只是在它们的值上进行测试;您的代码只需将键/值从 initialMap 复制到 finalMap,然后打印 finalMap 如果两个限制设置为 2 和 4(它们只是决定是否打印的标志
    2. initialMap 中的每个键都与String(不是Object 或List)相关联,所以我看到分隔“方括号对象”的唯一方法是玩逗号......但我是不确定这是否是您的代码的目标

    建议你把map值改为List&lt;String&gt;,重新思考getData的逻辑。

    public static void main(String[] args) {
        int startLimit = 2;
        int endLimit = 4;
    
        HashMap<String, List<String>> finalMap = new HashMap<>();
        HashMap<String, List<String>> initialMap = new HashMap<>();
    
        List<String> sList = Arrays.asList("[s1, s2, s3, s4, s5, s6]", "[s7, s8, s9, s10, s11, s12]", "[s13, s14 ,s15, s16, s17, s18]", "[s19, s20, s21, s22, s23, s24]", "[s25, s26, s27, s28, s29, s30]");
        List<String> dList = Arrays.asList("[d1, d2, d3, d4, d5, d6]", "[d7, d8, d9, d10, d11, d12]", "[d13, d14 ,d15, d16, d17, d18]", "[d19, d20, d21, d22, d23, d24]", "[d25, d26, d27, d28, d29, d30]");
        List<String> wList = Arrays.asList("[w1, w2, w3, w4, w5, w6]", "[w7, w8, w9, w10, w11, w12]", "[w13, w14 ,w15, w16, w17, w18]", "[w19, w20, w21, w22, w23, w24]", "[w25, w26, w27, w28, w29, w30]");
        List<String> eList = Arrays.asList("[e1, e2, e3, e4, e5, e6]", "[e7, e8, e9, e10, e11, e12]", "[e13, e14 ,e15, e16, e17, e18]", "[e19, e20, e21, e22, e23, e24]", "[e25, e26, e27, e28, e29, e30]");
    
        initialMap.put("status", sList);
        initialMap.put("data", dList);
        initialMap.put("warning", wList);
        initialMap.put("error", eList);
    
        Iterator<Entry<String, List<String>>> i = initialMap.entrySet().iterator();
        Entry<String, List<String>> e = null;
        List<String> eValue = null;
        while (i.hasNext()) {
            e = i.next();
            eValue = e.getValue();
            finalMap.put(e.getKey(), eValue.subList(startLimit, endLimit));
        }
        System.out.println("final map after limiting the data " + finalMap);
    } 
    

    编辑:如果地图值不能为List&lt;String&gt;,您可以执行以下操作

    public static void main(String[] args) {
        int startLimit = 2;
        int endLimit = 4;
        String objectSeparator = "],";
    
        HashMap<String, String> finalMap = new HashMap<>();
        HashMap<String, String> initialMap = new HashMap<>();
    
        String sList = "[s1, s2, s3, s4, s5, s6],[s7, s8 s9, s10, s11, s12],[s13, s14 ,s15, s16, s17, s18],[s19, s20, s21, s22, s23, s24],[s25, s26, s27, s28, s29, s30]";
        String dList = "[[d1, d2, d3, d4, d5, d6],[d7, d8, d9, d10, d11, d12],[d13, d14 ,d15, d16, d17, d18],[d19, d20, d21, d22, d23, d24],[d25, d26, d27, d28, d29, d30]]";
        String wList = "[w1, w2, w3, w4, w5, w6],[w7, w8, w9, w10, w11, w12],[w13, w14 ,w15, w16, w17, w18],[w19, w20, w21, w22, w23, w24],[w25, w26, w27, w28, w29, w30]";
        String eList = "[e1, e2, e3, e4, e5, e6],[e7, e8, e9, e10, e11, e12],[e13, e14 ,e15, e16, e17, e18],[e19, e20, e21, e22, e23, e24],[e25, e26, e27, e28, e29, e30]";
    
        initialMap.put("status", sList);
        initialMap.put("data", dList);
        initialMap.put("warning", wList);
        initialMap.put("error", eList);
    
        Iterator<Entry<String, String>> it = initialMap.entrySet().iterator();
        Entry<String, String> e = null;
        String eValue = null;
        String[] splitted = null;
        while (it.hasNext()) {
            e = it.next();
            eValue = e.getValue();
    
            // Split each "square bracket object" in a separate string 
            splitted = eValue.split(objectSeparator);
    
            // Create a new string containing only objects with index between limits
            String limited = "";
            for(int idx = startLimit-1; idx <= endLimit-1; idx++)
                limited += (splitted[idx] + objectSeparator);
    
            // Remove trailing comma added inside for loop
            limited = limited.substring(0, limited.lastIndexOf(","));
    
            finalMap.put(e.getKey(), limited);
        }
        System.out.println("final map after limiting the data " + finalMap);
    } 
    

    【讨论】:

    • 如果 startLimit=2 和 endLimit =4 我需要 2,3,4 但你的算法只给出 2,4
    • 那是因为subList 排除了上限。如果可能的话,你应该调整你的限制在 [0, list size] 范围内。
    • @Macro Stramezzi 我们不能用 Object 来做吗.. 我不能把它列出来
    • @Macro Stramezzi 我们可以使用对象本身吗?
    【解决方案2】:

    注意:我假设与“数据”键关联的值与其他值具有相同的结构(没有额外的括号),如果不是这种情况,那么算法就会变得更多复杂。

    我在 JDK 6 上使用了 guava 和 commons-lang3。

    HashMap<String, Object> finalMap = Maps.newHashMap(Maps.transformValues(initialMap, new Function<Object, Object>() {
        public Object apply(Object input) {
            String inputAsString = (String) input;
            String trimmedInput = inputAsString.replaceAll("^\\[+", "").replaceAll("\\]+$", "");
            int removedBraces = (inputAsString.length() - trimmedInput.length()) / 2;
            List<String> splitInput = Lists.newArrayList(Splitter.on("],[").split(trimmedInput));
            List<String> subList = splitInput.subList(startLimit - 1, endLimit);
            return StringUtils.repeat('[', removedBraces) + Joiner.on("],[").join(subList)
            + StringUtils.repeat(']', removedBraces);
        }
    }));
    

    简而言之,这段代码创建了一个新地图,其中新地图中的每个值都是通过使用以下算法转换初始值来构建的:

    1. 去掉开头的'['和结尾的']'
    2. 用“],[”字符串分割
    3. 获取结果列表的子列表(从 startLimit - 1 到 endLimit)
    4. 使用 "],[" 将列表重新连接到一个字符串中,并添加初始的前导 '[' 和尾随 ']'

    【讨论】:

    • 如何使用一组大括号 [] 额外的数据?
    • 你的意思是如果地图中的每个值都有一个额外的集合还是只有其中一些?如果都是值,那么它是微不足道的(只需在拆分之前删除 2 个字符而不是一个字符,并在最后添加 '[[' 和 ']]')
    • 我用请求的算法和泛型类型更新了我的答案。
    猜你喜欢
    • 2020-01-08
    • 2014-07-20
    • 2016-03-10
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    相关资源
    最近更新 更多