在N个哈希表

时间:2016-12-19 12:19:15

标签: java hashmap

我有一个包含N个hastst表的哈希表:

Map<Integer,Map<String,Double>

我需要创建一个包含内部地图所有键的列表:

----------------
|     | a    2 |
| 100 | b    1 |    
|     | c    2 |
----------------
|     | a    2 |
| 101 | d    2 |     
---------------- 
|     | a    2 |
| 102 | b    1 |    
|     | e    2 |
----------------

list = {a,b,c,d,e}

这是我目前的代码:

Set<String> keys= new HashSet<>();
    map1.entrySet().forEach(e -> {
        keys.addAll(e.getValue().keySet());
    });

map1包含数千个条目。

这是最佳方法吗?谁知道更快的方式?

3 个答案:

答案 0 :(得分:3)

您可以尝试使用以下代码:

Map<String, Double> innerMap = new HashMap<>();
innerMap.put("a", 2d);
innerMap.put("b", 2d);
innerMap.put("c", 2d);

Map<String, Double> innerMap2 = new HashMap<>();
innerMap2.put("a", 2d);
innerMap2.put("d", 2d);
innerMap2.put("e", 2d);

Map<Integer, Map<String, Double>> map = new HashMap<>();
map.put(100, innerMap);
map.put(101, innerMap2);

Set<String> collect = map.values()
                         .stream()
                         .parallel()
                         .map(Map::keySet)
                         .flatMap(Collection::stream)
                         .collect(Collectors.toSet());

不幸的是,如果它对性能产生重大影响,您将不得不自己尝试。

这意味着您使用的是 Java 8 。但是当你使用方法forEach()时我就是这么认为的。

修改
请注意D. Kovács关于parallel()方法用法的评论:Details

答案 1 :(得分:1)

我认为您可以使用flatMap()

更多地利用并行性

如果您可以估算所需的尺寸,也可以考虑使用ConcurrentHashMap,即Collections.newSetFromMap(new ConcurrentHashMap())

示例:

    final int EST_SIZE = 6_000_000;
    // Map<Integer,Map<String,Double>> map1;
    Set<String> keys = map1.values().stream().map(Map::keySet)
            .flatMap(Set::stream).parallel().unordered()
            .collect(Collector.of(
                    () -> Collections.newSetFromMap(
                        new ConcurrentHashMap<>(EST_SIZE * 4 / 3 + 1)
                    ),
                    Set::add,
                    (set1,set2) -> { 
                        set1.addAll(set2);
                        return set1;
                    },
                    Collector.Characteristics.CONCURRENT,
                    Collector.Characteristics.UNORDERED
                    ));

注意:上述代码是针对高度专业化方案的尝试优化。在决定之前测试并检查性能。在一般情况下,你应该喜欢这样的东西:

    Set<String> keys = map1.values().stream().map(Map::keySet)
            .flatMap(Set::stream).collect(Collectors.toSet());

答案 2 :(得分:1)

基本上,您的方法对于通用案例是最佳的。你当然可以定制它,如果你对Map结构,密钥分配等有额外的限制。但对于一般情况,我没有看到更好的方法,也许是其他语法(例如,一直使用流:< / p>

map.entrySet().stream().map(Map.Entry::getValue).flatMap(e -> e.keySet().stream()).collect(Collectors.toSet())