-1

I need a LinkedHashSet with a fixed size n so that when we insert the n+1th element , the first element is automatically removed and new element is inserted at the end.

LinkedHashSet <Integer> = new LinkedHashSet <Integer> () ;

How should I implement the constructor to fix the size ?

akisonlyforu
  • 322
  • 2
  • 13
  • 1
    You'll have to create a sub class of LinkedHashSet and implement that logic yourself. – Eran Mar 08 '18 at 10:40
  • 1
    There is not implement that does that, you need to implement LinkedHashSet and override some methods like "add" – azro Mar 08 '18 at 10:41
  • @Eran I am just a beginner. Please help . – akisonlyforu Mar 08 '18 at 10:41
  • in the constructor, just value a maxLength field ; it's `HashSet.add` you need to override to implement your logic (e.g. call super.add, then if size() > maxLength remove first element) – Aaron Mar 08 '18 at 10:45
  • 1
    Is there a specific reason for `LinkedHashSet`? Following Aaron's suggestion is not that difficult, but be aware of `LinkedHashSet`'s way of handling adding elements that are already present (spoiler: the insertion order is **not** updated). I don't know what you want to happen in that case, but I have the impression you would do better with a `LinkedList` or some other `Queue` implementation as a base class. – Malte Hartwig Mar 08 '18 at 13:03

2 Answers2

4

By default LinkedHashSet is not capable for this. You can read about the reasons here: https://stackoverflow.com/a/7632240/9337345

The only thing what you can do is to create an inherited LinkedHashSet which is responsible for the fixed size as you desire.

For example:

import java.util.Iterator;
import java.util.LinkedHashSet;

public class MyLinkedHashSet<T> extends LinkedHashSet<T> {
    private long maxSize;

    public MyLinkedHashSet(long maxSize) {
        this.maxSize = maxSize;
    }

    @Override
    public boolean add(T item) {
        if(size() == maxSize) {
            removeFirst();
        }
        return super.add(item);
    }

    private void removeFirst() {
        if(size() > 0) {
            Iterator<T> iterator = iterator();
            T item = iterator.next();
            remove(item);
        }
    }

    public static void main(String[] args) {
        LinkedHashSet<Integer> set = new MyLinkedHashSet<>(3);
        set.add(1);
        set.add(2);
        set.add(3);
        set.add(4);
        System.out.println(set);    // [2, 3, 4]
        set.clear();
        System.out.println(set);    // []
        set.addAll(Arrays.asList(1, 2, 3, 4, 5));
        System.out.println(set);    // [3, 4, 5]
    }
}

I hope this is what you meant.

Csaba
  • 421
  • 4
  • 8
0

To implement a fixed size LinkedHashSet in java, we are going to do the following:

  1. According to the source of [LinkedHashSet](new LinkedHashMap(16, .75f)), its based on a implementation of a LinkedHashMap
  2. After looking through the documentation of LinkedHashMap, we see that it has a method called [removeEldestEntry](https://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html#removeEldestEntry(java.util.Map.Entry)), that we can use for our purpose of automatic removing

Eventually, we will get to the following implementation:

Set<Integer> unnamedVariable = Collections.newSetFromMap(new LinkedHashMap<Integer, Boolean>() {

    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, Boolean> eldest) {
        return this.size() > n;
    }

});

This gives us a high performance solution, compared to manually removing the last entry using iterators, as we re-using existing functionality of the backend layer.

Ferrybig
  • 18,194
  • 6
  • 57
  • 79