[cache] LRU ์•Œ๊ณ ๋ฆฌ์ฆ˜ with LinkedHashMap

LRU (Least Recently Used)

LRU ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์šด์˜์ฒด์ œ์˜ ํŽ˜์ด์ง€ ๊ต์ฒด ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. Cache ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ค‘ ๊ฐ€์žฅ ์œ ๋ช…ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ด๊ธฐ๋„ ํ•˜๋‹ค.
LRU ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฐ€์žฅ ์˜ค๋žซ๋™์•ˆ ์ฐธ์กฐ๋˜์ง€ ์•Š์€ ํ•ญ๋ชฉ์„ ๊ต์ฒด ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค.

LinkedHashMap ์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ

LinkedHashMap ์˜ ๋‹ค์Œ ์ƒ์„ฑ์ž๋ฅผ ํ™œ์šฉํ•˜์˜€๋‹ค.

accessOrder ์†์„ฑ

public LinkedHashMap(int initialCapacity,
                     float loadFactor,
                     boolean accessOrder) {
    super(initialCapacity, loadFactor);
    this.accessOrder = accessOrder;
}

accessOrder ๊ฐ’์„ true ๋กœ ์ƒ์„ฑํ•˜๋ฉด ๋‚ด๋ถ€์ ์œผ๋กœ key์— ์ ‘๊ทผํ•  ๋•Œ ๋งˆ๋‹ค afterNodeAccess() ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
afterNodeAccess()๋ฉ”์†Œ๋“œ๋Š” ์ตœ๊ทผ์— ์ ‘๊ทผํ•œ ๋…ธ๋“œ๋ฅผ ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ๋…ธ๋“œ๋กœ ์œ„์น˜์‹œํ‚จ๋‹ค.

removeEldestEntry() ๋ฉ”์†Œ๋“œ

๊ฐ€์žฅ ์˜ค๋ž˜๋œ ๊ฐ’์„ ๋Œ€์ฒดํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
๊ธฐ๋ณธ ๊ฐ’์€ false์ง€๋งŒ LRU ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์ง€์ •๋œ ์‚ฌ์ด์ฆˆ๋ฅผ ๋„˜์–ด๊ฐ€๋ฉด ์˜ค๋ž˜๋œ ๊ฐ’ ๋ถ€ํ„ฐ ์ง€์›Œ์ง€๋„๋ก ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•œ๋‹ค.

@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
    return size() > size;
}

LRU Test

๋‹ค์Œ์€ size๋ฅผ 10์œผ๋กœ ์ง€์ •ํ•˜๊ณ  1๋ถ€ํ„ฐ 10๊นŒ์ง€ ์ˆœ์„œ๋Œ€๋กœ key์™€ value๋ฅผ ์ดˆ๊ธฐํ™” ์‹œํ‚จ ๋’ค ๋‹ค์Œ์˜ ์ž‘์—…์„ ํ•œ ๊ฒฐ๊ณผ๋‹ค.

  • 3์€ get()์œผ๋กœ ์ ‘๊ทผ
  • 5, 2๋Š” put()์œผ๋กœ ๊ฐ’ ์—…๋ฐ์ดํŠธ
  • 11์€ put()์œผ๋กœ ๊ฐ’ ์ž…๋ ฅ
====[LRU test]====
key-4=value-4
key-6=value-6
key-7=value-7
key-8=value-8
key-9=value-9
key-10=value-10
key-3=value-3
key-5=value-5-update
key-11=value-11-insert
key-2=value-2-update

๊ฐ€์žฅ ์ตœ๊ทผ์— ์ ‘๊ทผํ•œ 2,3,5,11 key๊ฐ€ ๋’ค ์ˆœ์„œ๋กœ ์ •๋ ฌ๋˜๊ณ  size๊ฐ€ 10์ด๊ธฐ ๋•Œ๋ฌธ์— ๋งจ ์•ž์˜ key๋กœ ์žˆ์—ˆ์„ key-1์ด ๋จผ์ € ์‚ญ์ œ๋œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.