6

In Java LinkedHashSet is created with backing HashSet creating LinkedHashMap with following LinkedHashMap constructor

map = new LinkedHashMap<>(initialCapacity, loadFactor);

Now in LinkedHashMap, the above constructor in turn calls

 public LinkedHashMap(int initialCapacity, float loadFactor) {
    super(initialCapacity, loadFactor);
    accessOrder = false;
}

so is there any way to have a LinkedHashSet with accessOrder set to true? This can help create LRU cache implementation with LinkedHashSet.

Jyotirup
  • 2,882
  • 9
  • 30
  • 38

2 Answers2

3

LinkedHashSet doesn't support access order, since you are not accessing elements of a LinkedHashSet.

You add elements to the LinkedHashSet, and you can iterate over them in insertion order.

When you check if an element is a member of the LinkedHashSet, you are not accessing it. You check membership via boolean contains(Object o), calls map.containsKey(o) for the backing map. However, containsKey() doesn't affect the access order of the Map.

On the other hand, the get(Object key) method of LinkedHashMap does affect access order, but it is never used by LinkedHashSet.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • Actually, no. "put" is considered an access. The choice of the word "access" in the official docs seems to imply otherwise, and it is not obvious from the LinkedHashMap documentation, but several boring re-reads you'll see it, it's in there. – tekHedd Feb 20 '19 at 19:27
  • Just FYI: "Invoking the put or get method results in an access to the corresponding entry (assuming it exists after the invocation completes)." https://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html#LinkedHashMap(int,%20float,%20boolean) I assume that the implementors of (Linked)HashSet simply missed this, or it was changed after LinkedHashSet was implemented. – tekHedd Feb 20 '19 at 19:37
1

As you can see from the source code, a LinkedHashSet is backed by a LinkedHashMap with the accessOrder set to false.

Furthermore, there is no public constructor for LinkedHashSet to change the access order from insertion order to access order.

You could try this (just an example):

LinkedHashSet<E> set = (LinkedHashSet<E>) Collections.newSetFromMap(new LinkedHashMap<>(16, 0.75f, true));
Dsenese1
  • 1,106
  • 10
  • 18
  • OP wants to create a `LinkedHashSet` – Lino Dec 07 '17 at 14:15
  • I want to create an object of LinkedHashSet not LinkedHashMap – Jyotirup Dec 07 '17 at 14:16
  • agreed, hence the question if there is any hack to create LRU cache using LinkedHashSet in Java – Jyotirup Dec 07 '17 at 14:21
  • Can you provide a link to the source code? I can't find it. – Tim Biegeleisen Dec 07 '17 at 14:22
  • @TimBiegeleisen http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/LinkedHashSet.java – Dsenese1 Dec 07 '17 at 14:38
  • @Dsenese1 this will not work, as the returned Set is almost certainly not an instance of `LinkedHashSet` – Hulk Dec 11 '17 at 23:04
  • It could have worked! :) You could override the internal map in the constructor, but no, "map" is private, not protected. Basically, the Java implementors have ensured that it is absolutely impossible to create an access-ordered LinkedHashSet without completely reimplementing it. – tekHedd Feb 20 '19 at 19:25