Java 功能收集和未经检查的警告

Java functional collection and unchecked warnings

我写了一个纯函数集合 class - 一个包又名 multiset - 它工作正常,但在 class 定义本身和使用,特别是在和使用 FBag.make 中。据我所知,问题主要是因为函数集合需要静态工厂方法而不是 public 构造函数,而静态方法无法访问泛型类型。

有没有一种优雅的方法可以避免这种情况,还是我必须硬着头皮接受这是一个类型擦除问题,然后抑制警告?

代码如下。 (我知道这个实现渐近效率低下。预计 N 会很小;如果发生变化,我将更改实现。)

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;
        }
    }
}

static 方法可以有自己的通用声明,您可以使用它从 Collection<T>T[]:

创建一个 Fbag<T>
public static <T> FBag<T> make(Collection<? extends T> c) {
    var p = EMPTY;
    for (var a : c) {
        p = p.add(a);
    }
    return p;
}

public static <T> FBag<T> make(T[] c, int from, int to) {
    var p = EMPTY;
    for (var i = from; i < to; i++) {
        p = p.add(c[i]);
    }
    return p;
}

对于 static 成员 EMPTY,我认为没有办法绕过使用原始类型。您可以在 Collections.EMPTY_LIST:

中看到相同的内容
@SuppressWarnings("rawtypes")
public static final List EMPTY_LIST = new EmptyList<>();

@SuppressWarnings("unchecked")
public static final <T> List<T> emptyList() {
    return (List<T>) EMPTY_LIST;
}

因此,您在这里所能做的就是取消警告:

@SuppressWarnings("rawtypes")
public static final FBag EMPTY = new FBag<>(null, null);

@SuppressWarnings("unchecked")
public static final <T> FBag<T> empty() {
    return (FBag<T>) EMPTY;
}

另一方面,对于 static 方法,您可以声明它们自己的通用类型变量。

public static <E> FBag<E> make(Collection<E> c) {
    FBag<E> p = empty ();
    for (E a : c) {
        p = p.add(a);
    }
    return p;
}

public static <E> FBag<E> make(E[] c, int from, int to) {
    FBag<E> p = empty ();
    for (int i = from; i < to; i++) {
        p = p.add(c[i]);
    }
    return p;
}

(我用显式声明替换了 var,因为我没有安装 Java 10,而且我不想 post 未经检查的代码)。