找到一种使用流生成地图的更好方法

时间:2017-05-26 17:22:31

标签: java java-stream

我有这个枚举:

public enum FieldType
{
    INTEGER
    {
        @Override
        Set<Class<?>> getTypes()
        {
            return new HashSet<>(Arrays.asList(int.class, Integer.class));
        }
    },
    LONG
    {
        @Override
        Set<Class<?>> getTypes()
        {
            return new HashSet<>(Arrays.asList(long.class, Long.class));
        }
    };
    // More types...

    private static final Map<Class<?>, FieldType> _fieldTypes;

    static
    {
        _fieldTypes = Stream.of(values()).
            flatMap(ft -> ft.getTypes().stream()).
            collect(toMap(t -> t,
                t -> Stream.of(values()).
                filter(ft -> ft.getTypes().contains(t)).
                findAny().
                get()
            ));
    }

    abstract Set<Class<?>> getTypes();

    // More methods...
}

正如您所看到的,我在此枚举中有一个映射,它将类型映射到字段类型。我设法使用流在静态块中填充此映射。它有效,但我认为这可能是一种更好,更简洁的方法。我可以将 toMap 方法的第二个参数放在一个新方法中,但我认为我只是将复杂性转移到其他地方。

您是否有关于如何以简单方式实现同​​样目标的建议?

2 个答案:

答案 0 :(得分:3)

您可以在展平时插入Entry

_fieldTypes = Stream.of(values())
    .flatMap(ft -> ft.getTypes().stream() // for every Class<?> of a FieldType...
        .map(cls -> new SimpleEntry<>(cls, ft))) // get Entry<Class<?>, FieldType>
    .collect(toMap(Entry::getKey, Entry::getValue));

正如bradimus建议的那样,您还可以使用collectingAndThenCollections.unmodifiableMap根据toMap的结果创建不可修改的地图:

.collect(collectingAndThen(toMap(Entry::getKey, Entry::getValue),
    Collections::unmodifiableMap));

答案 1 :(得分:1)

稍微简单一点:

Map<Class<?>, FieldType> map = Arrays.stream(FieldType.values())
                .flatMap(ft -> ft.getTypes().stream()
                      .map(cl -> new AbstractMap.SimpleEntry<>(cl, ft)))
                .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

显然你可以把它包装成Collections.unmodifiableMap