ПредишенСледващото

Рядко, днес сериозна заявка прави без кеширане на нищо. Някои кеш LRU се реализира елементарни, например, с помощта на хеш таблици и двойно-свързани списъци. Но не и на факта, че вашето решение ще се различава особено ефективна, така че е най-добре да се възползват от крайния изпълнението. Често като реализация препоръчвам Guava или LruMap на Twitter-Util. Но тези решения имат своите недостатъци, по-специално, стека Twitter традиционно ви свързва с Скала 2.10 и гуава просто ужасно.

За щастие, в Скала може лесно да се направи проста Kheshig не плъзгане в ненужен проект зависимости. В света Java, широко известен рецепция overaydom метод removeEldestEntry клас LinkedHashMap, позволява да се получи LRU кеш. Получаването на тази не много елегантен, но все пак не е толкова зле, колкото гуава. Преведено на Scala тя изглежда така:

внос Java. Util. # 123; Карта, LinkedHashMap # 125;

Def makeCache # 91; К, V # 93; # 40; капацитет. Int # 41. карта # 91; К, V # 93; = # 123;
новият LinkedHashMap # 91; К, V # 93; # 40; капацитет, 0.7F, вярно # 41; # 123;
частен Вал cacheCapacity = капацитет

замените деф removeEldestEntry # 40; влизане. Карта. влизане # 91; К, V # 93; # 41. булеви = # 123;
това. размер # 40; # 41;> това. cacheCapacity
# 125;
# 125;
# 125;

Скала> случай клас Dog (име: String)
дефиниран клас Dog

Скала> Val кеш = makeCache [String, куче] (3)
кеш: java.util.Map [String, куче] = <>

Скала> Option (cache.get ( "8"))
res2: Вариант [куче] = Някои (кучета (8))

Скала> Option (cache.get ( "ololo"))
res4: Вариант [куче] = Няма

Имайте предвид, че cache.get увити във вариант, тъй като това dzhavny LinkedHashMap и да получите метод може да се върне празно. Но за примитивни типове (Int и други подобни), той се връща стойността по подразбиране:

Скала> Val кеш = makeCache [String, Int] (3)
кеш: java.util.Map [String, Int] = <>

Скала> cache.get ( "тест")
res5: Int = 0

Скала> Val кеш = makeCache [String, булева] (3)
кеш: java.util.Map [String, булева] = <>

Скала> cache.get ( "тест")
res6: Булева = фалшива

Ето защо, може да искате да използвате метод containsKey:

Скала> cache.containsKey ( "тест")
res7: Булева = фалшива

Също така трябва да се вземе предвид, че ако вашият keshom може да работи повече от един поток в даден момент, ще трябва да го увийте в synchonized:

Скала> cache.synchronized
res8: Булева = фалшива

А сега да разгледаме втория метод.

Хотел Scala също има LinkedHashMap, но той няма аргумент accessOrder, в dzhavnom LinkedHashMap, в резултат на което той може да бъде получена само FIFO кеша:

внос Скала. колекция. _

Вал cacheCapacity = 10000
Вал cacheMutex = нов обект # 40; # 41;
Var кеш = непостоянен. LinkedHashMap # 91; String, Long # 93; # 40; # 41;

// запис на кеша
cacheMutex. синхронизирано # 123;
кеш. слагам # 40; "Ключ". 100500 # 41;
кеш = кеш. капка # 40; кеш. размер - cacheCapacity # 41;
# 125;

// чете от кеша
cacheMutex. синхронизирано # 123; кеш. получавам # 40; "Ключ" # 41; # 125;

Ето, методът на GET връща опция. Почиства кеша "на ръка", използвайки пада на метод. Освен това, този метод връща нова LinkedHashMap, така че да се синхронизира достъпа кеш изисква отделен обект cacheMutex. Също така трябва да се вземе предвид, че от съображения за ефективност може да искате да не падне, за всеки запис в кеш паметта:

// запис на кеша
cacheMutex. синхронизирано # 123;
кеш. слагам # 40; "Ключ". 100500 # 41;
ако # 40; кеш. размер> cacheCapacity # 41; # 123;
кеш = кеш. капка # 40; кеш. размер - # 40; cacheCapacity. toDouble * 0.75 # 41. toInt # 41;
# 125;
# 125;

И като цяло, е възможно да се направи това в отделна нишка.

Излишно е да казвам, има много други начини за създаване на кеш за Scala, но двамата ми се струват най-простите. Разбира се, в реални приложения е много по-интересно, защото кешовете не трябва да се раздели с реални данни или кеш на други nodah кеш може да се наложи да бъде разделен на няколко, така че да не се превърне в пречка, и така нататък.

И как си кеш?

Подкрепете проекта - споделете линка, благодаря!