【问题标题】:Usng StringJoiner in complex HashMaps在复杂的 HashMap 中使用 StringJoiner
【发布时间】:2019-10-03 11:57:27
【问题描述】:

我有一个地图列表如下:

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

我想遍历HashMaps 的列表并检查键是否与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

【问题讨论】:

    标签: java dictionary arraylist collections hashmap


    【解决方案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));
            }
        }
    

    【讨论】:

      【解决方案2】:

      您有什么理由使用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
      

      【讨论】:

      • 谢谢!加一个答案。
      【解决方案3】:

      利用.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));
      

      【讨论】:

        【解决方案4】:

        您正在寻找处理List分组 行为。由于,您可以使用 的优势。在任何情况下,您都需要一个新的Map 来存储这些值以便打印它们。 :

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

        如果您想使用 for 循环。在这种情况下更难,因为每个列表项中可能会出现更多条目:

        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&lt;String, List&lt;Object&gt;&gt; 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]
        

        【讨论】:

        • 感谢您的帮助。解决方案非常有趣。加一个。
        猜你喜欢
        • 2021-10-27
        • 1970-01-01
        • 2012-03-01
        • 2013-09-21
        • 2017-09-12
        • 2016-02-23
        • 1970-01-01
        • 1970-01-01
        • 2021-10-25
        相关资源
        最近更新 更多