繁体   English   中英

Java 8流中间映射/收集到具有2个值的流

[英]Java 8 streams intermediary map/collect to a stream with 2 values

想象一下,我有以下工作lambda表达式:

        Map<Field, String> fields = Arrays.stream(resultClass.getDeclaredFields())
            .filter(f -> f.isAnnotationPresent(Column.class))
            .collect(toMap(f -> {
                f.setAccessible(true);
                return f;
            }, f -> f.getAnnotation(Column.class).name()));

我想在filter语句之前创建一个具有2个值的流。 因此,我想进行映射,但仍然保留原始值。 我想实现以下目标:

        this.fields = Arrays.stream(resultClass.getDeclaredFields())
            //map to <Field, Annotation> stream
            .filter((f, a) -> a != null)
            .collect(toMap(f -> {
                f.setAccessible(true);
                return f;
            }, f -> a.name()));

Java 8流是否可能? 我看过collect(groupingBy()),但仍然没有成功。

您需要类似Pair东西,其中包含两个值。 您可以编写自己的代码,但这是一些重新利用AbstractMap.SimpleEntry代码:

     Map<Field, String> fields = Arrays.stream(resultClass.getDeclaredFields())
            .map(f -> new AbstractMap.SimpleEntry<>(f, f.getAnnotation(Column.class)))
            .filter(entry -> entry.getValue() != null)
            .peek(entry -> entry.getKey().setAccessible(true))
            .collect(toMap(Map.Entry::getKey, entry -> entry.getValue().name()));

您可以在collect操作期间一次性完成整个操作,而无需配对类型:

Map<Field, String> fields = Arrays.stream(resultClass.getDeclaredFields())
    .collect(HashMap::new, (m,f) -> {
        Column c=f.getAnnotation(Column.class);
        if(c!=null) {
            f.setAccessible(true);
            m.put(f, c.name());
        }
    }, Map::putAll);

不过,对我来说,将不会合并的两个操作分开看起来更干净:

Map<Field, String> fields = Arrays.stream(resultClass.getDeclaredFields())
    .collect(HashMap::new, (m,f) -> {
        Column c=f.getAnnotation(Column.class);
        if(c!=null) m.put(f,c.name());
    }, Map::putAll);

AccessibleObject.setAccessible(
    fields.keySet().stream().toArray(AccessibleObject[]::new), true);

此解决方案对具有批注的字段进行两次迭代,但是由于此方法仅执行一次安全检查,而不是对每个字段进行一次检查,因此它可能仍然胜过所有其他解决方案。

通常,除非确实存在性能问题,否则您不应该尝试进行优化;如果这样做,则应该进行度量,而不要猜测运营成本。 结果可能令人惊讶,并且对数据集进行多次迭代不一定很糟糕。

@Peter Lawrey:我尝试了使用中间地图的建议。 它现在可以工作,但不是很漂亮。

this.fields = Arrays.stream(resultClass.getDeclaredFields())
            .collect(HashMap<Field, Column>::new, (map, f) -> map.put(f, f.getAnnotation(Column.class)), HashMap::putAll)
            .entrySet().stream()
            .filter(entry -> entry.getValue() != null)
            .peek(entry -> entry.getKey().setAccessible(true))
            .collect(toMap(Map.Entry::getKey, entry -> entry.getValue().name()));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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