在复杂的HashMap中使用Usng StringJoiner

时间:2019-05-16 08:54:31

标签: java dictionary arraylist collections hashmap

我有以下地图列表:

List<Map<String,Object>> someObjectsList = new ArrayList<Map<String,Object>>();

我在每个HashMap中存储以下数据

key             value
2017-07-21      2017-07-21-07.33.28.429340
2017-07-24      2017-07-24-01.23.33.591340
2017-07-24      2017-07-24-01.23.33.492340
2017-07-21      2017-07-21-07.33.28.429540

我想遍历HashMap的列表,并检查键是否与任何HashMap值的前10个字符匹配,然后我要将这些键和值存储在以下格式。即使用遥测仪“逗号”。最终目的是将HashMap的唯一键及其相对值(如果键与任何HashMap值的前10个字符匹配)组合在新的HashMap中。

key          value
2017-07-21  2017-07-21-07.33.28.429340,2017-07-21-07.33.28.429540
2017-07-24  2017-07-24-01.23.33.591340,2017-07-24-01.23.33.492340

我正在尝试使用StringJoiner跟随以下Java代码,但未获得预期的结果。关于如何在这里构建逻辑的任何线索?

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;

public class SampleOne {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        List<Map<String, Object>> someObjectsList = new ArrayList<Map<String, Object>>();

        Map<String, Object> mapOne = new HashMap<String, Object>();
        mapOne.put("2017-07-21", "2017-07-21-07.33.28.429340");

        Map<String, Object> mapTwo = new HashMap<String, Object>();
        mapTwo.put("2017-07-24", "2017-07-24-01.23.33.591340");

        Map<String, Object> mapThree = new HashMap<String, Object>();
        mapThree.put("2017-07-24", "2017-07-24-01.23.33.492340");

        Map<String, Object> mapFour = new HashMap<String, Object>();
        mapFour.put("2017-07-21", "2017-07-21-07.33.28.429540");

        someObjectsList.add(mapOne);
        someObjectsList.add(mapTwo);
        someObjectsList.add(mapThree);
        someObjectsList.add(mapFour);

        for (Map map : someObjectsList) {
            StringJoiner sj = new StringJoiner(",");
            for (Object key : map.keySet()) {
                String value = ((String) map.get(key));
                String date = value.substring(0, Math.min(value.length(), 10));
                //System.out.println(str);
                //System.out.println(value);

                if(key.equals(date)) {
                    sj.add(value);
                    System.out.println(sj.toString());
                }
            }

        }

    }

}

输出:

2017-07-21-07.33.28.429340
2017-07-24-01.23.33.591340
2017-07-24-01.23.33.492340
2017-07-21-07.33.28.429540

4 个答案:

答案 0 :(得分:1)

在您的代码上,您在每个地图上使用不同的StringJoiner。因此,它正在创建它的新实例。

您可以将密钥保存在地图上。示例代码: (编辑:我没有删除您的StringJoiner部分。)

public static void main(String[] args) {
        // TODO Auto-generated method stub
        List<Map<String, Object>> someObjectsList = new ArrayList<Map<String, Object>>();

        Map<String, Object> mapOne = new HashMap<String, Object>();
        mapOne.put("2017-07-21", "2017-07-21-07.33.28.429340");

        Map<String, Object> mapTwo = new HashMap<String, Object>();
        mapTwo.put("2017-07-24", "2017-07-24-01.23.33.591340");

        Map<String, Object> mapThree = new HashMap<String, Object>();
        mapThree.put("2017-07-24", "2017-07-24-01.23.33.492340");

        Map<String, Object> mapFour = new HashMap<String, Object>();
        mapFour.put("2017-07-21", "2017-07-21-07.33.28.429540");

        someObjectsList.add(mapOne);
        someObjectsList.add(mapTwo);
        someObjectsList.add(mapThree);
        someObjectsList.add(mapFour);

        Map<String, Object> outputMap = new HashMap<String, Object>();

        for (Map map : someObjectsList) {
            StringJoiner sj = new StringJoiner(",");
            for (Object key : map.keySet()) {
                String value = ((String) map.get(key));
                String date = value.substring(0, Math.min(value.length(), 10));
                //System.out.println(str);
                //System.out.println(value);

                if(key.equals(date)) {
                    sj.add(value);
                    System.out.println(sj.toString());
                    if(outputMap.containsKey(key)) {
                        String str = (String) map.get(key);
                        str = str + "," + value;
                        outputMap.put((String)key, str);
                    } else {
                        outputMap.put((String)key, value);
                    }
                }
            }
        }

        for (String map : outputMap.keySet()) {
             System.out.println(map + " " + outputMap.get(map));
        }
    }

答案 1 :(得分:1)

您为什么使用Object而不是String并避免进行安全检查?也就是说,它不是“前10个字符”,而是要查看value是否以key句点开头(所有键都是10个字符)。因此,在这种情况下,您只需执行if (value.startsWith(key)) { ... }。如果stringjoiner未满,请不要忘记换行符。最后,您不需要ListMap可以一次按住多个键。一种替代方法:

//LinkedHashMap will preserve our insertion order
Map<String, String> map = new LinkedHashMap<>();
map.put("2017-07-21", "2017-07-21-07.33.28.429340");
map.put("2017-07-24", "2017-07-24-01.23.33.591340");
//note duplicates are overwritten, but no value change here
map.put("2017-07-24", "2017-07-24-01.23.33.492340");
map.put("2017-07-21", "2017-07-21-07.33.28.429540");
//  You can also use Java 8 streams for the concatenation
//  but I left it simple
List<String> matches = map.entrySet()
        .filter(e -> e.getValue().startsWith(e.getKey())
        .collect(Collectors.toList());
String concatenated = String.join("\n", matches);

如果您想生成不带流的字符串,则看起来像这样(同样,为简单起见,不使用#entrySet,但在这里效率更高):

List<String> matches = new ArrayList<>();
StringJoiner joiner = new StringJoiner("\n");
for (String key : map.keySet()) {
    String value = map.get(key);
    if (value.startsWith(key)) {
        joiner.add(value);
    }
}
//joiner#toString will give the expected result

答案 2 :(得分:1)

使用.merge函数:

Map<String, Object> finalMap = new HashMap<String, Object>();

for (Map map : someObjectsList) {
    for (Object key : map.keySet()) {
        String value = ((String) map.get(key));
        finalMap.merge((String) key, value, (k, v) -> k + "," + v);
    }
}

输出:

  

{2017-07-21 = 2017-07-21-07.33.28.429340,2017-07-21-07.33.28.429540,   2017-07-24 = 2017-07-24-01.23.33.591340,2017-07-24-01.23.33.492340}


可以通过以下一种方法实现相同的目的:

someObjectsList.stream()
               .flatMap(i -> i.entrySet().stream())
               .collect(Collectors.toMap(Entry::getKey, Entry::getValue, 
                                        (k, v) -> k + "," + v));

答案 3 :(得分:1)

您正在寻找处理List分组行为。自起,您就可以利用的优势。无论如何,您都需要一个新的Map来存储值以打印它们。 :

someObjectsList.stream()
        .flatMap(i -> i.entrySet().stream())               // flatmapping to entries
        .collect(Collectors.groupingBy(Entry::getKey))     // grouping them using the key

如果要使用for循环。在这种情况下,由于每个List项中可能会出现更多条目,因此更加困难:

final Map<String, List<Object>> map = new HashMap<>();
for (Map<String, Object> m: someObjectsList) {          // iterate List<Map>
    for (Entry<String, Object> entry: m.entrySet()) {   // iterate entries of each Map
        List<Object> list;
        final String key = entry.getKey();              // key of the entry
        final Object value = entry.getValue();          // value of the entry
        if (map.containsKey(key)) {                     // if the key exists
            list = map.get(key);                        // ... use it
        } else {
            list = new ArrayList<>();                   // ... or else create a new one
        }
        list.add(value);                                // add the new value
        map.put(key, list);                             // and add/update the entry
    }
}

在两种情况下从Map<String, List<Object>> map打印出来都会产生以下输出:

2017-07-21=[2017-07-21-07.33.28.429340, 2017-07-21-07.33.28.429540], 
2017-07-24=[2017-07-24-01.23.33.591340, 2017-07-24-01.23.33.492340]