0

I have a filter class wherein the user must declare the type (e.g. Filter<Double>, Filter<Float> etc). The class then implements a moving average filter so objects within the class must be added. My question is how to do this? I'm sorry if the answer is simple but I've muddled myself up by thinking about it too much I think :p.

public abstract class FilterData<T>
{
private final List<T> mFilter;
private T mFilteredValue; // current filtered value
protected Integer mSize = 10;
private T mUnfilteredValue; // current unfiltered value

public FilterData()
{
    mFilter = new ArrayList<T>();
}

public FilterData(int size)
{
    mSize = size;
    mFilter = new ArrayList<T>(mSize);
}

public abstract T add(final T pFirstValue, final T pSecondValue);

@SuppressWarnings("unchecked")
public T filter(T currentVal)
{
    T filteredVal;
    mUnfilteredValue = currentVal;
    push(currentVal);

    T totalVal = (T) (new Integer(0));
    int numNonZeros = 1;
    for (int i = 0; i < mFilter.size(); ++i)
    {
        if (mFilter.get(i) != (T) (new Integer(0)))
        {
            ++numNonZeros;
            T totalValDouble = add(mFilter.get(i), totalVal);
            totalVal = totalValDouble;
        }
    }
    Double filteredValDouble = (Double) totalVal / new Double(numNonZeros);
    filteredVal = (T) filteredValDouble;
    mFilteredValue = filteredVal;
    return filteredVal;
}

public T getFilteredValue()
{
    return mFilteredValue;
}

public List<T> getFilterStream()
{
    return mFilter;
}

public T getUnfilteredValue()
{
    return mUnfilteredValue;
}

public void push(T currentVal)
{
    mFilter.add(0, currentVal);
    if (mFilter.size() > mSize)
        mFilter.remove(mFilter.size() - 1);
}

public void resizeFilter(int newSize)
{
    if (mSize > newSize)
    {
        int numItemsToRemove = mSize - newSize;
        for (int i = 0; i < numItemsToRemove; ++i)
        {
            mFilter.remove(mFilter.size() - 1);
        }
    }
}
}

Am I right to include the abstract Add method and if so, how should I extend the class correctly to cover primitive types (e.g. Float, Double, Integer etc.) Thanks Chris

EDIT:

Apologies for being unclear. This is not homework I'm afraid, those days are long behind me. I'm quite new to Java having come from a C++ background (hence the expectation of easy operator overloading). As for the "push" method. I apologise for the add method in there, that is simply add a value to a list, not the variable addition I was referring to (made a note to change the name of my method then!). The class is used to provide an interface to construct a List of a specified length, populate it with variables and obtain an average over the last 'x' frames to iron out any spikes in the data. When a new item is added to the FilterData object, it is added to the beginning of the List and the last object is removed (provided the List has reached the maximum allowed size). So, to provide a continual moving average, I must summate and divide the values in the List. However, to perform this addition, I will have to find a way to add the objects together. (It is merely a helper class so I want to make it as generic as possible). Does that make it any clearer? (I'm aware the code is very Mickey Mouse but I wanted to make it as clear and simple as possible).

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
Sonoman
  • 3,379
  • 9
  • 45
  • 61
  • The question is unclear: In what context do you need this? Could you give your complete requirements? How is the filter supposed to be used? What does e.g. `push` do? – sleske Oct 19 '10 at 09:49
  • Please provide a working (compiling&running) code sample, which shows how far you got. Then explain where your problem is, then we can probably help :-). – sleske Oct 19 '10 at 09:49
  • I have a problem in statement such as `T totalVal = (T) (new Integer(0));`. If `T` is `Double` then you have `Double totalVal = (Double) (new Integer(0));` which will break your code...hence why I don't understand what your abstract class does. – Buhake Sindi Oct 19 '10 at 10:35
  • Sorry that was most definitely a brain fart moment when I was trying all sorts of casting. That shouldn't be there! – Sonoman Oct 19 '10 at 11:04

1 Answers1

1

What you're trying to do is create a Queue of Number objects with a fixed size, over which you want to calculate an average. With the trivial situation that you have size = 2 and store two integers 1 & 2 you have an average of 1.5 so its reasonable to set the return type of your filter method to double.

You can then write this code similar to this

public abstract class FilterData<T extends Number> {
    private final Queue<T> mFilter = new LinkedList<T>();
    protected Integer mSize;

    public FilterData() {
        this(10);
    }

    public FilterData(int size) {
        mSize = size;
    }

    public double filter(T currentVal) {
        push(currentVal);

        double totalVal = 0d;
        int numNonZeros = 0;
        for (T value : mFilter) {
            if (value.doubleValue() != 0) {
                ++numNonZeros;
                totalVal += value.doubleValue();
            }
        }

        return totalVal / numNonZeros;
    }

    public void push(T currentVal) {
        mFilter.add(currentVal);
        if (mFilter.size() > mSize)
            mFilter.remove();
    }

    public void resizeFilter(int newSize) {
        if (mSize > newSize) {
            int numItemsToRemove = mSize - newSize;
            for (int i = 0; i < numItemsToRemove; ++i) {
                mFilter.remove();
            }
        }
        mSize = newSize;
    }
}

You should note that this isn't thread safe.

Jon Freedman
  • 9,469
  • 4
  • 39
  • 58