【问题标题】:How can I get keys in mapA as keys in mapB is a substring of key in mapA?如何获取 mapA 中的键,因为 mapB 中的键是 mapA 中键的子字符串?
【发布时间】:2021-12-22 19:09:00
【问题描述】:

我这里有两张地图:

地图A

Map<String, String> mapA = new HashMap<>();
mapA.put("aaa|111|osdf", "value1");
mapA.put("bbb|222|dfsf", "value2");
...

地图B

Map<String, String> mapB = new HashMap<>();
mapB.put("aaa", "valueM");
mapB.put("bbb", "valueN");
...

如果mapB中的键是mapA中键的子字符串,现在我想获取mapA中的键,就像:

mapB.forEach((key, value) -> {
  if (mapA.containsKey(key)) {
     // This is not what I want, because key in mapB is substring of key in mapA.
     // nested loop is not suggested here.

 ​ }

})

输出

aaa|111|osdf
bbb|222|dfsf

如何获取 mapA 中的键,因为 mapB 中的键是 mapA 中键的子字符串?

【问题讨论】:

  • 根据您的示例,mapA 中的键的第一部分,如“aaa”或“bbb”(第一个“|”之前的部分)可以在 mapB 中作为键。这个假设正确吗?
  • 正确,但出于某种原因,应该遍历mapB
  • 对于 mapA,我们可以使用 Map 代替 Map 吗?如果是,那么在自定义类中我们可以在第一个管道之前修改 equals 和 hashCode 以使用“字符串”?

标签: java search hashmap substring


【解决方案1】:

这应该可以工作

 mapB.forEach((k, v) -> {
            String key = mapA.entrySet().stream()
                    .filter(entry -> entry.getKey().contains(k))
                    .findFirst()
                    .get()
                    .getKey();
            System.out.println(key);
        });

【讨论】:

    【解决方案2】:

    containsKey(Object key) 将检查此映射是否包含键 k 的映射,使得 (key==null ? k==null : key.equals(k)) 。但是,在您的情况下, aaa|111|osdfbbb|222|dfsf 被视为单键。

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    public class MapMain {
    
        public static void main(String[] args) {
    
            Map<String, String> mapA = new HashMap<>();
            mapA.put("aaa|111|osdf", "value1");
            mapA.put("bbb|222|dfsf", "value2");
    
            Map<String, String> mapB = new HashMap<>();
            mapB.put("aaa", "valueM");
            mapB.put("bbb", "valueN");
    
            mapB.forEach((k, v) -> {
                Set<String> mapAKeySet = mapA.keySet();
                mapAKeySet.stream().filter(key -> key.contains(k)).forEach(System.out::println);
            });
        }
    
    }
    

    【讨论】:

    • 感谢您的回复。我知道 containsKey 不应该工作。我只是要求解决方案以在 mapA 中获取该单个键。
    • @zhwlx22 我更新了我的代码检查。
    • 我认为这是一个嵌套循环解决方案?
    【解决方案3】:

    试试这个。

    public static void main(String[] args) {
        Map<String, String> mapA = new HashMap<>();
        mapA.put("aaa|111|osdf", "value1");
        mapA.put("bbb|222|dfsf", "value2");
    
        Map<String, String> mapB = new HashMap<>();
        mapB.put("aaa", "valueM");
        mapB.put("bbb", "valueN");
        
        for (String aKey : mapA.keySet())
            for (String bKey : mapB.keySet())
                if (aKey.contains(bKey)) {
                    System.out.println(aKey);
                    break;
                }
    }
    

    输出:

    aaa|111|osdf
    bbb|222|dfsf
    

    或者

        mapA.keySet().stream()
            .filter(aKey -> mapB.keySet().stream()
                .anyMatch(bKey -> aKey.contains(bKey)))
            .forEach(System.out::println);
    

    【讨论】:

      【解决方案4】:

      您可以将比较块更改为以下内容:

      mapB.forEach( ( key, value ) -> {
          mapA.keySet().forEach( k -> { if( k.contains( key ) ) System.out.println( k ); } );
      } );
      

      您可以将if 条件更改为startsWith()String 提供并更好地满足您的需求的其他检查。

      可能多次打印一个键,具体取决于两个映射中的实际键。因此,您可以不打印,而是在 if 块内的 Set 中收集匹配的键,然后再打印。


      使用自定义地图实现

      这只确保循环转移到Map 实现中。但是,不能避免循环。我很想看到一种不使用循环键的技术。

      public static void main( String[] args ){
          class CustomHashMap extends HashMap<String, String>{
              /* This method will find the matching keys. May be changed to return List<String>. */
              public String getStartingKey( String key ) {
                  if( key == null || !( key instanceof String ) ) return null;
                  for( String k : keySet() ) if( k.startsWith( key.toString() ) ) return k;
                  return null;
              }
          };
          
          CustomHashMap mapA = new CustomHashMap();
          
          mapA.put( "aaa|111|osdf", "value1" );
          mapA.put( "bbb|222|dfsf", "value2" );
          mapA.put( "ccc|222|dfsf", "value2" );
      
          Map<String, String> mapB = new HashMap<>();
          mapB.put( "aaa", "valueM" );
          mapB.put( "bbb", "valueN" );
      
          mapB.forEach( ( key, value ) -> {
              System.out.println( mapA.getStartingKey( key ) );
          } );
      }
      

      【讨论】:

      • 对不起,这是一个嵌套循环解决方案,这不是我需要的。谢谢。
      • 循环只能委托给其他地方,我认为仅此而已。您是否可以使用 HashMap 以外的其他 Map 实现?
      • 有不同Map的建议吗?
      • 使用自定义地图发布编辑
      猜你喜欢
      • 2019-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-24
      • 2015-03-24
      • 2016-05-24
      相关资源
      最近更新 更多