이것은 Java-ish 코드입니다.
해시 맵과 이중 연결 목록의 두 가지 데이터 구조가 필요합니다. 이중 연결 목록에는 타임 스탬프별로 정렬 된 History 객체 (URL 문자열과 타임 스탬프가 포함 된)가 있습니다. 해시 맵은 URL을 키로 사용하여 Map<String, History>
입니다.
class History {
History prev
History next
String url
Long timestamp
void remove() {
prev.next = next
next.prev = prev
next = null
prev = null
}
}
URL을 기록에 추가 할 때 해시지도에 있는지 확인하십시오. 그런 다음 타임 스탬프를 업데이트하면 연결된 목록에서 제거하고 연결된 목록의 끝에 추가합니다. 해시 맵에 없으면 해시 맵에 추가하고 연결된 목록의 끝에 추가하십시오. (해시 맵에 이미 있는지 여부와 상관없이) URL을 추가하는 것은 일정한 시간 작업입니다.
class Main {
History first // first element of the linked list
History last // last element of the linked list
HashMap<String, History> map
void add(String url) {
History hist = map.get(url)
if(hist != null) {
hist.remove()
hist.timestamp = System.currenttimemillis()
} else {
hist = new History(url, System.currenttimemillis())
map.add(url, hist)
}
last.next = hist
hist.prev = last
last = hist
}
}
지난 주, 올바른 타임 스탬프를 누를 때까지 연결된 목록을 거꾸로 통과합니다.
스레드 안전성이 중요하면 스레드 안전성 큐를 사용하여 기록에 URL을 추가하고 단일 스레드를 사용하여이 큐를 처리하십시오. 이런 식으로지도와 연결된 목록은 스레드로부터 안전 할 필요가 없습니다. 즉, 잠금 등에 대해 걱정할 필요가 없습니다.
지속성을 위해 연결된 목록을 직렬화/역 직렬화 할 수 있습니다. 연결된 목록을 deserialize 할 때 해시 맵을 가로 지르고 맵에 요소를 추가하여 해시 맵을 재구성하십시오. 그런 다음 기록을 지우려면 목록을 지우고 메모리에 매핑하고 데이터를 직렬화 한 파일을 삭제하십시오.
메모리 소비 및 IO (즉, (비) 직렬화 비용)면에서보다 효율적인 솔루션은 SQLite과 같은 서버리스 데이터베이스를 사용하는 것입니다. 이 방법을 사용하면 내역을 메모리에 보관할 필요가 없습니다. 마지막 주에 연결된 목록을 탐색하는 대신 데이터베이스를 쿼리하면됩니다. 그러나 SQLite는 본질적으로 트리 맵 (특히 디스크에 저장된 데이터에 최적화 된 B-Tree)입니다.
해시 맵을 사용하는 경우 정렬 된 결과를 빠르게 검색 할 수 없습니다. 왜 당신은 트리 맵을 사용하고 싶지 않습니까, 적색 - 검정색 검색 트리입니까? – mbroshi
레드 - 블랙 트리는 균형을 유지하기 위해 내부적으로 많은 로테이션을 필요로하기 때문에 특히 사용자가 알려진 사이트에서 새로운 사이트로 뛰어 내릴 수 있기 때문에 브라우저에 추가되는 경우가 많습니다. HashMap의 성능이 향상 될 것입니다. 콘텐츠를 정렬하고 이동하는 데 보조 데이터 구조가 사용됩니다. – user775093
히스토리 캐시에 얼마나 많은 사이트가있을 것으로 예상합니까? 1 년 내내 100,000 페이지가 있다면 놀라실 것입니다.하지만 1 백만 달러도 큰 문제가 아닙니다. 선형 목록에 저장하고 순차적으로 검색하면됩니다. 브라우저와 같은 사용자 인터페이스 응용 프로그램에 충분히 빠를 것입니다. –