[英]Get String values from supplier enum in java
i have an enum implementing a supplier, eg: 我有一个实施供应商的枚举,例如:
public enum QUERY_FIELD implements Supplier<String> {
PRODUCT_TYPE("ProductType"),
MIN_NUMBER_OF_PARTS("MinNumberOfParts"),
MAX_NUMBER_OF_PARTS("MaxNumberOfParts");
private final String id;
QUERY_FIELD(final String id) {
this.id = id;
}
@Override
public final String get() {
return id;
}
}
i have different utility methods which can find the enum i search for depending on the query 我有不同的实用程序方法,可以根据查询找到要搜索的枚举
public static <T extends Enum<T> & Supplier<String>> Optional<T> findById(final Class<T> enumClass, final String id) {
return Arrays.stream(enumClass.getEnumConstants()).filter(p -> id.equalsIgnoreCase(p.get())).findFirst();
}
public static <T extends Enum<T> & Supplier<? extends Number>> Optional<T> findById(final Class<T> enumClass, final Number id) {
return Arrays.stream(enumClass.getEnumConstants()).filter(p -> id.equals(p.get())).findFirst();
}
now i want to adapt this idea to create a utility method that just returns the list of all values depending on the suppliers type. 现在,我想采用这种想法来创建一个实用程序方法,该方法仅根据供应商类型返回所有值的列表。
i tried it with: 我尝试了:
public static <T extends Enum<T> & Supplier<? extends String>> List<String> getValueList(final Class<T> enumClass) {
return Arrays.stream(enumClass.getEnumConstants()).map(Supplier::get).collect(Collectors.toList());
}
or 要么
public static <U, T extends Enum<T> & Supplier<? extends U>> List<U> getValueList(final Class<T> enumClass) {
return Arrays.stream(enumClass.getEnumConstants()).map(Supplier::get).collect(Collectors.toList());
}
which both compile but do not work, how should i build this method? 两者都可以编译但不起作用,我应该如何构建此方法?
I guess that the problem you are experiencing in the runtime issue described in Enum, interfaces and (Java 8) lambdas: code compiles but fails at runtime; 我猜您在枚举,接口和(Java 8)lambda中描述的运行时问题中遇到的问题:代码可以编译,但在运行时失败; is this expected?
这是预期的吗? and is cause by a known bug in Java-8 https://bugs.openjdk.java.net/browse/JDK-8141508 .
并且是由Java-8 https://bugs.openjdk.java.net/browse/JDK-8141508中的一个已知错误引起的。
The problem is with the intersection bound Enum<T> & Supplier<? extends String>
问题在于交集绑定
Enum<T> & Supplier<? extends String>
Enum<T> & Supplier<? extends String>
. Enum<T> & Supplier<? extends String>
。 It seems that the compiler generates code where the second element in the intersection is lost and so in run-time it is as if you tried to use for the lambda an object of a class that is not guaranteed to implement Supplier
but just Enum
. 似乎编译器会生成代码,使交点中的第二个元素丢失,因此在运行时,就好像您试图为lambda使用一个不能保证实现
Supplier
而是仅实现Enum
的类的对象一样。
Since getEnumConstant
is available for all Class<X>
regardless wether X is an enum or not you could simply discard that part from the param-type bound and leave it as Supplier<String>
: 由于
getEnumConstant
对所有Class<X>
都可用,无论X是否为枚举,您都可以从param-type绑定中丢弃该部分,并将其保留为Supplier<String>
:
import java.util.function.*;
import java.util.*;
import java.util.stream.*;
enum Test implements Supplier<String> {
A, B, C;
public String get() { return name(); }
}
class Main {
public static <T extends Supplier<String>> List<String> getValueList(final Class<T> enumClass) {
return Arrays.stream(enumClass.getEnumConstants())
.map(Supplier::get)
.collect(Collectors.toList());
}
public static final void main(String[] args) {
System.out.println(getValueList(Test.class).stream()
.collect(Collectors.joining(",")));
}
}
However the downside of this is that the compiler won't fail if someone provide a class that is not an enum.... in order to prevent that you can keep the intersection bound and add an extra map
that explicitly cast the enum constants into suppliers: 但是,这样做的缺点是,如果有人提供的不是枚举的类,则编译器不会失败。...为了防止您可以保留交集并添加额外的
map
,该map
将枚举常量显式转换为供应商:
public static <T extends Enum<T> & Supplier<String>> List<String> getValueList(final Class<T> enumClass) {
return Arrays.stream(enumClass.getEnumConstants())
.map(x -> (Supplier<String>) x) // not needed to compile but needed for run-time.
.map(Supplier::get)
.collect(Collectors.toList());
}
UPDATE UPDATE
There is a even better solution for the second alternative. 第二种选择还有一个更好的解决方案。 You can do the cast just one outside the stream, that should save you compute:
您可以只在流外部进行转换,这可以节省您的计算:
public static <T extends Enum<T> & Supplier<String>> List<String> getValueList(final Class<T> enumClass) {
final Class<Supplier<String>> asSupplierClass = enumClass;
return Arrays.stream(asSupplierClass.getEnumConstants())
.map(Supplier::get)
.collect(Collectors.toList());
}
I have not tested it, let me know whether it works. 我尚未对其进行测试,请让我知道它是否有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.