如何使用computeIfAbsent()在HashMap中缓存数据?

时间:2017-12-28 21:26:55

标签: java collections java-8

我有单独的目录,其中包含具有类和目录属性的文件,其中包含嵌入对象类型的属性。 加载该类的第一个属性,然后loadEmbeddedTypeProps()方法遍历类的字段,如果找到某个类型的字段(我在下面的示例中使用了Enumerated),那么也会为该类型加载属性。另一个目录。最后,类的属性及其嵌入类型被合并mergeProperties()方法被调用。

我决定在静态cachedProperties HashMap中缓存嵌入类型的属性。 如果它已经包含某个键的属性,那么我们从cachedProperties获取它们并与locaProperties HashMap合并。如果没有,我们将从文件中下载属性(调用loadPropsForType())。

逻辑按预期工作,但看起来loadEmbeddedTypeProps()方法中的代码可能会使用computeIfAbsent方法进行改进。我最近开始尝试使用lambdas,但不确定如何在这里实现。它也适合使用computeIfAbsent

private static Map<String, Map<String, Properties>> cachedProperties = new HashMap<>();

            private Map<String, Properties> loadEmbeddedTypeProps(Class myClass) {
                Map<String, Properties> localProperties = new HashMap<>();
                Arrays.stream(myClass.getFields())
                        .filter(field -> field.getType().isAssignableFrom(Enumerated.class))
                        .forEach(field -> {
                            String fieldName = field.getType().getSimpleName();
                            String enumTypeName = StringUtils.uncapitalize(fieldName);
                            try {
                                if (cachedProperties.containsKey(enumTypeName)) {
                                 // properties for enumerated type are already in cache
                                    Map<String, Properties> propertiesFromCache = cachedProperties.get(enumTypeName);
                                    mergeProperties(propertiesFromCache, localProperties);
                                } else {
                                // properties for enumerated type are not cached yet
                                    Map<String, Properties> loadEnumProperties = loadPropsForType(enumTypeName);
                                    cachedProperties.put(enumTypeName, loadEnumProperties);
                                    mergeProperties(loadEnumProperties, localProperties);
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        });
                return localProperties;
            }

2 个答案:

答案 0 :(得分:1)

是的,computeIfAbsent()在这里是合适的。您可以按如下方式使用它:

Map<String, Properties> properties =
      cachedProperties.computeIfAbsent(enumTypeName, this::loadPropsForType);
mergeProperties(properties, localProperties);

假设loadPropsForType是封闭类的实例方法。无论是什么,都要适当地替换方法参考。根据{{​​3}}的文档,此处方法引用的类型是Function<? super String, ? extends Map<String, Properties>>的子类型。

答案 1 :(得分:1)

您可以使用computeIfAbsent,但由于您无法从Function<...>中抛出已检查的异常,因此您必须将try catch放入lambda中,并传递给{{1} }}

computeIfAbsent

返回.forEach(field -> { String fieldName = field.getType().getSimpleName(); String enumTypeName = StringUtils.uncapitalize(fieldName); Map<String, Properties> enumProperties = cachedProperties.computeIfAbsent(enumTypeName, key -> { try { return loadPropsForType(key); } catch (IOException e) { e.printStackTrace(); return null; } }); mergeProperties(enumProperties, localProperties); }); 告诉computeIfAbsent不应该进行映射。

  

如果映射函数返回null,则不记录映射。

因此,如果抛出异常,那么该字段基本上只是被忽略。请注意,返回的null也是enumProperties,因此您必须在null中处理该问题。