简体   繁体   English

从Java中的供应商枚举获取字符串值

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM