簡體   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