如何省略为数据缓存创建静态地图?
How to omit creating static Map for data caching?
我想知道是否可以省略使用 static Map
实例创建缓存。
这是我的 class:
的片段
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;
}
}
静态引用一直在增长,我想它可能会占用太多 space 并且对内存的影响太大。
解决方法:
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;
}
我想知道如何保持缓存而不使用静态引用?
不要将 Java Map
与缓存混淆。它可以是缓存的存储组件,但合理的缓存远不止存储。
如果缓存 "keeps growing all the time" 并占用 "too much space and memory",如您所说,那么它就不再是缓存了。该问题与静态引用无关。除其他事项外,缓存需要有限内存和策略来选择删除哪些旧值为了让 space 成为新的。
您可能还想阅读 this document about caching best practices or use an existing caching solution like EHCache or Guava Cache。
您可以使用 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);
}
});
我想知道是否可以省略使用 static Map
实例创建缓存。
这是我的 class:
的片段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;
}
}
静态引用一直在增长,我想它可能会占用太多 space 并且对内存的影响太大。
解决方法:
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;
}
我想知道如何保持缓存而不使用静态引用?
不要将 Java Map
与缓存混淆。它可以是缓存的存储组件,但合理的缓存远不止存储。
如果缓存 "keeps growing all the time" 并占用 "too much space and memory",如您所说,那么它就不再是缓存了。该问题与静态引用无关。除其他事项外,缓存需要有限内存和策略来选择删除哪些旧值为了让 space 成为新的。
您可能还想阅读 this document about caching best practices or use an existing caching solution like EHCache or Guava Cache。
您可以使用 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);
}
});