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 未经检查的代码)。
我写了一个纯函数集合 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 未经检查的代码)。