简体   繁体   中英

Set ordered by “add() count”

I'm trying to implement a Set which is ordered by the count of additions like this:

public class App {
    public static void main(String args[]) {
        FrequencyOrderedTreeSet<String> set = new FrequencyOrderedTreeSet<String>();
        set.add("bar");
        set.add("foo");
        set.add("foo");
        Iterator<String> i = set.iterator();
        while (i.hasNext()) {
            System.out.print(i.next());
        }
        // prints "foobar"
    }
}

I've created a protected class FrequencyOrderedTreeSet.Element which implements Comparable and has a T entry and an int frequency property and extended TreeSet<FrequencyOrderedTreeSet.Element> with FrequencyOrderedTreeSet<T> and overrode the compareTo and equals methods on the Element .

One problem is that I can't override the add() method because of type erasure problems and also I can't call instanceof Element in the equals method, because in case object given to it is an Element, I have to compare their entries, but if it's not, I have to compare the object itself to this.entry .

In the add method I create a new element, find the element with the same entry in the set, set the frequency on the new element to "old+1", remove the old one and add the new one. I'm not even sure this is the best way to do this or if it would work even because the other problems I described.

The question is: what's the best way to implement such data structure? In case I'm somehow on the right track - how can I circumvent the problems I've mentioned above?

Here's a basic implementation. It's not the most optimal and will take some more work if you want to implement the full Set interface.

public class FrequencySet<T> implements Iterable<T>
{
    private TreeSet<T> set;
    private HashMap<T, Integer> elements = new HashMap<T, Integer>();

    public FrequencySet()
    {
        set = new TreeSet<T>(new Comparator<T>()
        {
            public int compare(T o1, T o2)
            {
                return elements.get(o2)-elements.get(o1);
            }
        });
    }

    public void add(T t)
    {
        Integer i = elements.get(t);
        elements.put(t, i == null ? 1 : i+1);
        set.remove(t);
        set.add(t);
    }

    public Iterator<T> iterator() {return set.iterator();}

    public static void main(String [] args)
    {
        FrequencySet<String> fset = new FrequencySet<String>();

        fset.add("foo");
        fset.add("bar");
        fset.add("foo");
        for (String s : fset)
            System.out.print(s);
        System.out.println();

        fset.add("bar");
        fset.add("bar");
        for (String s : fset)
            System.out.print(s);
    }
}

The key is in the add method. We change the counter for the given object (which changes the relation order), remove it from the backing set and put it back in.

This works the other way (count is increased when you use GET)

@SuppressWarnings("rawtypes")
final class Cache implements Comparable {
    private String key;
    private String value;
    private int counter;

    public String getValue() {
        counter++;
        return value; 
    }
    private void setValue(String value) { this.value = value; }

    public String getKey() { return key; }
    private void setKey(String key) { this.key = key; }

    public int getCounter() { return counter; }
    public void setCounter(int counter) { this.counter = counter; }

    public Cache(String key, String value) {
        this.setKey(key);
        this.setValue(value);
        setCounter(0);
    }

    @Override
    public int compareTo(Object arg0) {
        if(!(arg0 instanceof Cache)) {
            throw new ClassCastException();
        }   
        return this.getCounter() - ((Cache) arg0).getCounter();
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM