问题
I need to do :
Dictionary cache;
cache = new Hashtable();
this.getDocument().putProperty("imageCache", cache);
Then I have a method who does :
cache.put(url, picture);
Where picture is an Image object. I create this way :
public Image getSmiley(String smileyName) {
BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
ImageIcon myicon = new ImageIcon(getClass().getResource("/ola/smileys/" + smileyName + ".png"));
myicon.paintIcon(null, g, 0, 0);
return img;
}
I have run a profiling and I have seen that when I call this method "put", the application slows down incredibly. What could be the reason ?
Thank you very much.
Best Regards
回答1:
I suspect that this might be due to your using the URL
class as the key type.
The javadoc for URL.equals(Object)
says this:
Two URL objects are equal if they have the same protocol, reference equivalent hosts, have the same port number on the host, and the same file and fragment of the file.
Two hosts are considered equivalent if both host names can be resolved into the same IP addresses; else if either host name can't be resolved, the host names must be equal without regard to case; or both host names equal to null.
Since hosts comparison requires name resolution, this operation is a blocking operation.
When you use a URL
instance as a key in a map, then each time a key is compared to a different one you could be triggering a DNS lookup ... and that could take a long time.
If this is your problem, then you need to change the key type of the map to String
or URI
... or something else that doesn't have an expensive equals(Object)
method.
回答2:
I'm just giving a guess, but I think it might be due to the underlying hash structure having to be resized.
When you're 'put'ing a value into a hashtable, once it reaches a certain capacity, it has to expand the underlying array -- otherwise, you end up getting a lot of hash collisions. However, this array expansion operation is expensive -- it has to allocate space for the new array and copy values into the new array.
One suggestion would be to give a reasonable initial capacity to the Hashtable constructor.
回答3:
How much is "incredibly"?
I can't guarantee how much of an improvement it would make, but try using HashMap
instead of Hashtable
. HashMap
is not synchronized, which I'm guessing you don't need here, since everything should be done on a single thread for your UI anyway.
See Differences between HashMap and Hashtable? for some additional details of the differences between these.
回答4:
I assume you're trying to pre-load a cache so you can do something like showing local images in a JEditorPane.
I just had this problem & Stephen C correctly identified the issue.
Originally I was using urls which started with http://, I switched to urls starting with file:/ and it fixed the problem.
These urls are never actually connected to, they're just unique keys for the hash so just making sure the URL object knows it doesn't need a DNS lookup to resolve them is enough, & changing to the file protocol does that.
来源:https://stackoverflow.com/questions/8426139/java-hashtable-put-method-slow-down-my-application