Переменные не являются полиморфными в Java; они не переопределяют друг друга.
Я записал Кэш LRU и некоторые тестовые сценарии, не стесняйтесь использовать его.
можно прочитать источник на мой блог .
Для ленивого (здесь, это минус тестовые сценарии):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LRUCache {
public class IndexedLinkedList<T> {
LinkedList<T> data = new LinkedList<T>();
Dictionary<T, LinkedListNode<T>> index = new Dictionary<T, LinkedListNode<T>>();
public void Add(T value) {
index[value] = data.AddLast(value);
}
public void RemoveFirst() {
index.Remove(data.First.Value);
data.RemoveFirst();
}
public void Remove(T value) {
LinkedListNode<T> node;
if (index.TryGetValue(value, out node)) {
data.Remove(node);
index.Remove(value);
}
}
public int Count {
get {
return data.Count;
}
}
public void Clear() {
data.Clear();
index.Clear();
}
public T First {
get {
return data.First.Value;
}
}
}
}
LRUCache
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LRUCache {
public class LRUCache<TKey, TValue> : IDictionary<TKey, TValue> {
object sync = new object();
Dictionary<TKey, TValue> data;
IndexedLinkedList<TKey> lruList = new IndexedLinkedList<TKey>();
ICollection<KeyValuePair<TKey, TValue>> dataAsCollection;
int capacity;
public LRUCache(int capacity) {
if (capacity <= 0) {
throw new ArgumentException("capacity should always be bigger than 0");
}
data = new Dictionary<TKey, TValue>(capacity);
dataAsCollection = data;
this.capacity = capacity;
}
public void Add(TKey key, TValue value) {
if (!ContainsKey(key)) {
this[key] = value;
} else {
throw new ArgumentException("An attempt was made to insert a duplicate key in the cache.");
}
}
public bool ContainsKey(TKey key) {
return data.ContainsKey(key);
}
public ICollection<TKey> Keys {
get {
return data.Keys;
}
}
public bool Remove(TKey key) {
bool existed = data.Remove(key);
lruList.Remove(key);
return existed;
}
public bool TryGetValue(TKey key, out TValue value) {
return data.TryGetValue(key, out value);
}
public ICollection<TValue> Values {
get { return data.Values; }
}
public TValue this[TKey key] {
get {
var value = data[key];
lruList.Remove(key);
lruList.Add(key);
return value;
}
set {
data[key] = value;
lruList.Remove(key);
lruList.Add(key);
if (data.Count > capacity) {
data.Remove(lruList.First);
lruList.RemoveFirst();
}
}
}
public void Add(KeyValuePair<TKey, TValue> item) {
Add(item.Key, item.Value);
}
public void Clear() {
data.Clear();
lruList.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item) {
return dataAsCollection.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
dataAsCollection.CopyTo(array, arrayIndex);
}
public int Count {
get { return data.Count; }
}
public bool IsReadOnly {
get { return false; }
}
public bool Remove(KeyValuePair<TKey, TValue> item) {
bool removed = dataAsCollection.Remove(item);
if (removed) {
lruList.Remove(item.Key);
}
return removed;
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
return dataAsCollection.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return ((System.Collections.IEnumerable)data).GetEnumerator();
}
}
}
Существует шаблоны & Библиотека Предприятия методов (более конкретно, Блок Программы кэширования ), но это IMO имеет тенденцию быть сверхспроектированным и чрезмерно сложный.
Платформа.NET всегда имела способность сохранить слабые ссылки к объектам.
В основном, слабые ссылки являются ссылками на объекты, которые время выполнения считает "неважным", и это может быть удалено сборкой "мусора", выполненной в любом моменте времени. Это может использоваться, например, к вещам кэша, но Вы не имели бы никакого контроля над тем, что собрано и что нет.
, С другой стороны, это очень просто в использовании, и это может просто быть тем, в чем Вы нуждаетесь.
Dave
Классическая ситуация компромисса. Хранение всего в памяти будет быстро за счет в широком масштабе увеличенного потребления памяти, пока получение от диска уменьшает потребление памяти, но не так производительно. Однако Вы уже знаете все это!
встроенное Система. Сеть. Кэширование. Кэш класс является большим, и я использовал его успешно много раз сам в моих приложениях ASP.NET (хотя главным образом для записи базы данных, кэширующейся), однако, недостаток состоит в том, что кэш будет только работать на одной машине (обычно единственный веб-сервер) и не может быть распределен через несколько машин.
, Если возможно "бросить некоторые аппаратные средства" в проблему, и это должны не обязательно быть дорогие аппаратные средства, просто поля с большим количеством памяти, Вы могли всегда идти с решением для распределенного кэширования. Это даст Вам намного больше памяти для проигрывания с при сохранении (почти) того же уровня производительности.
опции Some для решения для распределенного кэширования для.NET:
или даже Microsoft, собственная Скорость проект.
Как Вы реализуете свой кэш?
можно использовать Cache
класс от System.Web.Caching
, даже в невеб-приложениях, и он произведет чистку объектов на основе LRU, если/когда ему будет нужна память.
В невеб-приложении необходимо будет использовать HttpRuntime.Cache
для доступа Cache
экземпляр.
Примечание, что документация указывает, что Cache
класс не предназначается, чтобы использоваться за пределами ASP.NET, хотя это всегда работало на меня. (Я никогда не полагался на него ни в каком важнейшем приложении все же.)
Блок программы кэширования и кэш ASP.NET являются оба опциями однако, хотя они делают LRU, единственный вид использования диска, которое происходит, подкачкой страниц памяти. Я думаю, что существуют способы, которыми можно оптимизировать это, которые более характерны для цели получить лучший вывод. Вот некоторые мысли:
я, конечно, избегал бы использования простой хеш-таблицы все же.