实现地图功能



我正在创建一个"SpecialList",需要实现映射函数。该列表应该是惰性的,并且只有在评估时才会产生值。

如果值还不可用,toString((将返回"?";否则返回值的字符串表示形式。

在需要内容时调用get((。如果该值已经可用,则返回该值;否则,计算该值并返回。对于相同的值,只应进行一次计算。

这是我的:

public <U> SpecialList<U> map(Function<T, U> mapper) {
if (!this.isAvailable) {
return new SpecialList<U>(this.supplier);
}
return new SpecialList<U>(mapper, value);
}
// private constructor
private SpecialList(CachedSupplier<T> s) {
this.supplier = s;
this.isAvailable = false;
}

然而,它告诉我,没有有效的构造函数,因为T不能转换为U。

SpecialList.java:65: error: no suitable constructor found for SpecialList(SpecialList<T>.CachedSupplier<T>)
return new SpecialList<U>(this.supplier);
^
constructor SpecialList.SpecialList(U) is not applicable
(argument mismatch; SpecialList<T>.CachedSupplier<T> cannot be converted to U)
constructor SpecialList.SpecialList(Supplier<U>) is not applicable
(argument mismatch; SpecialList<T>.CachedSupplier<T> cannot be converted to Supplier<U>)

"U"在返回时不是变成了t吗?

我该如何解决这个问题?对于方法级别的泛型类型,我仍然有点不清楚。但有人告诉我,我需要添加<我的地图方法。

以下是我的完整代码:

class SpecialList<T> {
class CachedSupplier<T> {
private Supplier<? extends T> supplier;
private T value;
boolean isAvailable;
public CachedSupplier(Supplier<? extends T> supplier) {
this.supplier = supplier;
}
public T get() {
if (!isAvailable) {
value = supplier.get();
isAvailable = true;
}
return value;
}
}
private CachedSupplier<T> supplier;
private T value;
boolean isAvailable;
private SpecialList(T value) {
this.value = value;
this.isAvailable = true;
}
private SpecialList(Supplier<T> s) {
this.supplier = new CachedSupplier<T>(s);
this.isAvailable = false;
}
private SpecialList(CachedSupplier<T> s) {
this.supplier = s;
this.isAvailable = false;
}
private <R> SpecialList(Function<T, R> mapper, T v) {
this.supplier = new CachedSupplier<T>(() -> mapper.apply(v));
this.isAvailable = false;
}
public static <T> SpecialList<T> of(T value) {
return new SpecialList<>(value);
}
public static <T> SpecialList<T> of(Supplier<T> supplier) {
return new SpecialList<>(supplier);
}
public <R> SpecialList<R> map(Function<? super T,? extends R> mapper) {
if (!this.isAvailable) {
return new SpecialList<>(this.supplier);
}
return new SpecialList<R>(mapper, value);
}
public T get() {
if(this.isAvailable) {
return this.value;
} else {
this.value = this.supplier.get();
this.isAvailable = true;
return this.value;
}
}
}

我对泛型类型等仍然有点困惑,所以如果有什么奇怪的地方/我可以改进,请告诉我!

感谢

根据您发布的代码,类SpecialList的一个构造函数中存在编译时错误。。。

private <R> SpecialList(Function<T, R> mapper, T v) {
this.supplier = new CachedSupplier<T>(() -> mapper.apply(v));
this.isAvailable = false;
}

首先,在您发布的代码中,内部类CachedSupplier中没有接受Function参数的构造函数,因此您需要添加一个具有以下签名的构造函数:

public <R> CachedSupplier(Function<T, R> mapper)

SpecialList构造函数的第二个问题是lambda表达式。接口Function中的抽象方法apply有一个参数,您的lambda表达式缺少该参数。因此构造函数代码应该是:

private <R> SpecialList(Function<T, R> mapper, T v) {
this.supplier = new CachedSupplier<T>((v) -> mapper.apply(v));
this.isAvailable = false;
}

问题是您的映射函数正在将SpecialList类型参数从T更改为R。但在编译器高亮显示的片段中,您仍然返回SpecialList。

你可以做的事情:

  1. 如果您不打算用map((函数更改元素的类型,请去掉R,并用Function<? super T,? extends T> mapper替换Function<? super T,? extends R> mapper。然而,通过这种方式,映射器将被完全省略,这可能不是所需的行为
  2. 否则,您应该将原始供应商和新映射器的组合传递到SpecialList构造函数中,如下所示:
return new SpecialList<R>(() -> {
T originalValue = this.supplier.get();
return mapper.apply(originalValue);
};

我认为您在SpecialListCachedSupplier中都检查isAvailable是做过头了。在我看来,在CachedSupplier中这样做并将SpecialList的成员减少到仅supplier就足够了(当值可用时,这只是一个值获取器,而不需要额外的昂贵评估(。在构造函数中,当需要时(即,当您还没有值时(,您可以确保supplier是缓存的。所以这是我的建议。进一步的注释直接在源代码中(现在编译时没有错误或警告(:

class SpecialList<T> {
static class CachedSupplier<R> implements Supplier<R> {
/* R is a priori an idependent parameter. If you call it T again, then you get a warning
* that the original T is hidden within the new nested class (though it wouldn't really matter here),
* as one doesn't need to refer to it. I made it static, as you don't need an instance to define it. */
private Supplier<? extends R> supplier;
private R value;
boolean isAvailable;
public CachedSupplier(Supplier<? extends R> supplier) {
this.supplier = supplier;
this.isAvailable = false;
}
@Override
public R get() {
if (!isAvailable) {
value = supplier.get();
isAvailable = true;
}
return value;
}
}
private Supplier<T> supplier;
private SpecialList(T value) {
/* in this case no lazy evaluation and no caching needed */
this.supplier = () -> value;
}
private SpecialList(Supplier<T> s) {
this.supplier = new CachedSupplier<T>(s);
}
private SpecialList(CachedSupplier<T> s) {
this.supplier = s;
}
private <R> SpecialList(Function<R, T> mapper, R v) {
/* This constructor is not needed anymore in my suggested code. 
* I left it simply, in order to show how to fix the type errors related to it. 
* if I understood correctly the intentions of this constructor,
* R and T have to be swapped w.r.t the original post.
* This is a constructor that uses an R-value and a mapper R->T to create a SpecialList<T> */
this.supplier = new CachedSupplier<T>(() -> mapper.apply(v));
}
public static <T> SpecialList<T> of(T value) {
return new SpecialList<>(value);
}
public static <T> SpecialList<T> of(Supplier<T> supplier) {
return new SpecialList<>(supplier);
}
public <R> SpecialList<R> map(Function<T, R> mapper) {
/* mapper is here different (opposite direction) than in the last of the constructors.
* Here we have an existing SpecialList containing a value of Type T which will be turned into a
* SpecialList containing a value of type R by applying a mapper T->R after getting the value from
* the original SpecialList */
return new SpecialList<R>(() -> mapper.apply(get()));
}
public T get() {
return this.supplier.get();
}
}

这个解决方案还没有处理toString()的实现。当您还想实现后者时,使SpecialList成为CachedSupplier的子类(具有额外的map和toString方法以及对isAvailable的直接访问(可能会更自然

最新更新