我尝试实现一个属性文件MRU缓存,其缓存大小有限,是最近使用的属性之一,只能保存在其中。此缓存中的读取缺失将导致对该特定属性的文件进行读取,并将其保存在缓存中,直到超出其他最近属性从该文件读入缓存的限制。
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedHashMap;
public class PropertiesFileMRUCache {
private LinkedHashMap<String, String> propertiesMap = new LinkedHashMap<>(
10);
private int limit = 8;
private String propertiesFile = "default.properties";
public PropertiesFileMRUCache() {
}
public PropertiesFileMRUCache(String propertiesFile) {
this.propertiesFile = propertiesFile;
}
public PropertiesFileMRUCache(int limit, String propertiesFile) {
this(propertiesFile);
this.limit = limit;
}
public String getCapital(String country) {
String capital = propertiesMap.get(country);
if (capital == null) {
capital = readFromFile(country);
if (propertiesMap.size() == limit) {
propertiesMap.remove(propertiesMap.keySet().iterator().next());
}
} else {
propertiesMap.remove(country);
}
propertiesMap.put(country, capital);
return capital;
}
private String readFromFile(String country) {
try (BufferedReader br = new BufferedReader(new FileReader(
propertiesFile))) {
for (String line; (line = br.readLine()) != null;) {
if (line.startsWith(country)) {
return line.substring(line.indexOf('=') + 1);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
PropertiesFileMRUCache pfc = new PropertiesFileMRUCache("res\\CountryCapital.properties");
pfc.getCapital("India");
pfc.getCapital("USA");
pfc.getCapital("UK");
pfc.getCapital("Kuwait");
pfc.getCapital("Iraq");
pfc.getCapital("Canada");
pfc.getCapital("Australia");
pfc.getCapital("India");
pfc.getCapital("India");
pfc.getCapital("India");
pfc.getCapital("Germany");
pfc.getCapital("India");
pfc.getCapital("Germany");
pfc.getCapital("China");
pfc.getCapital("Pakistan");
System.out.println(pfc.propertiesMap);
}
}出于测试目的,我提供了一个用户指定的属性为res\CountryCapital.properties,默认缓存限制为8。CountryCapital.properties的内容如下所示,以供参考:
德里India=New USA=Washington Egypt=Cairo Srilanka=Columbo Korea=Seoul Tailand=Bangkok Qutar=Doha Lebanon=Beirut Canada=Toronto Norway=Oslo Finland=Helsinki China=Beiging Japan=Tokyo Bangladesh=Dhaka Pakistan=Karachi Pakistan=Karachi Bangladesh=Dhaka Afganistan=Kabul Bangladesh=Dhaka Afganistan=Kabul en32 19 en32 21 en32 23 en32 25 en32
发布于 2015-08-12 19:32:48
Java的LinkedHashMap代码虽然功能强大,但鲜为人知,它是为管理像您这样的缓存而构建的。在您的例子中,您应该使用访问顺序构造函数创建地图:
private static final class MyCache extends LinkedHashMap<String, String> {
private final int limit;
public MyCache(int limit) {
super(limit, 0.75f, true);
this.limit = limit;
}
@Override
protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
return size() > limit;
}
}注意如何覆盖removeEldestEntry方法?
如果将所有这些放在一个应用程序中,它看起来如下:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedHashMap;
import java.util.Map;
public class PropertiesFileMRUCache {
private static final class MyCache extends LinkedHashMap<String, String> {
private final int limit;
public MyCache(int limit) {
super(limit, 0.75f, true);
this.limit = limit;
}
@Override
protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
return size() > limit;
}
}
private final MyCache cache;
private final Path propertiesFile;
public PropertiesFileMRUCache(int limit, String file) {
cache = new MyCache(limit);
propertiesFile = Paths.get(file);
}
public String getCapital(String country) {
return cache.computeIfAbsent(country, c -> readFromFile(c));
}
private String readFromFile(String country) {
final String prefix = country + "=";
try (Stream<String> lines = Files.lines(propertiesFile)){
return lines.filter(line -> line.startsWith(prefix))
.map(line -> line.substring(prefix.length()))
.findFirst()
.orElse(null);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
PropertiesFileMRUCache pfc = new PropertiesFileMRUCache(8, "ccap.properties");
pfc.getCapital("India");
pfc.getCapital("USA");
pfc.getCapital("UK");
pfc.getCapital("Kuwait");
pfc.getCapital("Iraq");
pfc.getCapital("Canada");
pfc.getCapital("Australia");
pfc.getCapital("India");
pfc.getCapital("India");
pfc.getCapital("India");
pfc.getCapital("Germany");
pfc.getCapital("India");
pfc.getCapital("Germany");
pfc.getCapital("China");
pfc.getCapital("Pakistan");
System.out.println(pfc.cache);
}
}请注意,我是如何在您的readFromFile方法中进行黑客攻击的。我已经使它基于NIO2 2使用路径和文件。在Java 8中,这是最好的实践方法。我还流了行,我相信这会有所帮助。使用资源的尝试也能干净地关闭流。此外,computeIfAbsent是重用现有条目并创建缺失条目的正确方法。
有很多事情你应该认为是不同的。将LinkedHashMap的扩展视为最重要的,而改进computeIfAbsent的使用则是第二重要的。
https://codereview.stackexchange.com/questions/100721
复制相似问题