I have written a purely functional collection class - a bag aka multiset - and it works fine, but generates a number of warnings for unchecked assignment, both in the class definition itself and in use, particularly in and using FBag.make. As far as I can see, the problem arises primarily from the fact that functional collections want static factory methods instead of public constructors, and static methods cannot access the generic type.
Is there an elegant way to avoid this, or do I just have to bite the bullet, accept that this is a type erasure issue, and suppress the warnings?
Code follows. (I'm aware this implementation is asymptotically inefficient. N is expected to be small; if that changes, I will change the implementation.)
import java.util.Collection;
import java.util.Iterator;
public class FBag<E> implements Iterable<E> {
public static final FBag EMPTY = new FBag<>(null, null);
private final FBag<E> next;
private final E val;
private FBag(E val, FBag<E> next) {
this.val = val;
this.next = next;
}
public FBag<E> add(E val) {
return new FBag<>(val, this);
}
@Override
public Iterator<E> iterator() {
return new Iter<>(this);
}
public static FBag make(Collection c) {
var p = EMPTY;
for (var a : c) {
p = p.add(a);
}
return p;
}
public static FBag make(Object[] c, int from, int to) {
var p = EMPTY;
for (var i = from; i < to; i++) {
p = p.add(c[i]);
}
return p;
}
public FBag<E> remove(E val) {
if (this == EMPTY) {
return this;
}
if (this.val == val) {
return next;
}
return new FBag<>(this.val, next.remove(val));
}
private static class Iter<E1> implements Iterator {
private FBag<E1> p;
Iter(FBag<E1> p) {
this.p = p;
}
@Override
public boolean hasNext() {
return p != EMPTY;
}
@Override
public Object next() {
assert p != EMPTY;
var r = p.val;
p = p.next;
return r;
}
}
}