0

I am doing the following programming exercise: URL Timestamps. The statement is:

For my web app, I need a class that lets me store timestamps for URLs. For URLs that were never accessed, it should return -1. The class should be able to handle about a million calls in a few seconds.

I have tried:

import java.net.URL;
import java.util.*;

public class UrlMap {

  private static final Map<URL,Long> map = new HashMap<URL,Long>();

  public void setTimestamp(URL url, long timestamp) {
    map.put(url,timestamp);
  }

  public long getTimestamp(URL url) {
    System.out.println("map: "+map);
    return map.getOrDefault(url,-1L);
  }

}

I have a lot of curiosity because of it does not pass the execution tests but it does pass the example tests. The example tests are:

import static org.junit.Assert.*;
import org.junit.Test;
import java.net.URL;

public class UrlMapTest {
  @Test
  public void testCodewars() throws Exception {
    UrlMap map = new UrlMap();
    URL url1 = new URL("http://www.codewars.com/");
    long time1 = 12345L;
    URL url2 = new URL("http://www.codewars.com/kata/url-timestamps/");
    long time2 = 67890L;
    map.setTimestamp(url1, time1);
    map.setTimestamp(url2, time2);
    assertEquals(time1, map.getTimestamp(url1));
    assertEquals(time2, map.getTimestamp(url2));
  }  

  @Test
  public void testNew() throws Exception {
    UrlMap map = new UrlMap();
    URL url1 = new URL("http://www.codewars.com/");
    URL url2 = new URL("http://www.codewars.com/kata/url-timestamps/");
    assertEquals(-1, map.getTimestamp(url1));
    assertEquals(-1, map.getTimestamp(url2));
  }
}

I will explain the difficulty as best as I can. The execution tests, create a "url1" with timestamp 12345L. Then, in the next tests, it creates a url1 without timestamp. So it would expect to get a -1, because of it should not have a timestamp stored, however it does have the initial timestamp, as the map is static.

As an image worths more than a thousand words: enter image description here

I think this code passes the example tests because of in each of the test methods a new UrlMap is being created. However, in the execution tests I suppose the exact same urlMap class is being reused.

To try to fix this issue I have read: How can I initialise a static Map? How to update a value, given a key in a hashmap? What is an efficient way to implement a singleton pattern in Java?

How could we store urls and timestamps with a singleton pattern?

EDIT: Following @JoakimDanielson answer we pass the test which previously was been discussed. However it times out, execution time is above 16000ms. How could we improve this code to pass it?

import java.net.URL;
import java.util.*;

public class UrlMap {

  private Map<URL,Long> map;

  public UrlMap(){
    map=new HashMap<URL,Long>();
  }

  public void setTimestamp(URL url, long timestamp) {
    map.put(url,timestamp);
  }

  public long getTimestamp(URL url) {
    return map.getOrDefault(url,-1L);
  }

}
Yone
  • 2,064
  • 5
  • 25
  • 56

1 Answers1

1

Just implement an ordinary class where the map is an instance variable and your tests will pass

public  class UrlMap {
    private Map<URL, Long> map;

    public UrlMap() {
        map = new HashMap<URL, Long>();
    }

    public void setTimestamp(URL url, long timestamp) {
        map.put(url, timestamp);
    }

    public long getTimestamp(URL url) {
        return map.getOrDefault(url, -1L);
    }

}
Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
  • Hello, @JoakimDanielson. We are not allowed to declare UrlMap as an enum because of it should be a static class in order to execute the given tests. Besides, we are not allowed to modify the execution tests which are the ones which the posted code does not pass. – Yone Feb 29 '20 at 08:16
  • 2
    @Enoy If you are doing homework with specific contrived requirements then you should clearly state so in your question so we don't have to waste our time trying to help you with answers that are incorrect because of those requirements. – Joakim Danielson Feb 29 '20 at 08:18
  • @Enoy I have posted a new answer – Joakim Danielson Feb 29 '20 at 08:29
  • Thanks @JoakimDanielson for your time, and for updating the answer. I have tried the answer you have written and it does pass some of the tests, however it times out (execution time is above 16000ms ) when input is 1000 or more urls. How could we make the code faster? I suppose it times out due to that it iterates through all of the map each time when getTimestamp is called. – Yone Feb 29 '20 at 09:32
  • @Enoy I have helped you with your issue, the performance thing is a different question – Joakim Danielson Feb 29 '20 at 12:25
  • @Enoy Just store a string representation in the map. It seems to work for me. https://imgur.com/a/kbeco8N – nice_dev Feb 29 '20 at 16:29