我想知道是否可以省略使用static Map实例创建缓存。

这是我班的摘录:

public class XpathEvaluator {
    private DocumentBuilder builder;
    private XPath path;
    private Document document;
    private static Map<String, List<String>> cachedXpaths = new HashMap<>();

    private XpathEvaluator() throws ParserConfigurationException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        builder = factory.newDocumentBuilder();
        XPathFactory pathFactory = XPathFactory.newInstance();
        path = pathFactory.newXPath();
    }

    public static XpathEvaluator getEvaluator() throws ParserConfigurationException {
        return new XpathEvaluator();
    }

    public List multipleXpathResults(String xpathExpression) throws IOException, SAXException, XPathExpressionException {
        Logger.operation(StringUtils.appendStrings("Evaluating xpath expression: %1$s", xpathExpression));

        if (cachedXpaths.containsKey(xpathExpression)) {
            List<String> xPathValues = cachedXpaths.get(xpathExpression);
            Logger.info(StringUtils.appendStrings("For xpath: [%1$s] extract cached values: %2$s", xpathExpression, xPathValues));
            return xPathValues;
        }

        // ommited part
        cachedXpaths.put(xpathExpression, results);
        return results;
    }
}


静态引用一直在不断增长,我猜想它可能占用太多空间,并且对内存的影响太大。

解:

private LoadingCache<String, List<String>> cachedXpaths = CacheBuilder.newBuilder()
        .expireAfterWrite(3, TimeUnit.MINUTES)
        .maximumSize(1500)
        .concurrencyLevel(5)
        .weakKeys()
        .build(new CacheLoader<String, List<String>>() {
            @Override
            public List<String> load(String key) throws Exception {
                return createListByKey(key);
            }
        });

private static List<String> createListByKey(String key) throws Exception {
    return instance.getXpathValues(key);
}

public List<String> multipleXpathResults(String xpathExpression) throws Exception {
    Logger.operation(StringUtils.appendStrings("Evaluating xpath expression: %1$s", xpathExpression));

    List<String> results = cachedXpaths.getUnchecked(xpathExpression);
    if (results.isEmpty()) {
        Logger.error(StringUtils.appendStrings(
                "For xpath: [%1$s] extract cached values is EMPTY", xpathExpression));
        return results;
    }
    Logger.operation(StringUtils.appendStrings("Extracted xpath results: %1$s", results));
    return results;
}

private List<String> getXpathValues(String xpathExpression) throws XPathExpressionException {
    List<String> results = new ArrayList<>();
    XPathExpression expression = path.compile(xpathExpression);
    NodeList list = (NodeList) expression.evaluate(document, XPathConstants.NODESET);

    for (int index = 0; index < list.getLength(); index++) {
        Node node = list.item(index);
        String content = node.getTextContent();

        if (isContentWrong(content)) { // check if it is exactly string or number value
            Logger.error(StringUtils.appendStrings("XPATH value is EMPTY, for next node [%1$s]", node.getNodeName()));
            continue;
        }

        Logger.operation(StringUtils.appendStrings("Get NODE value: [%1$s]", content));
        results.add(content);
    }
    if (results.isEmpty()) { // log error if node result is empty
        Logger.error(StringUtils.appendStrings("XPATH result is EMPTY, for next xpath [%1$s]", xpathExpression));
        return Collections.emptyList();
    }
    return results;
}


我想知道如何保持高速缓存并且不使用静态引用?

最佳答案

您可以将Google guava用于这种类型的缓存:

Cache<String, List<String>> cachedXpaths = CacheBuilder.newBuilder()
                .expireAfterWrite(3, TimeUnit.MINUTES)
                .maximumSize(1000)
                .concurrencyLevel(5)
                .weakKeys()
                .build(
                        new CacheLoader<String, List<String>>() {
              // Call load method when there is a new key
                            public List<String> load(String key)
                              throws Exception {
                                // Sample custom method to add a new key
                                return createListByKey(key);
                            }
                        });

07-24 09:49
查看更多