Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 实现LRU缓存的最佳方法_Java_C++_Caching - Fatal编程技术网

Java 实现LRU缓存的最佳方法

Java 实现LRU缓存的最佳方法,java,c++,caching,Java,C++,Caching,我正在研究LRU缓存实现的这个问题,在缓存大小满后,弹出最近使用最少的项,并将其替换为新项 我考虑了两种实现: 1) 。创建两个类似于以下内容的贴图 std::map<timestamp, k> time_to_key std::map<key, std::pair<timestamp, V>> LRUCache std::将时间映射到键 映射LRUCache 要插入新元素,可以将当前时间戳和值放入LRUCache中。当缓存的大小已满时,我们可以通过查找t

我正在研究LRU缓存实现的这个问题,在缓存大小满后,弹出最近使用最少的项,并将其替换为新项

我考虑了两种实现:

1) 。创建两个类似于以下内容的贴图

std::map<timestamp, k> time_to_key
std::map<key, std::pair<timestamp, V>> LRUCache
std::将时间映射到键
映射LRUCache
要插入新元素,可以将当前时间戳和值放入LRUCache中。当缓存的大小已满时,我们可以通过查找time_to_key中存在的最小时间戳并从LRUCache中删除相应的key来逐出最近的元素。 插入一个新项是O(1),更新时间戳是O(n)(因为我们需要在time-to-key中搜索与时间戳对应的k)

2) 。创建一个链表,其中最近使用最少的缓存位于头部,新项添加在尾部。当缓存中已经存在的项到达时,与该项的键对应的节点将移动到列表的尾部。 插入新项是O(1),更新时间戳是O(n)(因为我们需要移动到列表的尾部),删除元素是O(1)

现在我有以下问题:

  • 以下哪一种实现更适合LRUCache

  • 是否有其他方法实现LRU缓存

  • 在Java中,我应该使用HashMap来实现LRUCache吗

  • 我见过一些问题,比如实现一个通用的LRU缓存,也见过一些问题,比如实现一个LRU缓存。通用LRU缓存与LRU缓存不同吗

  • 提前感谢

    编辑:

    **Data into LRU Cache :** 
    [Employee [id=1, name=Shahbaz, age=29, loginTime=2015-10-15 18:47:28.1
    [Employee [id=6, name=Sneha, age=25, loginTime=2015-10-15 18:47:28.125
    [Employee [id=7, name=chantan, age=19, loginTime=2015-10-15 18:47:28.125
    [Employee [id=8, name=nitin, age=22, loginTime=2015-10-15 18:47:28.125
    [Employee [id=9, name=sanuj, age=31, loginTime=2015-10-15 18:47:28.125
    

    在Java中实现LRUCache的另一种方法(最简单的方法)是使用LinkedHashMap并重写布尔removeEldestEntry(Map.entry eldest)函数

    通常情况下,LRU缓存表示为后进先出结构—元素的单个队列。如果您的标准提供的缓存不允许您从中间删除对象,例如,将对象放在顶部,那么您可能需要自己滚动。如果您想要LRU缓存,Java中最简单的是LinkedHashMap。默认行为是FIFO,但您可以将其更改为“访问顺序”,使其成为LRU缓存

    public static <K,V> Map<K,V> lruCache(final int maxSize) {
        return new LinkedHashMap<K, V>(maxSize*4/3, 0.75f, true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
                return size() > maxSize;
            }
        };
    }
    
    当accessOrder为
    true
    时,每当您获得()一个不是最后一个的条目时,LinkedHashMap就会重新排列映射的顺序


    这样,最旧的条目是最近使用的最少的条目。

    考虑到缓存允许并发访问,LRU缓存的良好设计问题归结为:

    a) 在更新两个结构(缓存结构和LRU结构)时,我们是否可以避免使用互斥锁

    b) 缓存的读取(获取)操作是否需要互斥

    更详细地说:假设我们使用java.util.concurrent.NactionurenthashMap(缓存结构)和java.util.concurrent.ConcurrentLinkedQueue(LRU结构)实现此功能

    a) 在编辑操作上锁定这两个结构-addEntry()、removeEntry()、ReceiveEntries()等

    b) 上述操作可能会以慢写操作的形式传递,但问题是即使对于读取(get)操作,我们也需要对这两个结构应用锁。因为,get意味着将条目放在LRU策略的队列前面(假设条目从队列末尾移除)

    使用诸如ConcurrentHashMap和无等待ConcurrentLinkedQueue之类的高效并发结构,然后对它们加锁,这就失去了它的全部用途

    我用同样的方法实现了一个LRU缓存,但是,LRU结构是异步更新的,无需在访问这些结构时使用任何互斥。LRU是缓存的内部细节,可以在不影响缓存用户的情况下以任何方式实现

    稍后,我还阅读了ConcurrentLinkedHashMap


    发现它也在尝试做同样的事情。未使用此结构,但可能非常适合。

    我想用两种可能的实现来扩展其中的一些建议。一个不是线程安全的,另一个可能是线程安全的

    下面是一个最简单的版本,单元测试表明它是有效的

    首先是非并发版本:

    import java.util.LinkedHashMap;
    import java.util.Map;
    
    public class LruSimpleCache<K, V> implements LruCache <K, V>{
    
        Map<K, V> map = new LinkedHashMap (  );
    
    
        public LruSimpleCache (final int limit) {
               map = new LinkedHashMap <K, V> (16, 0.75f, true) {
                   @Override
                   protected boolean removeEldestEntry(final Map.Entry<K, V> eldest) {
                       return super.size() > limit;
                   }
               };
        }
        @Override
        public void put ( K key, V value ) {
            map.put ( key, value );
        }
    
        @Override
        public V get ( K key ) {
            return map.get(key);
        }
    
        //For testing only
        @Override
        public V getSilent ( K key ) {
            V value =  map.get ( key );
            if (value!=null) {
                map.remove ( key );
                map.put(key, value);
            }
            return value;
        }
    
        @Override
        public void remove ( K key ) {
            map.remove ( key );
        }
    
        @Override
        public int size () {
            return map.size ();
        }
    
        public String toString() {
            return map.toString ();
        }
    
    
    }
    
    import java.util.LinkedHashMap;
    导入java.util.Map;
    公共类LruSimpleCache实现LruCache{
    Map Map=newlinkedhashmap();
    公共LruSimpleCache(最终整数限制){
    map=newlinkedhashmap(16,0.75f,真){
    @凌驾
    受保护的布尔重构(最终映射。条目最早){
    返回super.size()>limit;
    }
    };
    }
    @凌驾
    公开作废认沽权(K键,V值){
    map.put(键、值);
    }
    @凌驾
    公共V get(K键){
    返回map.get(key);
    }
    //仅供测试
    @凌驾
    public V getSilent(K键){
    V值=map.get(键);
    if(值!=null){
    map.remove(键);
    map.put(键、值);
    }
    返回值;
    }
    @凌驾
    公共无效删除(K键){
    map.remove(键);
    }
    @凌驾
    公共整数大小(){
    返回map.size();
    }
    公共字符串toString(){
    返回map.toString();
    }
    }
    
    true标志将跟踪get和put的访问。参见JavaDocs。没有构造函数的true标志的removeEdelstEntry只会实现一个FIFO缓存(请参见下面关于FIFO和removeEdelstEntry的注释)

    下面的测试证明它可以作为LRU缓存使用:

    public class LruSimpleTest {
    
        @Test
        public void test () {
            LruCache <Integer, Integer> cache = new LruSimpleCache<> ( 4 );
    
    
            cache.put ( 0, 0 );
            cache.put ( 1, 1 );
    
            cache.put ( 2, 2 );
            cache.put ( 3, 3 );
    
    
            boolean ok = cache.size () == 4 || die ( "size" + cache.size () );
    
    
            cache.put ( 4, 4 );
            cache.put ( 5, 5 );
            ok |= cache.size () == 4 || die ( "size" + cache.size () );
            ok |= cache.getSilent ( 2 ) == 2 || die ();
            ok |= cache.getSilent ( 3 ) == 3 || die ();
            ok |= cache.getSilent ( 4 ) == 4 || die ();
            ok |= cache.getSilent ( 5 ) == 5 || die ();
    
    
            cache.get ( 2 );
            cache.get ( 3 );
            cache.put ( 6, 6 );
            cache.put ( 7, 7 );
            ok |= cache.size () == 4 || die ( "size" + cache.size () );
            ok |= cache.getSilent ( 2 ) == 2 || die ();
            ok |= cache.getSilent ( 3 ) == 3 || die ();
            ok |= cache.getSilent ( 4 ) == null || die ();
            ok |= cache.getSilent ( 5 ) == null || die ();
    
    
            if ( !ok ) die ();
    
        }
    
    公共类LruSimpleTest{
    @试验
    公开无效测试(){
    LruCache=新的LruSimpleCache(4);
    cache.put(0,0);
    cache.put(1,1);
    cache.put(2,2);
    cache.put(3,3);
    布尔ok=cache.size()=4 | | die(“size”+cache.size());
    cache.put(4,
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    public class LruSimpleConcurrentCache<K, V> implements LruCache<K, V> {
    
        final CacheMap<K, V>[] cacheRegions;
    
    
        private static class CacheMap<K, V> extends LinkedHashMap<K, V> {
            private final ReadWriteLock readWriteLock;
            private final int limit;
    
            CacheMap ( final int limit, boolean fair ) {
                super ( 16, 0.75f, true );
                this.limit = limit;
                readWriteLock = new ReentrantReadWriteLock ( fair );
    
            }
    
            protected boolean removeEldestEntry ( final Map.Entry<K, V> eldest ) {
                return super.size () > limit;
            }
    
    
            @Override
            public V put ( K key, V value ) {
                readWriteLock.writeLock ().lock ();
    
                V old;
                try {
    
                    old = super.put ( key, value );
                } finally {
                    readWriteLock.writeLock ().unlock ();
                }
                return old;
    
            }
    
    
            @Override
            public V get ( Object key ) {
                readWriteLock.writeLock ().lock ();
                V value;
    
                try {
    
                    value = super.get ( key );
                } finally {
                    readWriteLock.writeLock ().unlock ();
                }
                return value;
            }
    
            @Override
            public V remove ( Object key ) {
    
                readWriteLock.writeLock ().lock ();
                V value;
    
                try {
    
                    value = super.remove ( key );
                } finally {
                    readWriteLock.writeLock ().unlock ();
                }
                return value;
    
            }
    
            public V getSilent ( K key ) {
                readWriteLock.writeLock ().lock ();
    
                V value;
    
                try {
    
                    value = this.get ( key );
                    if ( value != null ) {
                        this.remove ( key );
                        this.put ( key, value );
                    }
                } finally {
                    readWriteLock.writeLock ().unlock ();
                }
                return value;
    
            }
    
            public int size () {
                readWriteLock.readLock ().lock ();
                int size = -1;
                try {
                    size = super.size ();
                } finally {
                    readWriteLock.readLock ().unlock ();
                }
                return size;
            }
    
            public String toString () {
                readWriteLock.readLock ().lock ();
                String str;
                try {
                    str = super.toString ();
                } finally {
                    readWriteLock.readLock ().unlock ();
                }
                return str;
            }
    
    
        }
    
        public LruSimpleConcurrentCache ( final int limit, boolean fair ) {
            int cores = Runtime.getRuntime ().availableProcessors ();
            int stripeSize = cores < 2 ? 4 : cores * 2;
            cacheRegions = new CacheMap[ stripeSize ];
            for ( int index = 0; index < cacheRegions.length; index++ ) {
                cacheRegions[ index ] = new CacheMap<> ( limit / cacheRegions.length, fair );
            }
        }
    
        public LruSimpleConcurrentCache ( final int concurrency, final int limit, boolean fair ) {
    
            cacheRegions = new CacheMap[ concurrency ];
            for ( int index = 0; index < cacheRegions.length; index++ ) {
                cacheRegions[ index ] = new CacheMap<> ( limit / cacheRegions.length, fair );
            }
        }
    
        private int stripeIndex ( K key ) {
            int hashCode = key.hashCode () * 31;
            return hashCode % ( cacheRegions.length );
        }
    
        private CacheMap<K, V> map ( K key ) {
            return cacheRegions[ stripeIndex ( key ) ];
        }
    
        @Override
        public void put ( K key, V value ) {
    
            map ( key ).put ( key, value );
        }
    
        @Override
        public V get ( K key ) {
            return map ( key ).get ( key );
        }
    
        //For testing only
        @Override
        public V getSilent ( K key ) {
            return map ( key ).getSilent ( key );
    
        }
    
        @Override
        public void remove ( K key ) {
            map ( key ).remove ( key );
        }
    
        @Override
        public int size () {
            int size = 0;
            for ( CacheMap<K, V> cache : cacheRegions ) {
                size += cache.size ();
            }
            return size;
        }
    
        public String toString () {
    
            StringBuilder builder = new StringBuilder ();
            for ( CacheMap<K, V> cache : cacheRegions ) {
                builder.append ( cache.toString () ).append ( '\n' );
            }
    
            return builder.toString ();
        }
    
    
    }
    
    #include <iostream>
    #include <unordered_map>
    #include <utility>
    
    using namespace std;
    
    // List nodeclass
    class Node
    {
        public:
        int data;
        Node* next;
        Node* prev;
    };
    
    //Doubly Linked list
    class DLList
    {
        public:
    
        DLList()
        {
            head = NULL;
            tail = NULL;
            count = 0;
        }
    
        ~DLList() {}
    
        Node* addNode(int val);
        void print();
        void removeTail();
        void moveToHead(Node* node);
    
        int size()
        {
            return count;
        }
    
        private:
        Node* head;
        Node* tail;
        int count;
    };
    
    // Function to add a node to the list
    
    Node* DLList::addNode(int val)
    {
        Node* temp = new Node();
    
        temp->data = val;
        temp->next = NULL;
        temp->prev = NULL;
    
        if ( tail == NULL )
        {
            tail = temp;
            head = temp;
        }
        else
        {
            head->prev = temp;
            temp->next = head;
            head = temp;
        }
    
        count++;
    
        return temp;
    }
    
    void DLList::moveToHead(Node* node)
    {
        if (head == node)
            return;
    
        node->prev->next = node->next;
    
        if (node->next != NULL)
        {
            node->next->prev = node->prev;
        }
        else
        {
            tail = node->prev;
        }
            node->next = head;
            node->prev = NULL;
            head->prev = node;
            head = node;
    }
    
    void DLList::removeTail()
    {
        count--;
    
        if (head == tail)
        {
            delete head;
            head = NULL;
            tail = NULL;
        }
        else
        {
            Node* del = tail;
            tail = del->prev;
            tail->next = NULL;
            delete del;
        }
    }
    
    void DLList::print()
    {
        Node* temp = head;
    
        int ctr = 0;
    
        while ( (temp != NULL) && (ctr++ != 25) )
        {
            cout << temp->data << " ";
            temp = temp->next;
        }
        cout << endl;
    }
    
    class LRUCache
    {
        public:
            LRUCache(int aCacheSize);
            void fetchPage(int pageNumber);
    
        private:
            int cacheSize;
            DLList dlist;
            unordered_map< int, Node* > directAccess;
    };
    
        LRUCache::LRUCache(int aCacheSize):cacheSize(aCacheSize) { }
    
        void LRUCache::fetchPage(int pageNumber)
        {
            unordered_map< int, Node* >::const_iterator it = directAccess.find(pageNumber);
    
            if (it != directAccess.end())
            {
                dlist.moveToHead( (Node*)it->second);
            }
            else
            {
                if (dlist.size() == cacheSize-1)
                   dlist.removeTail();
    
                Node* node = dlist.addNode(pageNumber);
    
                directAccess.insert(pair< int, Node* >(pageNumber,node));
            }
    
            dlist.print();
        }
    
        int main()
        {
            LRUCache lruCache(10);
    
            lruCache.fetchPage(5);
            lruCache.fetchPage(7);
            lruCache.fetchPage(15);
            lruCache.fetchPage(34);
            lruCache.fetchPage(23);
            lruCache.fetchPage(21);
            lruCache.fetchPage(7);
            lruCache.fetchPage(32);
            lruCache.fetchPage(34);
            lruCache.fetchPage(35);
            lruCache.fetchPage(15);
            lruCache.fetchPage(37);
            lruCache.fetchPage(17);
            lruCache.fetchPage(28);
            lruCache.fetchPage(16);
    
            return 0;
    }
    
    package com.test.example.dto;
    
    import java.sql.Timestamp;
    /**
     * 
     * @author Vaquar.khan@gmail.com
     *
     */
    public class Employee implements Comparable<Employee> {
        private int     id;
        private String  name;
        private int     age;
        private Timestamp loginTime ;
    
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public Timestamp getLoginTime() {
        return loginTime;
    }
    
    public void setLoginTime(Timestamp loginTime) {
        this.loginTime = loginTime;
    }
    
    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", loginTime=" + loginTime + "]";
    }
    
    Employee(){}
    
    public Employee(int id, String name, int age, Timestamp loginTime) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
        this.loginTime = loginTime;
    }
    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + id;
        result = prime * result + ((loginTime == null) ? 0 : loginTime.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        Employee other = (Employee) obj;
        if (age != other.age) return false;
        if (id != other.id) return false;
        if (loginTime == null) {
            if (other.loginTime != null) return false;
        } else if (!loginTime.equals(other.loginTime)) return false;
        if (name == null) {
            if (other.name != null) return false;
        } else if (!name.equals(other.name)) return false;
        return true;
    }
    
    @Override
    public int compareTo(Employee emp) {
        if (emp.getLoginTime().before( this.loginTime) ){
            return 1;
        } else if (emp.getLoginTime().after(this.loginTime)) {
            return -1;
        }
        return 0;
    }
    
    
    }
    
    package com.test.example;
    
    import java.sql.Timestamp;
    import java.util.Calendar;
    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    import com.test.example.dto.Employee;
    /**
     * 
     * @author Vaquar.khan@gmail.com
     *
     */
    public class LRUObjectCacheExample {
    
    
        LinkedHashMap<Employee, Boolean>    lruCacheLinkedQueue;
    
    public LRUObjectCacheExample(int capacity) {
        lruCacheLinkedQueue = new LinkedHashMap<Employee, Boolean>(capacity, 1.0f, true) {
            /**
             * 
             */
            private static final long   serialVersionUID    = 1L;
    
            @Override
            protected boolean removeEldestEntry(
                    //calling map's entry method
                    Map.Entry<Employee, Boolean> eldest) {
                return this.size() > capacity;
            }
        };
    }
    
    void addDataIntoCache(Employee employee) {
        lruCacheLinkedQueue.put(employee, true);
        displayLRUQueue();
    }
    
    boolean checkIfDataPresentIntoLRUCaache(int data) {
        return lruCacheLinkedQueue.get(data) != null;
    }
    
     void deletePageNo(int data) {
        if (lruCacheLinkedQueue.get(data) != null){
                lruCacheLinkedQueue.remove(data);
        }
        displayLRUQueue();
    }
    
     void displayLRUQueue() {
        System.out.print("-------------------------------------------------------"+"\n");
        System.out.print("Data into LRU Cache : ");
        for (Entry<Employee, Boolean> mapEntry : lruCacheLinkedQueue.entrySet()) {
            System.out.print("[" + mapEntry.getKey() + "]");
        }
        System.out.println("");
    }
    
    public static void main(String args[]) {
        Employee employee1 = new Employee(1,"Shahbaz",29, getCurrentTimeStamp());
        Employee employee2 = new Employee(2,"Amit",35,getCurrentTimeStamp());
        Employee employee3 = new Employee(3,"viquar",36,getCurrentTimeStamp());
        Employee employee4 = new Employee(4,"Sunny",20,getCurrentTimeStamp());
        Employee employee5 = new Employee(5,"sachin",28,getCurrentTimeStamp());
        Employee employee6 = new Employee(6,"Sneha",25,getCurrentTimeStamp());
        Employee employee7 = new Employee(7,"chantan",19,getCurrentTimeStamp());
        Employee employee8 = new Employee(8,"nitin",22,getCurrentTimeStamp());
        Employee employee9 = new Employee(9,"sanuj",31,getCurrentTimeStamp());
        //
        LRUObjectCacheExample lru = new LRUObjectCacheExample(5);
        lru.addDataIntoCache(employee5);//sachin
        lru.addDataIntoCache(employee4);//Sunny
        lru.addDataIntoCache(employee3);//viquar
        lru.addDataIntoCache(employee2);//Amit
        lru.addDataIntoCache(employee1);//Shahbaz -----capacity reached
        //
            lru.addDataIntoCache(employee6);/Sneha
            lru.addDataIntoCache(employee7);//chantan
            lru.addDataIntoCache(employee8);//nitin
            lru.addDataIntoCache(employee9);//sanuj
            //
            lru.deletePageNo(3);
            lru.deletePageNo(4);
    
        }
        private static Timestamp getCurrentTimeStamp(){
            return new java.sql.Timestamp(Calendar.getInstance().getTime().getTime());
        }
    
    }
    
    **Data into LRU Cache :** 
    [Employee [id=1, name=Shahbaz, age=29, loginTime=2015-10-15 18:47:28.1
    [Employee [id=6, name=Sneha, age=25, loginTime=2015-10-15 18:47:28.125
    [Employee [id=7, name=chantan, age=19, loginTime=2015-10-15 18:47:28.125
    [Employee [id=8, name=nitin, age=22, loginTime=2015-10-15 18:47:28.125
    [Employee [id=9, name=sanuj, age=31, loginTime=2015-10-15 18:47:28.125
    
    public class LRUCache<K, V> extends LinkedHashMap<K, V> {
    
        private int cacheSize;
    
        public LRUCache(int cacheSize) {
            super(cacheSize * 4 / 3, 0.75f, true);
            this.cacheSize = cacheSize;
        }
    
        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
            return size() >= cacheSize;
        }
    
        public static void main(String args[]) {
            LRUCache<Integer, Integer> lruCache = new LRUCache<>(5);
    
            lruCache.put(1, 1);
            lruCache.put(2, 2);
            lruCache.put(3, 3);
            lruCache.put(1, 4);
            lruCache.put(2, 5);
            lruCache.put(7, 6);
    
            System.out.println(lruCache.keySet());
    
            lruCache.put(1, 4);
            lruCache.put(2, 5);
    
            System.out.println(lruCache.keySet());
        }
    } 
    
    class LRU {
        Map<String, Integer> ageMap = new HashMap<String, Integer>();
        int age = 1;
    
        void addElementWithAge(String element) {
    
            ageMap.put(element, age);
            age++;
    
        }
    
        String getLeastRecent(Map<String, Integer> ageMap) {
            Integer oldestAge = (Integer) ageMap.values().toArray()[0];
            String element = null;
            for (Entry<String, Integer> entry : ageMap.entrySet()) {
                if (oldestAge >= entry.getValue()) {
                    oldestAge = entry.getValue();
                    element = entry.getKey();
                }
            }
            return element;
        }
    
        public static void main(String args[]) {
            LRU obj = new LRU();
            obj.addElementWithAge("M1");
            obj.addElementWithAge("M2");
            obj.addElementWithAge("M3");
            obj.addElementWithAge("M4");
            obj.addElementWithAge("M1");
        }
    
    }
    
    myLRUCache = new LinkedHashMap<Long,String>() {
    protected boolean removeEldestEntry(Map.Entry eldest) 
    { 
    if(this.size()>1000)
        return true;
      else
          return false;
    }
    };